App de Servicios para Consorcios

Aplicación móvil dirigida a miembros de un consorcio, propietarios y/o inquilinos, con servicios para la reserva de amenities y presentación de liquidaciones de expensas.

Instancias de BIMS

BIMS puede distribuirse bajo dos modelos de negocio:

  1. Software as a Service

  2. Licenciamiento Perpétuo

Las cuentas de BIMS bajo el modelo de Software as a Service emplean la misma URL: https://bims.app.

Las instancias de BIMS de cuentas bajo el modelo de licenciamiento perpetuo pueden pueden implementarse en otros hosts. Ejemplo: https://beta.bims.app.

Es por ese motivo que la aplicación móvil debe permitirle al usuario configurar el host ($HOST) de su instancia de BIMS y la opción predeterminada debe ser la de SaaS: https://bims.app.

Para las cuentas SaaS, se debe indicar en el login también el código de empresa ($TENANT_CODE). Este código es alfanumérico. Ej.: "prueba24".

Se recomienda que las casillas de $HOST y de $TENANT_CODE, al no haber necesidad de cambiarlas en la app en un escenario normal, se configuren en una pantalla distinta del login.

Entidades

Propiedades

Las Propiedades [Estate] representan unidades inmobiliarias como casas o departamentos.

Consorcios

Los Consorcios [EstatesGroup] o Codominios son en esencia un conjunto de Propiedades. Representan edificios, barrios cerrados o cualquier estructura organizada de Propiedades.

Amenities

Los Amenities [Amenity] son espacios u otros recursos comunes en un Consorcio. Ejemplo: Quinchos, Piscinas, Canchas, Lavarropas.

Usuarios

Los Usuarios [User] son individuos que harán uso de la app. Los Usuarios están relacionados a una o más Propiedades en uno de dos roles por cada Propiedad: Propietario o Inquilino. Los Usuarios se crean en BIMS como usuarios del sistema con permisos específicos, a través del módulo de Bienes Raíces desde la ficha de una Propiedad.

A diferencia de los Usuarios regulares, los Usuarios para esta aplicación tienen definido el atriibuto User.account_type = 're'.

Login

Para hacer login en BIMS se requiere de un nombre de usuario ($USERNAME) una contraseña ($PASSWORD) y en el caso de tratarse de una cuenta de SaaS: el $TENTANT_CODE.

Endpoint para Inicio de Sesión

POST https://$HOST/api/users/login

Request Body

NameTypeDescription

user*

String

Nombre de Usuario

password*

String

Hash MD5 de la Contraseña

tenant

String

Código de Tenant

account_type

String

Tipo de Cuenta = "re"

{
    status: "ok",
    code: "200",
    data: {
        User: {
            id: 1,
            login: "demo",
            name: "Cuenta de Demo",
            ...
        },
        Group: {
            id: 1,
            name: "Administradores",
            full: true
            ...
        },
        Session {
            id: "vsknhtsefpt9pmr4pusgtgvdm3",
            expire: "2023-11-01 10:00:00",
            current_timestamp: "2023-11-01 08:00:00",
            ...
        }
    }
}

Ejemplo de Login en cURL

curl --include \
     --request POST \
     --header "Content-Type: application/json" \
     --data-binary "{
          \"user\": \"usuario2\",
          \"password\": \"2fb6c8d2f3842a5ceaa9bf320e649ff0\",
          \"tenant\": \"test123\",
          \"account_type\": \"re\",
     }" \
'https://bims.app/api/users/login?parse_perms=1';

Login según Tipo de Instancia de BIMS

Si se accede a una cuenta de tipo SaaS (1), el host será siempre https://bims.app y para identificar la instancia de BIMS se deberá indicar el código de empresa en el campo "tenant" en el login.

Si se accede a una cuenta de tipo Licenciamiento Perpetuo (2), el host será distinto de https://bims.app, y el mismo deberá ser indicado por el usuario.

En un escenario normal, el usuario definirá el código de empresa (para una cuenta SaaS) o la URL del host propio (para una cuenta de licanciamiento perpetuo) una sola vez; por eso se recomienda:

  1. Unificar el campo URL de Host y Código de Empresa en un mismo campo en el formulario.

  2. Mostrar este campo solo en el primer login, y luego ocultarlo y mostrarlo en un modo de visualización avanzada.

