- README.md con guía completa de instalación y arquitectura - docs/BACKEND.md — guía detallada del API - docs/FRONTEND.md — guía del SPA React - docs/DATABASE.md — funciones SQL y patrones de datos - docs/API.md — referencia completa de endpoints REST - docs/DEPLOYMENT.md — guía de despliegue en producción - docs/TROUBLESHOOTING.md — solución de problemas comunes - CHANGELOG.md — historial de cambios - CONTRIBUTING.md — guía de contribución
700 lines
12 KiB
Markdown
700 lines
12 KiB
Markdown
# 🔌 Referencia Completa de la API REST
|
|
|
|
**Base URL:** `https://<dominio>/api`
|
|
|
|
---
|
|
|
|
## Índice
|
|
1. [Convenciones](#convenciones)
|
|
2. [Autenticación](#autenticación)
|
|
3. [Empleados](#empleados)
|
|
4. [Contratos](#contratos)
|
|
5. [Productos](#productos)
|
|
6. [Gastos](#gastos)
|
|
7. [Aprobaciones y Pagos](#aprobaciones-y-pagos)
|
|
8. [Pagos Mensuales](#pagos-mensuales)
|
|
9. [Configuraciones](#configuraciones)
|
|
10. [Emails](#emails)
|
|
11. [Ingresos (Little Hotelier)](#ingresos-little-hotelier)
|
|
12. [Compras](#compras)
|
|
13. [Tipo de Cambio](#tipo-de-cambio)
|
|
14. [Hotel P&L](#hotel-pl)
|
|
15. [Restaurant P&L](#restaurant-pl)
|
|
16. [Ingresos Horux](#ingresos-horux)
|
|
|
|
---
|
|
|
|
## Convenciones
|
|
|
|
- **Formato:** JSON en request body y response.
|
|
- **Paginación:** `?page=N&limit=M` (default limit: 500 para empleados, 10 para productos).
|
|
- **Errores:** Status `500` con `{ message: "Error descripción" }`.
|
|
- **CORS:** Origen controlado por `URL_CORS` en el backend.
|
|
|
|
---
|
|
|
|
## Autenticación
|
|
|
|
> ⚠️ **Nota:** No hay JWT. El login devuelve un rol numérico que el frontend guarda en `localStorage`.
|
|
|
|
### POST `/api/auth/login`
|
|
|
|
```json
|
|
// Request
|
|
{
|
|
"name_mail_user": "usuario_o_email",
|
|
"user_pass": "contraseña"
|
|
}
|
|
|
|
// Response 200
|
|
{
|
|
"rol": 1,
|
|
"user_id": 5,
|
|
"user_name": "Admin",
|
|
"message": "Usuario autenticado correctamente"
|
|
}
|
|
```
|
|
|
|
**Status codes de la función SQL:**
|
|
- `status: 1` = Autenticado
|
|
- `status: 2` = Credenciales incorrectas
|
|
|
|
### POST `/api/auth/createuser`
|
|
|
|
```json
|
|
// Request
|
|
{
|
|
"name_user": "Nuevo Usuario",
|
|
"id_rol": 2,
|
|
"email": "user@email.com",
|
|
"user_pass": "password123"
|
|
}
|
|
|
|
// Response
|
|
{
|
|
"message": "Se agrego el usuario correctamente",
|
|
"status": 1
|
|
}
|
|
```
|
|
|
|
### POST `/api/auth/recoverpass`
|
|
|
|
Genera una contraseña aleatoria y la envía por correo.
|
|
|
|
```json
|
|
// Request
|
|
{ "user_mail": "user@email.com" }
|
|
|
|
// Response
|
|
{
|
|
"message": "Correo enviado con nueva contraseña.",
|
|
"status": 1
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Empleados
|
|
|
|
Base: `/api/employees`
|
|
|
|
### GET `/api/employees/`
|
|
|
|
Lista paginada de empleados.
|
|
|
|
**Query params:** `?page=1&limit=500`
|
|
|
|
```json
|
|
// Response
|
|
{
|
|
"page": 1,
|
|
"limit": 500,
|
|
"total": 45,
|
|
"totalPages": 1,
|
|
"data": [
|
|
{
|
|
"employee_rfc": "RFC123456",
|
|
"name_employee": "Juan Pérez",
|
|
"nss_employe": "12345678901",
|
|
"position_employee": "Recepcionista",
|
|
"area_employee": "Front Desk",
|
|
"phone_employee": "5551234567",
|
|
"end_contract": "2025-12-31",
|
|
"daily_pay": 500.00,
|
|
"uniforms": 2,
|
|
"status": "Activo",
|
|
"birthday": "1990-05-15",
|
|
"curp": "CURP123456HDF"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### GET `/api/employees/activeEmployees`
|
|
|
|
```json
|
|
{ "message": "Total de empleados activos", "data": 42 }
|
|
```
|
|
|
|
### GET `/api/employees/getattendance`
|
|
|
|
```json
|
|
{ "message": "attendance", "data": [...] }
|
|
```
|
|
|
|
### GET `/api/employees/gradeofstudy`
|
|
|
|
Catálogo de grados de estudio.
|
|
|
|
### GET `/api/employees/relationship`
|
|
|
|
Catálogo de parentescos.
|
|
|
|
### POST `/api/employees/employee`
|
|
|
|
Obtiene un empleado por RFC.
|
|
|
|
```json
|
|
// Request
|
|
{ "rfcEmployee": "RFC123456" }
|
|
```
|
|
|
|
### POST `/api/employees/newemployee`
|
|
|
|
```json
|
|
// Request
|
|
{
|
|
"name_emp": "Juan Pérez",
|
|
"rfc_emp": "RFC123456",
|
|
"nss_emp": "12345678901",
|
|
"addres_emp": "Calle 123",
|
|
"phone_emp": "5551234567",
|
|
"email_emp": "juan@email.com",
|
|
"birthday_emp": "1990-05-15",
|
|
"curp_emp": "CURP123456HDF",
|
|
"study_emp": 1,
|
|
"emergency_name": "María Pérez",
|
|
"emergency_tel": "5559876543",
|
|
"relationship_id": 1
|
|
}
|
|
```
|
|
|
|
### POST `/api/employees/updateemployee`
|
|
|
|
Misma firma que `newemployee`. Actualiza por RFC.
|
|
|
|
---
|
|
|
|
## Contratos
|
|
|
|
Base: `/api/contracts`
|
|
|
|
### GET `/api/contracts/`
|
|
|
|
### GET `/api/contracts/getinfocontract/:id`
|
|
|
|
### GET `/api/contracts/neartoend`
|
|
|
|
### GET `/api/contracts/positions`
|
|
|
|
### GET `/api/contracts/areas`
|
|
|
|
### GET `/api/contracts/bosses`
|
|
|
|
### GET `/api/contracts/reportempcontract`
|
|
|
|
### GET `/api/contracts/disabledcontract`
|
|
|
|
### POST `/api/contracts/newcontract`
|
|
|
|
### PUT `/api/contracts/updatecontract/:id`
|
|
|
|
---
|
|
|
|
## Productos
|
|
|
|
Base: `/api/products`
|
|
|
|
### GET `/api/products/`
|
|
|
|
Paginado (default limit: 10).
|
|
|
|
### GET `/api/products/productcategory`
|
|
|
|
### GET `/api/products/producttype`
|
|
|
|
### GET `/api/products/suppliers`
|
|
|
|
### GET `/api/products/gdiscardproducts`
|
|
|
|
### GET `/api/products/reportinventory`
|
|
|
|
### GET `/api/products/stockadjusment`
|
|
|
|
### GET `/api/products/gethousekeeper`
|
|
|
|
### GET `/api/products/getproducts`
|
|
|
|
### GET `/api/products/getconsumptionstockreport`
|
|
|
|
### POST `/api/products/newsupplier`
|
|
|
|
```json
|
|
{
|
|
"new_name_supp": "Proveedor SA",
|
|
"new_rfc_supp": "RFC123456",
|
|
"new_mail_supp": "prov@email.com",
|
|
"new_phone_supp": "5551234567"
|
|
}
|
|
```
|
|
|
|
### POST `/api/products/newproduct`
|
|
|
|
```json
|
|
{
|
|
"new_name_product": "Toallas",
|
|
"new_sku_product": "TOW-001",
|
|
"product_type": [{"id": 1, "name": "Textil"}],
|
|
"new_category": 1,
|
|
"suppliers_id": 1,
|
|
"unit": 1,
|
|
"new_stock": 100,
|
|
"newprice_product": 150.00,
|
|
"new_tax": 1,
|
|
"currency": 1,
|
|
"image_product": "url_o_base64"
|
|
}
|
|
```
|
|
|
|
> Nota: `product_type` se serializa a JSONB.
|
|
|
|
### POST `/api/products/stockadjusmentset`
|
|
|
|
```json
|
|
{
|
|
"stockproductadjusment": [
|
|
{ "id_product": 1, "new_stock": 50 },
|
|
{ "id_product": 2, "new_stock": 30 }
|
|
]
|
|
}
|
|
```
|
|
|
|
### POST `/api/products/newconsumptionstock`
|
|
|
|
```json
|
|
{
|
|
"product_id": 1,
|
|
"quantity_consumption": 5,
|
|
"date_consumption": "2025-01-15",
|
|
"rfc_emp": "RFC123456"
|
|
}
|
|
```
|
|
|
|
### POST `/api/products/disableSupplier`
|
|
|
|
```json
|
|
{ "supplier_id": 1 }
|
|
```
|
|
|
|
### PUT `/api/products/update_product/:id`
|
|
|
|
### PUT `/api/products/discardproduct/:id`
|
|
|
|
```json
|
|
{
|
|
"quantity": 5,
|
|
"reasons": "Dañado"
|
|
}
|
|
```
|
|
|
|
### PUT `/api/products/product/:id`
|
|
|
|
### PUT `/api/products/updatesupplier/:id`
|
|
|
|
⚠️ **Bug conocido:** Falta `/` inicial en la ruta del backend.
|
|
|
|
---
|
|
|
|
## Gastos
|
|
|
|
Base: `/api/expenses`
|
|
|
|
### GET `/api/expenses/pendingapproval`
|
|
|
|
### GET `/api/expenses/approvedexpenses`
|
|
|
|
### GET `/api/expenses/rejectedexpenses`
|
|
|
|
### GET `/api/expenses/mainsupplier`
|
|
|
|
### PUT `/api/expenses/getexpense/:id`
|
|
|
|
⚠️ **Nota:** Es `PUT` pero debería ser `GET`. No requiere body.
|
|
|
|
### GET `/api/expenses/getinfo`
|
|
|
|
Devuelve catálogos combinados (suppliers, categories, areas, users, currencies, uniforms, taxes).
|
|
|
|
### GET `/api/expenses/reportexpenses`
|
|
|
|
### POST `/api/expenses/countpending`
|
|
|
|
```json
|
|
{ "option": 1 } // 1 = aprobaciones, 2 = mensuales
|
|
```
|
|
|
|
### GET `/api/expenses/reportpayments`
|
|
|
|
### GET `/api/expenses/monthlypayments`
|
|
|
|
### POST `/api/expenses/newexpense`
|
|
|
|
```json
|
|
{
|
|
"new_description": "Compra de amenities",
|
|
"suppliers_id": 1,
|
|
"new_request_date": "2025-01-01",
|
|
"new_payment_deadline": "2025-01-31",
|
|
"request_by": 1,
|
|
"area": 1,
|
|
"expense_cat": 1,
|
|
"currency_id": 1,
|
|
"products": [
|
|
{ "id_product": 1, "quantity": 10 },
|
|
{ "id_product": 2, "quantity": 5 }
|
|
],
|
|
"new_iva": 16.00,
|
|
"new_ieps": 0.00,
|
|
"new_subtotal": 1000.00,
|
|
"new_total": 1160.00,
|
|
"needtoapprove": true
|
|
}
|
|
```
|
|
|
|
### POST `/api/expenses/totalapproved`
|
|
|
|
```json
|
|
{ "option": 1 } // 1 = aprobado, 2 = rechazado
|
|
```
|
|
|
|
### PUT `/api/expenses/updateexpense/:id`
|
|
|
|
Misma estructura que `newexpense`, con campos prefijados con `up_`.
|
|
|
|
### GET `/api/expenses/gettaxes`
|
|
|
|
---
|
|
|
|
## Aprobaciones y Pagos
|
|
|
|
Base: `/api/status`
|
|
|
|
### PUT `/api/status/approveupdate/:id`
|
|
|
|
```json
|
|
{
|
|
"status": 2,
|
|
"approved_by": 1
|
|
}
|
|
```
|
|
|
|
**Status:**
|
|
- `2` = Aprobado
|
|
- `3` = Rechazado
|
|
|
|
### PUT `/api/status/paymentupdate/:id`
|
|
|
|
```json
|
|
{ "status": 2 }
|
|
```
|
|
|
|
### GET `/api/status/penapppayments`
|
|
|
|
### GET `/api/status/countdelaypay`
|
|
|
|
### GET `/api/status/totalspent`
|
|
|
|
---
|
|
|
|
## Pagos Mensuales
|
|
|
|
Base: `/api/payment`
|
|
|
|
### POST `/api/payment/newexpmonthly`
|
|
|
|
```json
|
|
{
|
|
"descriptionex": "Renta",
|
|
"recurrence_id": 1,
|
|
"payment_type": 1,
|
|
"currency_id": 1,
|
|
"suppliers_id": 1,
|
|
"area": 1,
|
|
"expense_category": 1,
|
|
"day_expense": 15,
|
|
"tax_id": 1,
|
|
"new_subtotal": 5000.00
|
|
}
|
|
```
|
|
|
|
### GET `/api/payment/refreshmonthly`
|
|
|
|
### PUT `/api/payment/paymentstatusmonthly/:id`
|
|
|
|
```json
|
|
{
|
|
"status_payment": 2,
|
|
"tax_id": 1,
|
|
"subtotal": 5000.00
|
|
}
|
|
```
|
|
|
|
Si `subtotal` es null, solo actualiza el estado sin recalcular total.
|
|
|
|
### PUT `/api/payment/updateexpmonthly/:id`
|
|
|
|
### GET `/api/payment/onemothlyexpense/:id`
|
|
|
|
### PUT `/api/payment/needtorefresh/:id`
|
|
|
|
```json
|
|
{ "notrefresh": true }
|
|
```
|
|
|
|
---
|
|
|
|
## Configuraciones
|
|
|
|
Base: `/api/settings`
|
|
|
|
### POST `/api/settings/newroom`
|
|
|
|
### POST `/api/settings/newproperty`
|
|
|
|
### GET `/api/settings/reportrooms`
|
|
|
|
### GET `/api/settings/reportproperties`
|
|
|
|
### GET `/api/settings/approveby`
|
|
|
|
### GET `/api/settings/requestby`
|
|
|
|
### GET `/api/settings/categoryexpense`
|
|
|
|
### GET `/api/settings/currency`
|
|
|
|
### GET `/api/settings/units`
|
|
|
|
### GET `/api/settings/recurrence`
|
|
|
|
---
|
|
|
|
## Emails
|
|
|
|
Base: `/api/emails`
|
|
|
|
> ⚠️ **Nota:** Todos estos endpoints tienen validación de frecuencia (1 ejecución por mes) mediante la función `validateendpoint()`.
|
|
|
|
### POST `/api/emails/nearexpiring`
|
|
|
|
### POST `/api/emails/paymentdelay`
|
|
|
|
### POST `/api/emails/expensesneartodeadline`
|
|
|
|
### POST `/api/emails/expensesspecial`
|
|
|
|
### POST `/api/emails/birthdays`
|
|
|
|
### POST `/api/emails/contractexpired`
|
|
|
|
### POST `/api/emails/expiredcontractsmonth`
|
|
|
|
---
|
|
|
|
## Ingresos (Little Hotelier)
|
|
|
|
Base: `/api/incomes`
|
|
|
|
> **Nota:** La mayoría de estos endpoints reciben filtros de fecha en el body.
|
|
|
|
### POST `/api/incomes/getincomes`
|
|
|
|
### POST `/api/incomes/totalincomes`
|
|
|
|
### POST `/api/incomes/channelscards`
|
|
|
|
### POST `/api/incomes/loadincomes`
|
|
|
|
Carga masiva desde CSV/XLSX previamente colocado en `src/resources/littleHotelier/`.
|
|
|
|
### POST `/api/incomes/loadproductsales`
|
|
|
|
### POST `/api/incomes/loadchequesdetalle`
|
|
|
|
### POST `/api/incomes/reportincomes`
|
|
|
|
### POST `/api/incomes/countticket`
|
|
|
|
### POST `/api/incomes/efectivo`
|
|
|
|
### POST `/api/incomes/otros`
|
|
|
|
### POST `/api/incomes/propinas`
|
|
|
|
### POST `/api/incomes/tarjeta`
|
|
|
|
### POST `/api/incomes/vales`
|
|
|
|
### POST `/api/incomes/sumatotal`
|
|
|
|
### POST `/api/incomes/ticketpromedio`
|
|
|
|
### GET `/api/incomes/getproductsales`
|
|
|
|
### GET `/api/incomes/getdetallecheque`
|
|
|
|
---
|
|
|
|
## Compras
|
|
|
|
Base: `/api/purchases`
|
|
|
|
### GET `/api/purchases/getpurchases`
|
|
|
|
Devuelve líneas de compra pendientes de recepción.
|
|
|
|
```json
|
|
// Response
|
|
{
|
|
"message": "Se obtuvieron todos los Purchases details",
|
|
"data": [
|
|
{
|
|
"id_purchase_dt": 1,
|
|
"id_expense": 5,
|
|
"id_product": 2,
|
|
"product_name": "Toallas",
|
|
"quantity": 10,
|
|
"delivered": 0,
|
|
"id_tax": 1,
|
|
"total": 1500.00
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### PUT `/api/purchases/entry/:id`
|
|
|
|
Registra la recepción física de una compra.
|
|
|
|
```json
|
|
// Request
|
|
{ "checking": 10 }
|
|
|
|
// Response
|
|
{
|
|
"message": "Se obtuvo el Purchases details",
|
|
"newentry": 1
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Tipo de Cambio
|
|
|
|
Base: `/api/exchange`
|
|
|
|
### POST `/api/exchange/consultexchange`
|
|
|
|
Consulta tipo de cambio actual desde API de Banxico.
|
|
|
|
### GET `/api/exchange/getexchanges`
|
|
|
|
Devuelve historial de tipos de cambio guardados.
|
|
|
|
---
|
|
|
|
## Hotel P&L
|
|
|
|
Base: `/api/hotelpl`
|
|
|
|
### POST `/api/hotelpl/cogs`
|
|
|
|
### POST `/api/hotelpl/ebitda`
|
|
|
|
### POST `/api/hotelpl/employeeshare`
|
|
|
|
### POST `/api/hotelpl/grossprofit`
|
|
|
|
### POST `/api/hotelpl/tips`
|
|
|
|
### POST `/api/hotelpl/totalrevenue`
|
|
|
|
### POST `/api/hotelpl/weightedCategoriesCost`
|
|
|
|
---
|
|
|
|
## Restaurant P&L
|
|
|
|
Base: `/api/restaurantpl`
|
|
|
|
### POST `/api/restaurantpl/cogs`
|
|
|
|
### POST `/api/restaurantpl/ebitda`
|
|
|
|
### POST `/api/restaurantpl/grossprofit`
|
|
|
|
### POST `/api/restaurantpl/totalrevenue`
|
|
|
|
### POST `/api/restaurantpl/weightedCategoriesCost`
|
|
|
|
---
|
|
|
|
## Ingresos Horux
|
|
|
|
Base: `/api/incomeshrx`
|
|
|
|
### GET `/api/incomeshrx/accountincome`
|
|
|
|
### GET `/api/incomeshrx/categoryincome`
|
|
|
|
### GET `/api/incomeshrx/invoiceIncome`
|
|
|
|
### GET `/api/incomeshrx/totalIncome`
|
|
|
|
### GET `/api/incomeshrx/incomehorux`
|
|
|
|
### GET `/api/incomeshrx/oneincomehorux/:id`
|
|
|
|
### GET `/api/incomeshrx/stripedata/`
|
|
|
|
Obtiene transfers de Stripe y las inserta en PostgreSQL.
|
|
|
|
### POST `/api/incomeshrx/stripedatademo/`
|
|
|
|
Crea un transfer de demo en Stripe.
|
|
|
|
### POST `/api/incomeshrx/insertinvoice`
|
|
|
|
Descarga facturas de API externa (año actual) y las inserta.
|
|
|
|
### POST `/api/incomeshrx/newincome`
|
|
|
|
```json
|
|
{
|
|
"account_id": 1,
|
|
"amount": 5000.00,
|
|
"new_date": "2025-01-15",
|
|
"newinvoice": "FAC-001",
|
|
"area_id": 1,
|
|
"categories": [{"id": 1, "amount": 5000}]
|
|
}
|
|
```
|
|
|
|
### PUT `/api/incomeshrx/updateincome/:id`
|
|
|
|
Misma estructura que `newincome`.
|
|
|
|
---
|
|
|
|
> **Fin de la referencia API.** Para ver la lógica interna de cada endpoint, revisa los controllers en `backend/hotel_hacienda/src/controllers/`.
|