Files
mini-erp/mini-backend/docs/api-reference.md
2026-08-17 11:58:38 -05:00

12 KiB

API Reference

Base URL: http://<host>:8000 API Version: 1.1.0 Content-Type: application/json


Headers Globales

Header Requerido Descripción
Content-Type Sí application/json
X-Session-Token Sí (excepto /api/Login) Token obtenido en el login
X-Request-ID Opcional UUID para trazabilidad; si no se envía, el servidor lo genera

Formato de Errores

Todas las respuestas de error siguen el mismo formato:

{
  "detail": "Mensaje de error de SAP o del servidor"
}
Código Significado
400 Error de negocio SAP (ej: código duplicado, validación fallida)
401 Token inválido/expirado, o credenciales incorrectas
404 Recurso no encontrado en SAP
500 Error de conexión con SAP o error interno

Autenticación

POST /api/Login

Inicia sesión de empleado. Busca en SAP EmployeesInfo al empleado cuyo campo de usuario U_WEB_USER coincida con Username, y valida Password contra su campo U_WEB_PASS. También exige que el empleado esté activo (Active == "tYES").

Request body:

{
  "Username": "jgarcia",
  "Password": "********"
}

Response 200:

{
  "message": "Login exitoso",
  "token": "aB3x...token_urlsafe_32_chars...",
  "username": "Juan",
  "company": "NOMBRE_COMPANYDB"
}

Response 401:

{
  "detail": "Usuario o contraseña incorrectos"
}

Otros posibles detail en 401: "Usuario no registrado" (no existe ningún empleado con ese U_WEB_USER) y "Usuario inactivo" (el empleado existe pero Active != "tYES").


POST /api/Logout

Cierra la sesión del empleado.

Headers: X-Session-Token: <token>

Response 200:

{
  "message": "Logout exitoso"
}

Socios de Negocio

GET /api/BusinessPartners

Lista paginada de socios de negocio.

Query parameters:

Parámetro Tipo Default Descripción
skip int 0 Registros a saltar ($skip)
top int 50 Registros por página ($top)
fields string — Campos a retornar, separados por coma ($select)
filter string — Filtro OData ($filter). Activa B1S-CaseInsensitive

Response 200:

{
  "odata.metadata": "https://.../$metadata#BusinessPartners",
  "value": [
    {
      "CardCode": "C001",
      "CardName": "Cliente Demo",
      "CardType": "C"
    }
  ],
  "odata.count": 150
}

GET /api/BusinessPartners/{bp_code}

Obtiene un socio de negocio por CardCode.

Response 200:

{
  "CardCode": "C001",
  "CardName": "Cliente Demo",
  "CardType": "C",
  "Phone1": "123456789",
  "EmailAddress": "cliente@demo.com"
}

POST /api/BusinessPartners

Crea un nuevo socio de negocio.

Request body:

{
  "CardCode": "C001",
  "CardName": "Cliente Demo",
  "CardType": "C"
}

Response 201:

{
  "CardCode": "C001"
}

PATCH /api/BusinessPartners/{bp_code}

Actualiza un socio de negocio existente.

Request body:

{
  "CardName": "Nuevo Nombre",
  "Phone1": "987654321"
}

Response 204: Sin contenido.


Artículos

GET /api/Items

Lista paginada de artículos.

Query parameters:

Parámetro Tipo Default Descripción
skip int 0 Registros a saltar
top int 50 Registros por página
fields string — Campos a retornar ($select)
filter string — Filtro OData ($filter)

Response 200:

{
  "odata.metadata": "https://.../$metadata#Items",
  "value": [
    {
      "ItemCode": "A001",
      "ItemName": "Artículo Demo",
      "InventoryUOM": "UN"
    }
  ],
  "odata.count": 250
}

GET /api/Items/{item_code}

Obtiene un artículo por ItemCode.

Response 200:

{
  "ItemCode": "A001",
  "ItemName": "Artículo Demo",
  "InventoryUOM": "UN",
  "SalesPrice": 100.50
}

POST /api/Items

Crea un nuevo artículo.

Request body:

{
  "ItemCode": "A001",
  "ItemName": "Artículo Demo",
  "InventoryUOM": "UN"
}

Response 201:

{
  "ItemCode": "A001"
}

PATCH /api/Items/{item_code}

Actualiza un artículo existente.

Request body:

{
  "ItemName": "Nuevo Nombre",
  "SalesPrice": 120.00
}

Response 204: Sin contenido.


Ventas

Facturas (A/R Invoices)

GET /api/Invoices

Lista paginada de facturas de venta.

Query parameters:

Parámetro Tipo Default Descripción
skip int 0 Registros a saltar
top int 50 Registros por página
fields string — Campos a retornar
filter string — Filtro OData
orderby string — Ordenamiento ($orderby)

Response 200:

{
  "odata.metadata": "https://.../$metadata#Invoices",
  "value": [
    {
      "DocEntry": 1001,
      "CardCode": "C001",
      "DocTotal": 1500.00,
      "DocDate": "2026-07-06"
    }
  ],
  "odata.count": 45
}

POST /api/Invoices

Crea una factura de venta.

Response 201:

{
  "DocEntry": 1001
}

GET /api/Invoices/{invoice_key}

Obtiene una factura por DocEntry.


PATCH /api/Invoices/{invoice_key}

Actualiza una factura. Usa header B1S-ReplaceCollectionsOnPatch: true.

Response 204: Sin contenido.


Pedidos (Sales Orders)

GET /api/Orders

Lista paginada de pedidos de venta. Mismos parámetros que Invoices.

POST /api/Orders

Crea un pedido de venta.

Response 201:

{
  "DocEntry": 2001
}

GET /api/Orders/{order_key}

Obtiene un pedido por DocEntry.

PATCH /api/Orders/{order_key}

Actualiza un pedido. Usa header B1S-ReplaceCollectionsOnPatch: true.

Response 204: Sin contenido.


Guías de Remisión de Venta (Delivery Notes)

GET /api/DeliveryNotes

Lista paginada de guías de remisión de venta. Mismos parámetros que Invoices/Orders.

POST /api/DeliveryNotes

Crea una guía de remisión de venta.

Response 201:

{
  "DocEntry": 3001
}

GET /api/DeliveryNotes/{key}

Obtiene una guía de remisión por DocEntry.

PATCH /api/DeliveryNotes/{key}

Actualiza una guía de remisión. Usa header B1S-ReplaceCollectionsOnPatch: true.

Response 204: Sin contenido.


Compras

Órdenes de Compra

GET /api/PurchaseOrders

Lista paginada. Mismos parámetros que Invoices/Orders.

POST /api/PurchaseOrders

Crea una orden de compra.

Response 201:

{
  "DocEntry": 4001
}

GET /api/PurchaseOrders/{key}

Obtiene una orden de compra por DocEntry.

PATCH /api/PurchaseOrders/{key}

Actualiza una orden de compra. Usa header B1S-ReplaceCollectionsOnPatch: true.

Response 204: Sin contenido.


Facturas de Compra (A/P Invoices)

GET /api/PurchaseInvoices

Lista paginada. Mismos parámetros que Invoices/Orders.

POST /api/PurchaseInvoices

Crea una factura de compra.

Response 201:

{
  "DocEntry": 4501
}

GET /api/PurchaseInvoices/{key}

Obtiene una factura de compra por DocEntry.

PATCH /api/PurchaseInvoices/{key}

Actualiza una factura de compra. Usa header B1S-ReplaceCollectionsOnPatch: true.

Response 204: Sin contenido.


Guías de Recepción de Compra (Purchase Delivery Notes)

GET /api/PurchaseDeliveryNotes

Lista paginada. Mismos parámetros que Invoices/Orders.

POST /api/PurchaseDeliveryNotes

Crea una guía de recepción de compra.

Response 201:

{
  "DocEntry": 5001
}

GET /api/PurchaseDeliveryNotes/{key}

Obtiene una guía de recepción de compra por DocEntry.

PATCH /api/PurchaseDeliveryNotes/{key}

Actualiza una guía de recepción de compra. Usa header B1S-ReplaceCollectionsOnPatch: true.

Response 204: Sin contenido.


Catálogos

GET /api/Currencies

Lista de monedas.

Response 200:

{
  "value": [
    { "Code": "USD", "Name": "US Dollar" },
    { "Code": "EUR", "Name": "Euro" }
  ]
}