Ejemplo:

Manejo de Sesiones

El Id de Sesión

En la respuesta del API a un login existoso, se retorna el Id de la sesión ($SESSION_ID) en el atributo: data.Session.id.

La aplicación debe guardar el valor $SESSION_ID y pasar a las siguientes consultas que haga al API en el argumento de la URL: "sid".

Ejemplo de uso en cURL

Suponiendo que el valor de $SESSION_ID = 7cr7cn9m6k598mv7gdvag2vrq7.

curl "https://bims.app/api/products?sid=7cr7cn9m6k598mv7gdvag2vrq7&company=1&limit=2"

Vigencia de la Sesión

Las sesiones son temporales. En la respuesta al login exitoso, el campo data.Session.expire se indica la fecha de expiración de la sesión, mientras que en el campo data.Session.current_timestamp se indica la marca de tiempo actual como referencia.

Se recomienda actualizar períodicamente el $SESSION_ID con un nuevo login en background y no exigirle al usuario un nuevo login hasta que el mismo cierre su sesión.

Rol del Usuario

Como se ha indicado antes, el Usuario puede estar asociado a una o más Propiedades con uno de los sigiuientes dos roles por Propiedad: Propietario o Inquilino. Estas relaciones, con sus respectivos roles, se indican en la respuesta del login en el atributo data.UsersEstate. Ejemplo:

{
    "status": "ok",
    "code": "200",
    "data": {
        "User": {
            "id": "316",
            "name": "Tony Stark",
            ...
        },
        "UsersEstate": [
            {
                "id": "17",
                "user_id": "316",
                "estate_id": "2",
                "role": "tenant",
                "Estate": {
                    "id": "2",
                    "name": "Departamento A1",
                    "estates_group_id": "1"
                }
            }
        ],
        ...
    }
}

Edición de Perfil Propio

El usuario debe tener la posibilidad de cambiar su contraseña, su nombre de usuario, su dirección de e-mail o su número telefónico. Para tal efecto, utilizar el endpoint "api/users/me". Ejemplo:

curl --include \
     --request POST \
     --header "Content-Type: application/json" \
     --data-binary "{
		\"password\": \"nuevopass\"
}" \
'https://beta.bims.app/api/users/me?sid=qfq2rqi5fnepd56qpoinven6m1';

En el ejemplo de arriba estamos actualizando la contraseña del usuario actual (el correspondiente al sid indicado) a "nuevopass". Si el resultado es existoso, BIMS retornará los datos actualizados del usuario. Ejemplo:

{
    "code": "200",
    "status": "ok",
    "data": {
        "User": {
            "id": "38",
            "name": "Fernando",
            "login": "fernando-propietario",
            "password": "cc5e214c2c6daf2af2055712905e1c99"
            ...

Si ha ocurrido un error, BIMS retornará un status: 'error'. Ejemplo:

{
    "code": "405",
    "status": "error",
    "message": "No hay argumentos de entrada",
    "last_update": "2024-03-17 18:57:13"
}

Consorcios

El endpoint del API para listar los Consorcios es "estates_groups". Ejemplo de consulta:

curl 'https://beta.bims.app/api/estates_groups/index?sid=2fb6c8d2f3842a5ceaa9bf320e649ff0&company=1';

Indicar en las consultas siempre el valor sid (recibido en la respuesta del login en data.Session.id) y company_id (indicado en la respuesta del login en data.User.company_id).

Amenities

Para consultar la lista de Amenities de un Consorcio, utilice el endpoint "amenities" e indique el Id del Consorcio en la URL con el argumento: states_group_id. Ejemplo:

curl 'https://beta.bims.app/api/amenities/index?estates_group_id=1&sid=2fb6c8d2f3842a5ceaa9bf320e649ff0&company=1';

Reservas de Amenities

Estructura de Datos

La tabla de reserva de amenities es "amenity_bookings" y cuenta con los siguientes campos:

CampoDescripciónTipo de Dato

id

Id de la Reserva

BIGINT

amenity_id

Id del Amenity

BIGINT

user_id

Id del Usuario titular de la reserva

BIGINT

start_date

Fecha y Hora de Inicio de la Reserva

TIMESTAMP

end_date

Fecha y Hora de Fin de la Reserva

TIMESTAMP

status

Estado de la Reserva (pending, confirmed, declined)

VARCHAR

auth_user_id

Id del Usuario que Autorizó / Rechazó la Reserva

BIGINT

authorized

Fecha y Hora de Autorización / Rechazo de la Reserva

TIMESTAMP

created

Fecha y Hora de Creación de la Reserva

TIMESTAMP

modified

Fecha y Hora de Última Modificación de la Reserva

TIMESTAMP

notes

Observaciones

TEXT

Consulta de Reservas

Para consultar las Reservas de Amenities existentes, ejecute un GET al endpoint "amenity_bookings". Puede indicar los siguientes argumentos en la URL:

ArgumentoDescripciónTipo de Dato

amenity_id

Id del Amenity

Entero Largo

from

Inicio del Rango de Fechas de la Consulta (Default: ahora).

Timestamp (YYYY-mm-dd HH:ii)

to

Fin del Rango de Fechas de la Consulta

Timestamp (YYYY-mm-dd HH:ii)

Ejemplo:

curl 'https://beta.bims.app/api/amenities/index?amenity_id=5&sid=2fb6c8d2f3842a5ceaa9bf320e649ff0&company=1';

Reservas de Amenities

Estructuras de Datos

AmenityBooking: Reserva

CampoDescripciónTipo de Dato

amenity_id

Id del Amenity

Entero Largo

start_date

Fecha y Hora de Inicio de la Reserva

Timestamp (YYYY-mm-dd HH:ii)

end_date

Fecha y Hora de Fin de la Reserva

Timestamp (YYYY-mm-dd HH:ii)

notes

Observaciones

TEXT

AmenityBookingGuest: Invitados de la Reserva

CampoDescripciónTipo de Dato

guest_document

Número de Documento

Varchar

guest_name

Nombre

Varchar

guest_email

Dirección de E-Mail

Varchar

AmenityBookingProduct: Productos solicitados al momento de la Reserva

CampoDescripciónTipo de Dato

product_id

Id del Producto

Entero Largo

quantity

Cantidad

Float

price

Precio Unitario

Float

Registro de Reservas de Amenities

Para solicitar la reserva de un Amenity, utiice el endpoint "amenity_bookings". Ejemplo:

curl --include \
     --request POST \
     --header "Content-Type: application/json" \
     --data-binary "{
          \"AmenityBooking\": {
               \"amenity_id\": \"5\",
               \"start_date\": \"2024-04-05 18:00\",
               \"end_date\": \"2024-04-06 02:00\",
               \"notes\": \"Para fiesta de cumpleaños infantil\"
          },
          \"AmenityBookingGuest\": [
               {
                    \"guest_document\": \"521321\",
                    \"guest_name\": \"Julio Fleitas\",
                    \"guest_email\": \"jf@gmail.com\"
               },
              {
                    \"guest_document\": \"3152545\",
                    \"guest_name\": \"Luis Fleitas\",
                    \"guest_email\": \"lf@gmail.com\"
              } 
          ],
          \"AmenityBookingProduct\": [
               {
                    \"product_id\": \"12\",
                    \"quantity\": \"2\",
                    \"price\": \"56000\"
               },
               {
                    \"product_id\": \"782\",
                    \"quantity\": \"5\",
                    \"price\": \"5000\"
               }
          ]
     }" \
'http://localhost:8080/bims2/api/amenity_bookings?sid=ssriq8vfjluel5fpjtn0b6mqm7';

Facturas Emitidas

Descripción

Se emiten a los Inquilinos y/o Propietarios facturas en conceptos de Expensas (a partir de una Liquidación de Expensas). El usuario debe poder consultar las facturas que le han sido emitidas.

Estructuras de Datos

Esta es la descripción de los datos recibidos del backend al consultar las facturas emitidas.

CampoDescripciónTipo de Dato

id

Id de la Venta