GET /api/BusinessPartnerGroups

Lista de grupos de socios de negocio.

Response 200:

{
  "value": [
    { "Number": 1, "GroupName": "Clientes Nacionales" }
  ]
}

GET /api/Warehouses

Lista paginada de almacenes. Acepta skip, top, fields, filter.


GET /api/ItemGroups

Lista de grupos de artículos.

Response 200:

{
  "value": [
    { "Number": 1, "GroupName": "Materia Prima" }
  ]
}

GET /api/SalesTaxCodes

Lista paginada de códigos de IVA. Acepta skip, top, fields, filter.


GET /api/FactoringIndicators

Lista paginada de indicadores de factoring. Acepta skip, top, fields, filter.


GET /api/Sunat/BusinessPartners/DocumentType

Lista los valores del campo de usuario EXX_TIPODOCU (tabla OCRD, tipo de documento SUNAT del socio de negocio), consultando UserFieldsMD en SAP. Endpoint fijo, sin parámetros de paginación.

Response 200:

{
  "value": [
    { "FieldID": 1, "Description": "DNI" },
    { "FieldID": 2, "Description": "RUC" }
  ]
}

Lotes

GET /api/BatchNumberDetails

Lista paginada de lotes/números de serie. Acepta skip, top, fields, filter, orderby.


GET /api/BatchNumberDetails/{batch_id}

Obtiene un lote por ID.


PATCH /api/BatchNumberDetails/{batch_id}

Actualiza un lote.

Response 204: Sin contenido.


Permisos

GET /api/user/menu

Retorna las rutas de menú permitidas para el empleado autenticado.

Headers: X-Session-Token: <token>

Response 200:

{
  "allowedPaths": [
    "/inventario/*",
    "/ventas/*",
    "/compras/*"
  ]
}

Response 401:

{
  "detail": "Usuario no autenticado"
}

Reportes (API Gateway — Crystal Reports)

Estos endpoints no van contra el Service Layer sino contra el SAP API Gateway (core/api_gateway.py), que expone los reportes Crystal Reports autorizados para la compañía.

GET /api/apigateway/reports

Lista los reportes Crystal Reports autorizados para el usuario/compañía.

Response 200:

[
  { "DocCode": "R001", "DocName": "Guía de Remisión" }
]

GET /api/apigateway/reports/{docCode}/parameters

Obtiene los parámetros de entrada que requiere un reporte puntual (por DocCode) antes de exportarlo.


POST /api/apigateway/reports/{docCode}/export

Exporta el reporte a PDF. El body es la lista de parámetros que el reporte necesita (formato definido por el propio API Gateway / Crystal Reports).

Request body:

[
  { "name": "DocEntry", "value": "1001" }
]

Response 200: application/pdf (streaming, Content-Disposition: inline).


Reportes (Jinja/HTML → PDF)

Generados desde plantillas HTML propias (templates/reports/) renderizadas con Jinja2 y convertidas a PDF con WeasyPrint, a partir de datos consultados directamente en HANA (core/hana.py), sin pasar por el Service Layer.

POST /api/reports/stickers

Genera el sticker de una guía de remisión de venta (DeliveryNotes) para imprimir etiquetas de despacho.

Request body:

{
  "doc_entry": 3001,
  "cantidad": 4,
  "formato": "pdf",
  "papel": "Carta"
}
Campo Tipo Requerido Descripción
doc_entry int Sí DocEntry de la guía de remisión en HANA
cantidad int Sí Cantidad de stickers a generar
formato "pdf" | "html" No (default "pdf") Formato de salida
papel "A4" | "Carta" No (default "Carta") Tamaño de papel del PDF

Response 200: application/pdf o text/html según formato, streaming.

Response 404:

{
  "detail": "No se encontró el documento 3001"
}

Response 500: error al consultar HANA.


Resumen de Códigos de Respuesta

Método Éxito Cuerpo en éxito Error SAP Error de conexión
GET 200 JSON del recurso 4xx con detail 500
POST 201 {"CardCode"/"ItemCode"/"DocEntry": valor} 4xx con detail 500
PATCH 204 Sin cuerpo 4xx con detail 500