BIGINT

issue_date

Fecha de Emisieon

DATE

invoice_number

Número de Factura sin Prefijos

VARCHAR

full_invoice_number

Número de Factura Completo

VARCHAR

amount

Importe de la Venta

NUMERIC

notes

Observaciones

TEXT

local_amount

Importe de la Venta en Moneda lOcal

NUMERIC

pdf_url

URL a la Factura en PDF

VARCHAR

Consulta de Facturas Emitidas

El endpoint para la consulta es api/estates_groups/invoices. El backend retornará las facturas emitidas a todas las propiedades asociadas al usuario, exclusivamente.

Indicar siempre el id del consorcio actual en la consulta en al argumento de url: estates_group_id.

Ejemplo:

curl 'http://localhost:8080/bims2/api/estates_groups/invoices?sid=p6t2iudoed74flqnkig152en44&estates_group_id=1'
{
    "code": "200",
    "status": "ok",
    "data": [
        {
            "Sale": {
                "id": "13004",
                "issue_date": "2023-10-20",
                "invoice_number": "1969",
                "full_invoice_number": "001-001-0001969",
                "amount": "1100000",
                "notes": "Factura generada autom\u00e1ticamente a partir de la Liquidaci\u00f3n de Expensas #13 para la propiedad .",
                "local_amount": "1100000",
                "pdf_url": "http:\/\/localhost:8080\/bims2sales\/pdf\/13004\/845ee69d25fca3a280e037edfefa215b"
            },
            "Currency": {
                "symbol": "Gs"
            },
            "Estate": {
                "id": "2",
                "name": "Departamento A1"
            },
            "EstatesGroup": {
                "id": "1",
                "name": "Edificio San Mart\u00edn"
            },
            "Contact": {
                "id": "74",
                "name": "Tony Stark",
                "document_id": "1233818"
            },
            "ReExpensesSet": {
                "id": "13",
                "issue_date": "2023-10-20",
                "period_from": "2023-09-01",
                "period_to": "2023-09-30"
            }
        }
    ],
    "last_update": "2024-04-22 14:36:50"
}

Liquidaciones de Expensas

Se espera que la app exponga las Liquidaciones de Expensas generadas en BIMS para el Consorcio. Las Liquidaciones de Expensas señalan todos los gastos comunes y su distribución entre las propiedades del consorcio. Solo a modo de referencia, estas liquidaciones en pantalla tienen el siguiente formato:

En la app, las liquidaciones de expensas deben listarse indicando para cada cada registro de la lista los siguientes datos de cabecera:

TítuloDescripciónCampo

Id

Id de la Liquidación

ReExpensesSet.id

Fecha de Emisión

Fecha de Emisión de la Liquidación

ReExpensesSet.issue_date

Período

Período Cubierto por la Liquidación, compuesto por una Fecha de Inicio y Fecha de Cierre

ReExpensesSet.period_from / ReExpensesSet.period_to

Gastos Totales

Valor Total de Liquidación, compuesto por la suma de 2 campos.

ReExpensesSet.total_proportional + ReExpensesSet.total_equitative

Reserva

Valor destinado a fondo de reserva

ReExpensesSet.total_reserve

Valor Correspondiente

Es el valor de la Liquidación que le corresponde abonar a las Propiedades del consorcio del usuario activo. Las Propiedades del Usuario activo están definidas en el atributo UsersEstate de los datos del usuario retornados con el login.

SUM(ReExpensesEstate.amount) tal que ReExpensesEstate.estate_id sea uno de los UserEstate.estate_id en los datos del Usuario.

Finalmente, para obtener los datos de las Liquidaciones de Expensas, utilizá el endpoint "re_expenses_sets". Ejemplo:

curl 'https://beta.bims.app/api/re_expenses_sets?sid=4qcgsgctj1eapgsidlnutms1d6&estates_group_id=1'

Siempre indicá el Consorcio actual en el argumento estates_group_id.

No es necesario desarrollar un detalle de las liquidaciones, en su lugar crear un webview a la URL indicada en ReExpense.public_url.

Check-In de Invitados

Cuando desde la app se registra la reserva de un amenity, se genera un código QR. Este código QR lleva a un enlace a BIMS, desde cuya versión móvil se debe poder registrar el checkin de los invitados. La pantalla debe mostrar los datos generales de la reserva y la lista de invitados con posibilidad de seleccionar los usuarios que ingresan.

La URL de los QR estarán construídas de la siguiente manera: <BIMS-HOST>?ab_checkin=<ID-RESERVA>. Ejemplo: https://bims.app?ab_checkin=12.

La app deberá consultar los datos de la reserva. Para ello empleara el endpoint "amenity_bookings", indicando el id de ls reserva (ab_checkin) en el argumento "id" en la URL. Ejemplo:

curl 'https://beta.bims.app/api/amenity_bookings/index?id=51&sid=2fb6c8d2f3842a5ceaa9bf320e649ff0&company=1';

La URL del ejemplo es válida, para pruebas solo cambiá el valor de "sid" por un session id válido.

Para que se habilite esta opción en la versión móvil de BIMS, el usuario debe tener el siguinte permiso: "reAmenityBookingGuestCheckin" o bien, su tipo de usuario debe tener permisos completos (user.Group.full = true).

Los datos en la respuesta para construir la pantalla son los siguientes.

DescripciónCampoTipo de Dato

Nombre del Consorcio

data.Amenity.EstatesGroup

VARCHAR

Nombre del Amenity

data.Amenity.name

VARCHAR

Fecha de Inicio

data.AmenityBooking.start_date

TIMESTAMP

Fecha de Fin

data.AmenityBooking.end_date

TIMESTAMP

Solicitante

data.User.name

VARCHAR

Unidad

data.User.UsersEstate[0].Estate.name

VARCHAR

Nombre del Invitado

data.AmenityBookingGuest[n].guest_name

VARCHAR

Documento del Invitado

data.AmenityBookingGuest[n].guest_document

VARCHAR

Id del Invitado

data.AmenityBookingGuest[n].id

BIGINT

Id de la Reserva

data.AmenityBookings.id

BIGINT

Invitado Checkeado

data.AmenitiBookingGuest[n].checkedin

TIMESTAMP

Cuando el usuario haga clic sobre la casilla de un invitado, se debe hacer checkin del usuario. Para esto utilizá el endpoint amenity_bookings/checkin, e indicá el id de la reserva y el id del invitado.

Ejemplo:

curl --include \
     --request POST \
     --header "Content-Type: application/json" \
     --data-binary "{
          \"amenity_booking_id\": 51,
          \"amenity_booking_guest_id\": 85
     }" \
'https://beta.bims.app/api/amenity_bookings/checkin?sid=v2la11i3l697ppsi2v9k2famg0';

{
    "code": "200",
    "status": "ok"
}

Marcá la casilla del usuario como chequeada.

Si el atributo "status" en la respuesta indica "ok", entonces el checkin se ha realizado con éxito.

Si el atributo "status" en la respuesta indica "error", entonces la operación no se ha completado y debe revertirse el estado del la casilla del invitado.

Ejemplo de transacción fallida:

curl --include \
     --request POST \
     --header "Content-Type: application/json" \
     --data-binary "{
          \"amenity_booking_id\": 51
     }" \
'https://beta.bims.app/api/amenity_bookings/checkin?sid=v2la11i3l697ppsi2v9k2famg0';

{
    "code": "405",
    "status": "error",
    "message": "No hay argumentos de entrada"
}

El usuario debe poder deshacer un checkin haciendo clic nuevamente sobre un invitado previamente checkeado. Se debe ofrecer un mensaje de confirmación. Para deschequear un invitado en el backend utilizá el endpoint amenity_bookings/checkin y sumá el argumento "uncheck" con el valor 1. Ejemplo:

curl --include \
     --request POST \
     --header "Content-Type: application/json" \
     --data-binary "{
          \"amenity_booking_id\": 51,
          \"amenity_booking_guest_id\": 85,
          \"uncheck\": 1
     }" \
'https://beta.bims.app/api/amenity_bookings/checkin?sid=v2la11i3l697ppsi2v9k2famg0';

{
    "code": "200",
    "status": "ok"
}

Last updated