@nubiia/mcp-freematica 0.6.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -12
- package/dist/clients/freematica-client.d.ts +190 -1
- package/dist/clients/freematica-client.js +281 -1
- package/dist/clients/freematica-client.js.map +1 -1
- package/dist/config.d.ts +22 -1
- package/dist/config.js +29 -1
- package/dist/config.js.map +1 -1
- package/dist/schemas/contratos.d.ts +268 -5
- package/dist/schemas/contratos.js +402 -1
- package/dist/schemas/contratos.js.map +1 -1
- package/dist/server-instructions.js +44 -1
- package/dist/server-instructions.js.map +1 -1
- package/dist/server.d.ts +6 -0
- package/dist/server.js +2 -2
- package/dist/server.js.map +1 -1
- package/dist/tools/contratos/cabecera.d.ts +7 -0
- package/dist/tools/contratos/cabecera.js +128 -0
- package/dist/tools/contratos/cabecera.js.map +1 -0
- package/dist/tools/contratos/index.d.ts +21 -0
- package/dist/tools/contratos/index.js +31 -0
- package/dist/tools/contratos/index.js.map +1 -0
- package/dist/tools/contratos/materiales.d.ts +4 -0
- package/dist/tools/{contratos.js → contratos/materiales.js} +5 -11
- package/dist/tools/contratos/materiales.js.map +1 -0
- package/dist/tools/contratos/opcionales.d.ts +5 -0
- package/dist/tools/contratos/opcionales.js +106 -0
- package/dist/tools/contratos/opcionales.js.map +1 -0
- package/dist/tools/contratos/servicios.d.ts +5 -0
- package/dist/tools/contratos/servicios.js +215 -0
- package/dist/tools/contratos/servicios.js.map +1 -0
- package/dist/transports/http.d.ts +2 -0
- package/dist/transports/http.js +3 -1
- package/dist/transports/http.js.map +1 -1
- package/dist/transports/stdio.d.ts +2 -0
- package/dist/transports/stdio.js +3 -1
- package/dist/transports/stdio.js.map +1 -1
- package/dist/types/contratos.d.ts +29 -0
- package/dist/utils/idreg.d.ts +37 -0
- package/dist/utils/idreg.js +52 -0
- package/dist/utils/idreg.js.map +1 -0
- package/package.json +1 -1
- package/dist/tools/contratos.d.ts +0 -10
- package/dist/tools/contratos.js.map +0 -1
package/README.md
CHANGED
|
@@ -59,6 +59,29 @@ MCP server que expone operaciones del API REST de Freemática (ERP: facturación
|
|
|
59
59
|
| `freematica_list_albaranes_factura` | `GET /pven/v2/albaranes-facturas` | Lista paginada de vinculaciones albarán↔factura (idReg nativo + FIQL) |
|
|
60
60
|
| `freematica_get_albaran_factura` | `GET /pven/v2/albaranes-facturas/{idReg}` | Detalle de una vinculación albarán-factura |
|
|
61
61
|
| `freematica_list_resultados_facturacion` | `GET /pvss/v1/facturacion-resultados` | Resultados del proceso batch de facturación automática de vigilancia (FIQL) |
|
|
62
|
+
| `freematica_list_contratos` | `GET /pvss/v1/contratos` | Lista paginada de cabeceras de contratos (solo filtros nativos: el API ignora FIQL aquí) |
|
|
63
|
+
| `freematica_get_contrato` | `GET /pvss/v1/contratos` (scan) | Busca un contrato por empresa + código natural (paginación interna + filtrado en cliente) |
|
|
64
|
+
| `freematica_list_servicios_contrato` | `GET /pvss/v1/contratos/{idReg}/servicios` | Servicios de un contrato |
|
|
65
|
+
| `freematica_get_servicio_contrato` | `GET /pvss/v2/contratos-servicios/{idReg}` | Detalle de un servicio de contrato |
|
|
66
|
+
| `freematica_list_contratos_opcionales` | `GET /ppre/v2/contratos/opcionales` | Lista paginada de opcionales de contratos |
|
|
67
|
+
| `freematica_get_contrato_opcionales` | `GET /ppre/v2/contratos/opcionales/{idReg}` | Detalle de un registro de opcionales |
|
|
68
|
+
|
|
69
|
+
### Tools de escritura (requieren `FREEMATICA_ENABLE_WRITES=true`)
|
|
70
|
+
|
|
71
|
+
Por defecto el servidor es de **solo lectura**. Con `FREEMATICA_ENABLE_WRITES=true` se registran además estas tools de creación y actualización. **No existe ninguna tool de borrado.** Todas las escrituras dejan log de auditoría (operación + endpoint + campos a nivel info; body completo a nivel debug).
|
|
72
|
+
|
|
73
|
+
| Tool | Endpoint Freemática | Descripción |
|
|
74
|
+
| ---------------------------------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------- |
|
|
75
|
+
| `freematica_create_contrato` | `POST /pvss/v2/contratos` | Alta de cabecera de contrato |
|
|
76
|
+
| `freematica_update_contrato` | `PUT /pvss/v2/contratos/{idReg}` | Actualización de cabecera de contrato |
|
|
77
|
+
| `freematica_create_servicio_contrato` | `POST /pvss/v2/contratos/{idReg}/servicios` | Alta de servicio (identificación derivada del idReg) |
|
|
78
|
+
| `freematica_update_servicio_fechas` | `PUT /pvss/v2/contratos/{id}/servicio/{id}` | Fechas inicio/fin del servicio (mecanismo de baja) |
|
|
79
|
+
| `freematica_create_servicio_historico_precios` | `POST /pvss/v2/contratos/{id}/servicios-historico-precios/{id}` | Alta de revisión de precios del servicio |
|
|
80
|
+
| `freematica_update_servicio_historico_precios` | `PUT /pvss/v2/contratos/{id}/servicios-historico-precios/{id}` | Actualización de revisión de precios |
|
|
81
|
+
| `freematica_create_servicio_facturacion_txt` | `POST /pvss/v2/contratos/{id}/servicios-facturacion-txt/{id}` | Alta de línea de texto de facturación |
|
|
82
|
+
| `freematica_update_servicio_facturacion` | `PUT /pvss/v2/contratos/{id}/servicios-facturacion/{id}` | Datos de facturación del servicio (precios hora, forma de pago…) |
|
|
83
|
+
| `freematica_create_contrato_opcionales` | `POST /ppre/v2/contratos/opcionales` | Alta de opcionales de contrato |
|
|
84
|
+
| `freematica_update_contrato_opcionales` | `PUT /ppre/v2/contratos/opcionales/{idReg}` | Actualización de opcionales de contrato |
|
|
62
85
|
|
|
63
86
|
## Filtros tipados (FIQL interno)
|
|
64
87
|
|
|
@@ -234,18 +257,19 @@ El servidor lee toda su configuración de **variables de entorno** al arrancar.
|
|
|
234
257
|
|
|
235
258
|
Variables de entorno opcionales para tuning de comportamiento en producción:
|
|
236
259
|
|
|
237
|
-
| Variable | Default | Descripción
|
|
238
|
-
| --------------------------------------- | ---------------------------------------------------- |
|
|
239
|
-
| `FREEMATICA_BASE_URL` | `https://api-p01.clientservicepanel.com/restsat/api` | Base URL del API de Freemática. Cambiar solo si Freemática cambia el host o se usa un entorno alternativo.
|
|
240
|
-
| `FREEMATICA_TIMEOUT_MS` | `30000` | Timeout por petición en milisegundos. Si el upstream no responde en este tiempo, el request se cancela con `network_error`.
|
|
241
|
-
| `FREEMATICA_MAX_RETRIES` | `3` | Número máximo de reintentos para errores 5xx y errores de red. Los errores 4xx nunca se reintentan.
|
|
242
|
-
| `FREEMATICA_CIRCUIT_BREAKER_THRESHOLD` | `5` | Número de operaciones lógicas fallidas consecutivas (post-retry-exhaustion) necesarias para abrir el circuit breaker.
|
|
243
|
-
| `FREEMATICA_CIRCUIT_BREAKER_TIMEOUT_MS` | `30000` | Tiempo en ms que el circuit breaker permanece abierto antes de pasar a half-open.
|
|
244
|
-
| `FREEMATICA_MAX_RESPONSE_SIZE_MB` | `10` | Tamaño máximo de respuesta aceptada del upstream en MB. Respuestas mayores se truncan con aviso en el campo `truncated`.
|
|
245
|
-
| `
|
|
246
|
-
| `
|
|
247
|
-
| `
|
|
248
|
-
| `
|
|
260
|
+
| Variable | Default | Descripción |
|
|
261
|
+
| --------------------------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
262
|
+
| `FREEMATICA_BASE_URL` | `https://api-p01.clientservicepanel.com/restsat/api` | Base URL del API de Freemática. Cambiar solo si Freemática cambia el host o se usa un entorno alternativo. |
|
|
263
|
+
| `FREEMATICA_TIMEOUT_MS` | `30000` | Timeout por petición en milisegundos. Si el upstream no responde en este tiempo, el request se cancela con `network_error`. |
|
|
264
|
+
| `FREEMATICA_MAX_RETRIES` | `3` | Número máximo de reintentos para errores 5xx y errores de red. Los errores 4xx nunca se reintentan. |
|
|
265
|
+
| `FREEMATICA_CIRCUIT_BREAKER_THRESHOLD` | `5` | Número de operaciones lógicas fallidas consecutivas (post-retry-exhaustion) necesarias para abrir el circuit breaker. |
|
|
266
|
+
| `FREEMATICA_CIRCUIT_BREAKER_TIMEOUT_MS` | `30000` | Tiempo en ms que el circuit breaker permanece abierto antes de pasar a half-open. |
|
|
267
|
+
| `FREEMATICA_MAX_RESPONSE_SIZE_MB` | `10` | Tamaño máximo de respuesta aceptada del upstream en MB. Respuestas mayores se truncan con aviso en el campo `truncated`. |
|
|
268
|
+
| `FREEMATICA_ENABLE_WRITES` | `false` | Registra las tools de escritura (`freematica_create_*` / `freematica_update_*`). Sin ella el servidor es de solo lectura. Valores: `true`/`false`/`1`/`0`. |
|
|
269
|
+
| `MCP_TRANSPORT` | `stdio` | Transporte: `stdio` (para Claude Desktop/Code) o `http` (para Nubiia). Equivale al flag `--transport=`. |
|
|
270
|
+
| `MCP_PORT` | `3000` | Puerto TCP donde el servidor MCP expone `/mcp` y `/health`. Ignorado en modo stdio. |
|
|
271
|
+
| `MCP_ALLOWED_ORIGINS` | `*` | CORS: lista de orígenes permitidos separados por coma, o `*` para todos. En producción restringir al dominio de Nubiia. Ignorado en modo stdio. |
|
|
272
|
+
| `LOG_LEVEL` | `info` | Nivel de log para pino: `fatal`, `error`, `warn`, `info`, `debug`, `trace`. En producción usar `info`. En desarrollo usar `debug`. |
|
|
249
273
|
|
|
250
274
|
### De dónde salen las credenciales `x-auth-*`
|
|
251
275
|
|
|
@@ -7,7 +7,7 @@ import type { Cliente } from '../types/clientes.js';
|
|
|
7
7
|
import type { ContactoCliente } from '../types/contactos-clientes.js';
|
|
8
8
|
import type { MasterDataItem } from '../types/master-data.js';
|
|
9
9
|
import type { OportunidadNegocio } from '../types/oportunidades-negocio.js';
|
|
10
|
-
import type { VoContratosServMatAsignado } from '../types/contratos.js';
|
|
10
|
+
import type { VoContrato, VoContratoServicio, VoContratosOpcionales, VoContratosServMatAsignado, VoServiciosFac, VoServiciosFacTxt, VoServiciosHistPr } from '../types/contratos.js';
|
|
11
11
|
export interface ListResult<T> {
|
|
12
12
|
items: T[];
|
|
13
13
|
total: number;
|
|
@@ -601,6 +601,195 @@ export declare class FreematicaClient extends BaseClient {
|
|
|
601
601
|
traspasado?: string;
|
|
602
602
|
order?: string;
|
|
603
603
|
}): Promise<ListResult<Record<string, unknown>>>;
|
|
604
|
+
/**
|
|
605
|
+
* Lista paginada de cabeceras de contratos.
|
|
606
|
+
*
|
|
607
|
+
* Endpoint: GET /pvss/v1/contratos
|
|
608
|
+
*
|
|
609
|
+
* IMPORTANTE: este endpoint IGNORA silenciosamente el query param `rQuery`
|
|
610
|
+
* (verificado empíricamente contra el API real el 2026-07-02: con un filtro
|
|
611
|
+
* FIQL válido devuelve el dataset completo sin error). Por eso solo se
|
|
612
|
+
* exponen los filtros nativos `codEmpresa` y `codDelegacion`; cualquier otro
|
|
613
|
+
* filtrado debe hacerse en cliente (ver `getContrato`).
|
|
614
|
+
*
|
|
615
|
+
* @param opts - Paginación + filtros nativos empresa/delegación + order.
|
|
616
|
+
* @returns Lista paginada de cabeceras de contrato (campos CTRT_*).
|
|
617
|
+
*/
|
|
618
|
+
listContratos(opts?: ListOptions & {
|
|
619
|
+
empresa?: string;
|
|
620
|
+
delegacion?: string;
|
|
621
|
+
order?: string;
|
|
622
|
+
}): Promise<ListResult<VoContrato>>;
|
|
623
|
+
/**
|
|
624
|
+
* Busca una cabecera de contrato por sus códigos naturales.
|
|
625
|
+
*
|
|
626
|
+
* No existe un endpoint GET singular para contratos pvss y el listado ignora
|
|
627
|
+
* `rQuery`, así que se pagina el listado (items=200, máximo permitido por el
|
|
628
|
+
* API) filtrando en cliente por CTRT_COD hasta encontrar la coincidencia.
|
|
629
|
+
*
|
|
630
|
+
* @param opts - Códigos naturales del contrato.
|
|
631
|
+
* @returns Cabecera del contrato.
|
|
632
|
+
* @throws FreematicaError('not_found') si no existe.
|
|
633
|
+
*/
|
|
634
|
+
getContrato(opts: {
|
|
635
|
+
empresa: string;
|
|
636
|
+
delegacion?: string;
|
|
637
|
+
codContrato: string;
|
|
638
|
+
}): Promise<VoContrato>;
|
|
639
|
+
/**
|
|
640
|
+
* Lista paginada de servicios de un contrato.
|
|
641
|
+
*
|
|
642
|
+
* Endpoint: GET /pvss/v1/contratos/{idContrato}/servicios
|
|
643
|
+
*
|
|
644
|
+
* @param idContrato - idReg opaco del contrato (Base64 "EMP__DELEG__COD").
|
|
645
|
+
* @param opts - Paginación + order.
|
|
646
|
+
* @returns Lista paginada de servicios (campos CTRTS_*).
|
|
647
|
+
*/
|
|
648
|
+
listServiciosContrato(idContrato: string, opts?: ListOptions & {
|
|
649
|
+
order?: string;
|
|
650
|
+
}): Promise<ListResult<VoContratoServicio>>;
|
|
651
|
+
/**
|
|
652
|
+
* Detalle de un servicio de contrato por `idReg` opaco.
|
|
653
|
+
*
|
|
654
|
+
* Endpoint: GET /pvss/v2/contratos-servicios/{idreg}
|
|
655
|
+
*
|
|
656
|
+
* @param idReg - idReg opaco del servicio (Base64 "EMP__DELEG__CTRT__COD").
|
|
657
|
+
* @returns Servicio completo.
|
|
658
|
+
*/
|
|
659
|
+
getServicioContrato(idReg: string): Promise<VoContratoServicio>;
|
|
660
|
+
/**
|
|
661
|
+
* Lista paginada de opcionales de contratos.
|
|
662
|
+
*
|
|
663
|
+
* Endpoint: GET /ppre/v2/contratos/opcionales
|
|
664
|
+
*
|
|
665
|
+
* @param opts - Paginación + order.
|
|
666
|
+
* @returns Lista paginada de opcionales (campos CON2_*).
|
|
667
|
+
*/
|
|
668
|
+
listContratosOpcionales(opts?: ListOptions & {
|
|
669
|
+
order?: string;
|
|
670
|
+
}): Promise<ListResult<VoContratosOpcionales>>;
|
|
671
|
+
/**
|
|
672
|
+
* Detalle de un registro de opcionales de contrato por `idReg` opaco.
|
|
673
|
+
*
|
|
674
|
+
* Endpoint: GET /ppre/v2/contratos/opcionales/{idReg}
|
|
675
|
+
*/
|
|
676
|
+
getContratoOpcionales(idReg: string): Promise<VoContratosOpcionales>;
|
|
677
|
+
/**
|
|
678
|
+
* Alta de cabecera de contrato.
|
|
679
|
+
*
|
|
680
|
+
* Endpoint: POST /pvss/v2/contratos — body VoContratos.
|
|
681
|
+
* Campos requeridos por el API: CTRT_DELEG, CTRT_DES, CTRT_FECHA, CTRT_COD_CLI.
|
|
682
|
+
*
|
|
683
|
+
* @param body - Campos CTRT_* del contrato.
|
|
684
|
+
* @returns El contrato creado (VoContratos).
|
|
685
|
+
*/
|
|
686
|
+
createContrato(body: VoContrato): Promise<VoContrato>;
|
|
687
|
+
/**
|
|
688
|
+
* Actualización de cabecera de contrato.
|
|
689
|
+
*
|
|
690
|
+
* Endpoint: PUT /pvss/v2/contratos/{idReg} — body VoContratos.
|
|
691
|
+
*
|
|
692
|
+
* @param idReg - idReg opaco del contrato.
|
|
693
|
+
* @param body - Campos CTRT_* a actualizar.
|
|
694
|
+
* @returns Respuesta del API.
|
|
695
|
+
*/
|
|
696
|
+
updateContrato(idReg: string, body: VoContrato): Promise<VoContrato>;
|
|
697
|
+
/**
|
|
698
|
+
* Alta de un servicio en un contrato.
|
|
699
|
+
*
|
|
700
|
+
* Endpoint: POST /pvss/v2/contratos/{idReg}/servicios — body VoServicios.
|
|
701
|
+
* Campos requeridos por el API: CTRTS_EMP, CTRTS_DELEG, CTRTS_CTRT (los
|
|
702
|
+
* mismos valores codificados en el idReg del contrato).
|
|
703
|
+
*
|
|
704
|
+
* @param idContrato - idReg opaco del contrato.
|
|
705
|
+
* @param body - Campos CTRTS_* del servicio.
|
|
706
|
+
* @returns El servicio creado (VoServicios).
|
|
707
|
+
*/
|
|
708
|
+
createServicioContrato(idContrato: string, body: VoContratoServicio): Promise<VoContratoServicio>;
|
|
709
|
+
/**
|
|
710
|
+
* Actualiza fechas de inicio y fin de un servicio.
|
|
711
|
+
*
|
|
712
|
+
* Endpoint: PUT /pvss/v2/contratos/{idContrato}/servicio/{idServicio}.
|
|
713
|
+
* Según el spec, este endpoint solo actualiza fecha inicio y fecha fin.
|
|
714
|
+
*
|
|
715
|
+
* @param idContrato - idReg opaco del contrato.
|
|
716
|
+
* @param idServicio - idReg opaco del servicio.
|
|
717
|
+
* @param body - Campos CTRTS_* (fechas) a actualizar.
|
|
718
|
+
* @returns Respuesta del API.
|
|
719
|
+
*/
|
|
720
|
+
updateServicioFechas(idContrato: string, idServicio: string, body: VoContratoServicio): Promise<VoContratoServicio>;
|
|
721
|
+
/**
|
|
722
|
+
* Actualiza los datos de facturación de un servicio.
|
|
723
|
+
*
|
|
724
|
+
* Endpoint: PUT /pvss/v2/contratos/{idContrato}/servicios-facturacion/{idServicio}.
|
|
725
|
+
*
|
|
726
|
+
* @param idContrato - idReg opaco del contrato.
|
|
727
|
+
* @param idServicio - idReg opaco del servicio.
|
|
728
|
+
* @param body - Campos CTRTF_* a actualizar.
|
|
729
|
+
* @returns Respuesta del API.
|
|
730
|
+
*/
|
|
731
|
+
updateServicioFacturacion(idContrato: string, idServicio: string, body: VoServiciosFac): Promise<VoServiciosFac>;
|
|
732
|
+
/**
|
|
733
|
+
* Alta de un texto de facturación de un servicio.
|
|
734
|
+
*
|
|
735
|
+
* Endpoint: POST /pvss/v2/contratos/{idContrato}/servicios-facturacion-txt/{idServicio}.
|
|
736
|
+
*
|
|
737
|
+
* @param idContrato - idReg opaco del contrato.
|
|
738
|
+
* @param idServicio - idReg opaco del servicio.
|
|
739
|
+
* @param body - Campos CTRTFL_* del texto.
|
|
740
|
+
* @returns Respuesta del API.
|
|
741
|
+
*/
|
|
742
|
+
createServicioFacturacionTxt(idContrato: string, idServicio: string, body: VoServiciosFacTxt): Promise<VoServiciosFacTxt>;
|
|
743
|
+
/**
|
|
744
|
+
* Alta de un registro de histórico de precios de un servicio.
|
|
745
|
+
*
|
|
746
|
+
* Endpoint: POST /pvss/v2/contratos/{idContrato}/servicios-historico-precios/{idServicio}.
|
|
747
|
+
*
|
|
748
|
+
* @param idContrato - idReg opaco del contrato.
|
|
749
|
+
* @param idServicio - idReg opaco del servicio.
|
|
750
|
+
* @param body - Campos SERVHPR_* del histórico.
|
|
751
|
+
* @returns Respuesta del API (VoServiciosHistPr).
|
|
752
|
+
*/
|
|
753
|
+
createServicioHistoricoPrecios(idContrato: string, idServicio: string, body: VoServiciosHistPr): Promise<VoServiciosHistPr>;
|
|
754
|
+
/**
|
|
755
|
+
* Actualiza un registro de histórico de precios de un servicio.
|
|
756
|
+
*
|
|
757
|
+
* Endpoint: PUT /pvss/v2/contratos/{idContrato}/servicios-historico-precios/{idServicio}.
|
|
758
|
+
*
|
|
759
|
+
* @param idContrato - idReg opaco del contrato.
|
|
760
|
+
* @param idServicio - idReg opaco del servicio.
|
|
761
|
+
* @param body - Campos SERVHPR_* a actualizar.
|
|
762
|
+
* @returns Respuesta del API.
|
|
763
|
+
*/
|
|
764
|
+
updateServicioHistoricoPrecios(idContrato: string, idServicio: string, body: VoServiciosHistPr): Promise<VoServiciosHistPr>;
|
|
765
|
+
/**
|
|
766
|
+
* Alta de un registro de opcionales de contrato.
|
|
767
|
+
*
|
|
768
|
+
* Endpoint: POST /ppre/v2/contratos/opcionales — body VoContratosOpcionales.
|
|
769
|
+
* Campos requeridos por el API: CON2_CODEMP, CON2_DELEG, CON2_TIPOCONT,
|
|
770
|
+
* CON2_NUMCONT, CON2_FCHCONT.
|
|
771
|
+
*
|
|
772
|
+
* @param body - Campos CON2_* del registro.
|
|
773
|
+
* @returns El registro creado.
|
|
774
|
+
*/
|
|
775
|
+
createContratoOpcionales(body: VoContratosOpcionales): Promise<VoContratosOpcionales>;
|
|
776
|
+
/**
|
|
777
|
+
* Actualiza un registro de opcionales de contrato.
|
|
778
|
+
*
|
|
779
|
+
* Endpoint: PUT /ppre/v2/contratos/opcionales/{idReg}.
|
|
780
|
+
*
|
|
781
|
+
* @param idReg - idReg opaco del registro de opcionales.
|
|
782
|
+
* @param body - Campos CON2_* a actualizar.
|
|
783
|
+
* @returns Respuesta del API.
|
|
784
|
+
*/
|
|
785
|
+
updateContratoOpcionales(idReg: string, body: VoContratosOpcionales): Promise<VoContratosOpcionales>;
|
|
786
|
+
/**
|
|
787
|
+
* Log de auditoría de operaciones de escritura.
|
|
788
|
+
*
|
|
789
|
+
* Nivel info: operación + endpoint + claves del body (sin valores).
|
|
790
|
+
* Nivel debug: body completo, para poder reconstruir la operación.
|
|
791
|
+
*/
|
|
792
|
+
private logWrite;
|
|
604
793
|
private listResource;
|
|
605
794
|
/**
|
|
606
795
|
* Helper genérico para endpoints de lista que soportan paginación + filtros FIQL
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BaseClient } from './base-client.js';
|
|
1
|
+
import { BaseClient, FreematicaError } from './base-client.js';
|
|
2
2
|
import { buildFiql, appendRquery } from './fiql-builder.js';
|
|
3
3
|
import { CATALOG_ENDPOINTS } from '../schemas/master-data.js';
|
|
4
4
|
import { ESTADO_CARTERA_FIQL_MAP, } from '../schemas/cartera.js';
|
|
@@ -1239,6 +1239,286 @@ export class FreematicaClient extends BaseClient {
|
|
|
1239
1239
|
return { items: data.items, total: Number(data.total) };
|
|
1240
1240
|
}
|
|
1241
1241
|
// ---------------------------------------------------------------------------
|
|
1242
|
+
// Contratos y Servicios (v0.7.0) — lectura
|
|
1243
|
+
// ---------------------------------------------------------------------------
|
|
1244
|
+
/**
|
|
1245
|
+
* Lista paginada de cabeceras de contratos.
|
|
1246
|
+
*
|
|
1247
|
+
* Endpoint: GET /pvss/v1/contratos
|
|
1248
|
+
*
|
|
1249
|
+
* IMPORTANTE: este endpoint IGNORA silenciosamente el query param `rQuery`
|
|
1250
|
+
* (verificado empíricamente contra el API real el 2026-07-02: con un filtro
|
|
1251
|
+
* FIQL válido devuelve el dataset completo sin error). Por eso solo se
|
|
1252
|
+
* exponen los filtros nativos `codEmpresa` y `codDelegacion`; cualquier otro
|
|
1253
|
+
* filtrado debe hacerse en cliente (ver `getContrato`).
|
|
1254
|
+
*
|
|
1255
|
+
* @param opts - Paginación + filtros nativos empresa/delegación + order.
|
|
1256
|
+
* @returns Lista paginada de cabeceras de contrato (campos CTRT_*).
|
|
1257
|
+
*/
|
|
1258
|
+
async listContratos(opts = {}) {
|
|
1259
|
+
const url = new URL('https://placeholder/pvss/v1/contratos');
|
|
1260
|
+
if (opts.items !== undefined)
|
|
1261
|
+
url.searchParams.set('items', String(opts.items));
|
|
1262
|
+
if (opts.page !== undefined)
|
|
1263
|
+
url.searchParams.set('page', String(opts.page));
|
|
1264
|
+
if (opts.empresa !== undefined)
|
|
1265
|
+
url.searchParams.set('codEmpresa', opts.empresa);
|
|
1266
|
+
if (opts.delegacion !== undefined)
|
|
1267
|
+
url.searchParams.set('codDelegacion', opts.delegacion);
|
|
1268
|
+
if (opts.order !== undefined)
|
|
1269
|
+
url.searchParams.set('order', opts.order);
|
|
1270
|
+
const path = url.pathname + (url.search ? url.search : '');
|
|
1271
|
+
const data = await this.get(path);
|
|
1272
|
+
return { items: data.items, total: Number(data.total) };
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Busca una cabecera de contrato por sus códigos naturales.
|
|
1276
|
+
*
|
|
1277
|
+
* No existe un endpoint GET singular para contratos pvss y el listado ignora
|
|
1278
|
+
* `rQuery`, así que se pagina el listado (items=200, máximo permitido por el
|
|
1279
|
+
* API) filtrando en cliente por CTRT_COD hasta encontrar la coincidencia.
|
|
1280
|
+
*
|
|
1281
|
+
* @param opts - Códigos naturales del contrato.
|
|
1282
|
+
* @returns Cabecera del contrato.
|
|
1283
|
+
* @throws FreematicaError('not_found') si no existe.
|
|
1284
|
+
*/
|
|
1285
|
+
async getContrato(opts) {
|
|
1286
|
+
const PAGE_SIZE = 200;
|
|
1287
|
+
const MAX_PAGES = 100; // guardarraíl: 20.000 contratos
|
|
1288
|
+
for (let page = 1; page <= MAX_PAGES; page++) {
|
|
1289
|
+
const { items } = await this.listContratos({
|
|
1290
|
+
empresa: opts.empresa,
|
|
1291
|
+
delegacion: opts.delegacion,
|
|
1292
|
+
page,
|
|
1293
|
+
items: PAGE_SIZE,
|
|
1294
|
+
});
|
|
1295
|
+
const match = items.find((c) => String(c['CTRT_COD']) === opts.codContrato &&
|
|
1296
|
+
String(c['CTRT_EMP']) === opts.empresa &&
|
|
1297
|
+
(opts.delegacion === undefined || String(c['CTRT_DELEG']) === opts.delegacion));
|
|
1298
|
+
if (match)
|
|
1299
|
+
return match;
|
|
1300
|
+
if (items.length < PAGE_SIZE)
|
|
1301
|
+
break;
|
|
1302
|
+
}
|
|
1303
|
+
throw new FreematicaError('not_found', `Contrato no encontrado: empresa=${opts.empresa} delegacion=${opts.delegacion ?? '*'} codContrato=${opts.codContrato}`);
|
|
1304
|
+
}
|
|
1305
|
+
/**
|
|
1306
|
+
* Lista paginada de servicios de un contrato.
|
|
1307
|
+
*
|
|
1308
|
+
* Endpoint: GET /pvss/v1/contratos/{idContrato}/servicios
|
|
1309
|
+
*
|
|
1310
|
+
* @param idContrato - idReg opaco del contrato (Base64 "EMP__DELEG__COD").
|
|
1311
|
+
* @param opts - Paginación + order.
|
|
1312
|
+
* @returns Lista paginada de servicios (campos CTRTS_*).
|
|
1313
|
+
*/
|
|
1314
|
+
async listServiciosContrato(idContrato, opts = {}) {
|
|
1315
|
+
const url = new URL(`https://placeholder/pvss/v1/contratos/${encodeURIComponent(idContrato)}/servicios`);
|
|
1316
|
+
if (opts.items !== undefined)
|
|
1317
|
+
url.searchParams.set('items', String(opts.items));
|
|
1318
|
+
if (opts.page !== undefined)
|
|
1319
|
+
url.searchParams.set('page', String(opts.page));
|
|
1320
|
+
if (opts.order !== undefined)
|
|
1321
|
+
url.searchParams.set('order', opts.order);
|
|
1322
|
+
const path = url.pathname + (url.search ? url.search : '');
|
|
1323
|
+
const data = await this.get(path);
|
|
1324
|
+
return { items: data.items, total: Number(data.total) };
|
|
1325
|
+
}
|
|
1326
|
+
/**
|
|
1327
|
+
* Detalle de un servicio de contrato por `idReg` opaco.
|
|
1328
|
+
*
|
|
1329
|
+
* Endpoint: GET /pvss/v2/contratos-servicios/{idreg}
|
|
1330
|
+
*
|
|
1331
|
+
* @param idReg - idReg opaco del servicio (Base64 "EMP__DELEG__CTRT__COD").
|
|
1332
|
+
* @returns Servicio completo.
|
|
1333
|
+
*/
|
|
1334
|
+
async getServicioContrato(idReg) {
|
|
1335
|
+
return this.get(`/pvss/v2/contratos-servicios/${encodeURIComponent(idReg)}`);
|
|
1336
|
+
}
|
|
1337
|
+
/**
|
|
1338
|
+
* Lista paginada de opcionales de contratos.
|
|
1339
|
+
*
|
|
1340
|
+
* Endpoint: GET /ppre/v2/contratos/opcionales
|
|
1341
|
+
*
|
|
1342
|
+
* @param opts - Paginación + order.
|
|
1343
|
+
* @returns Lista paginada de opcionales (campos CON2_*).
|
|
1344
|
+
*/
|
|
1345
|
+
async listContratosOpcionales(opts = {}) {
|
|
1346
|
+
const url = new URL('https://placeholder/ppre/v2/contratos/opcionales');
|
|
1347
|
+
if (opts.items !== undefined)
|
|
1348
|
+
url.searchParams.set('items', String(opts.items));
|
|
1349
|
+
if (opts.page !== undefined)
|
|
1350
|
+
url.searchParams.set('page', String(opts.page));
|
|
1351
|
+
if (opts.order !== undefined)
|
|
1352
|
+
url.searchParams.set('order', opts.order);
|
|
1353
|
+
const path = url.pathname + (url.search ? url.search : '');
|
|
1354
|
+
const data = await this.get(path);
|
|
1355
|
+
return { items: data.items, total: Number(data.total) };
|
|
1356
|
+
}
|
|
1357
|
+
/**
|
|
1358
|
+
* Detalle de un registro de opcionales de contrato por `idReg` opaco.
|
|
1359
|
+
*
|
|
1360
|
+
* Endpoint: GET /ppre/v2/contratos/opcionales/{idReg}
|
|
1361
|
+
*/
|
|
1362
|
+
async getContratoOpcionales(idReg) {
|
|
1363
|
+
return this.get(`/ppre/v2/contratos/opcionales/${encodeURIComponent(idReg)}`);
|
|
1364
|
+
}
|
|
1365
|
+
// ---------------------------------------------------------------------------
|
|
1366
|
+
// Contratos y Servicios (v0.7.0) — escritura (create/update, sin delete)
|
|
1367
|
+
//
|
|
1368
|
+
// Todas las operaciones de escritura se registran en el log (nivel info con
|
|
1369
|
+
// la operación y claves del registro; nivel debug con el body completo) para
|
|
1370
|
+
// soportar auditoría y rollback manual.
|
|
1371
|
+
// ---------------------------------------------------------------------------
|
|
1372
|
+
/**
|
|
1373
|
+
* Alta de cabecera de contrato.
|
|
1374
|
+
*
|
|
1375
|
+
* Endpoint: POST /pvss/v2/contratos — body VoContratos.
|
|
1376
|
+
* Campos requeridos por el API: CTRT_DELEG, CTRT_DES, CTRT_FECHA, CTRT_COD_CLI.
|
|
1377
|
+
*
|
|
1378
|
+
* @param body - Campos CTRT_* del contrato.
|
|
1379
|
+
* @returns El contrato creado (VoContratos).
|
|
1380
|
+
*/
|
|
1381
|
+
async createContrato(body) {
|
|
1382
|
+
this.logWrite('createContrato', 'POST /pvss/v2/contratos', body);
|
|
1383
|
+
return this.post('/pvss/v2/contratos', body);
|
|
1384
|
+
}
|
|
1385
|
+
/**
|
|
1386
|
+
* Actualización de cabecera de contrato.
|
|
1387
|
+
*
|
|
1388
|
+
* Endpoint: PUT /pvss/v2/contratos/{idReg} — body VoContratos.
|
|
1389
|
+
*
|
|
1390
|
+
* @param idReg - idReg opaco del contrato.
|
|
1391
|
+
* @param body - Campos CTRT_* a actualizar.
|
|
1392
|
+
* @returns Respuesta del API.
|
|
1393
|
+
*/
|
|
1394
|
+
async updateContrato(idReg, body) {
|
|
1395
|
+
this.logWrite('updateContrato', `PUT /pvss/v2/contratos/${idReg}`, body);
|
|
1396
|
+
return this.put(`/pvss/v2/contratos/${encodeURIComponent(idReg)}`, body);
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* Alta de un servicio en un contrato.
|
|
1400
|
+
*
|
|
1401
|
+
* Endpoint: POST /pvss/v2/contratos/{idReg}/servicios — body VoServicios.
|
|
1402
|
+
* Campos requeridos por el API: CTRTS_EMP, CTRTS_DELEG, CTRTS_CTRT (los
|
|
1403
|
+
* mismos valores codificados en el idReg del contrato).
|
|
1404
|
+
*
|
|
1405
|
+
* @param idContrato - idReg opaco del contrato.
|
|
1406
|
+
* @param body - Campos CTRTS_* del servicio.
|
|
1407
|
+
* @returns El servicio creado (VoServicios).
|
|
1408
|
+
*/
|
|
1409
|
+
async createServicioContrato(idContrato, body) {
|
|
1410
|
+
this.logWrite('createServicioContrato', `POST /pvss/v2/contratos/${idContrato}/servicios`, body);
|
|
1411
|
+
return this.post(`/pvss/v2/contratos/${encodeURIComponent(idContrato)}/servicios`, body);
|
|
1412
|
+
}
|
|
1413
|
+
/**
|
|
1414
|
+
* Actualiza fechas de inicio y fin de un servicio.
|
|
1415
|
+
*
|
|
1416
|
+
* Endpoint: PUT /pvss/v2/contratos/{idContrato}/servicio/{idServicio}.
|
|
1417
|
+
* Según el spec, este endpoint solo actualiza fecha inicio y fecha fin.
|
|
1418
|
+
*
|
|
1419
|
+
* @param idContrato - idReg opaco del contrato.
|
|
1420
|
+
* @param idServicio - idReg opaco del servicio.
|
|
1421
|
+
* @param body - Campos CTRTS_* (fechas) a actualizar.
|
|
1422
|
+
* @returns Respuesta del API.
|
|
1423
|
+
*/
|
|
1424
|
+
async updateServicioFechas(idContrato, idServicio, body) {
|
|
1425
|
+
this.logWrite('updateServicioFechas', `PUT /pvss/v2/contratos/${idContrato}/servicio/${idServicio}`, body);
|
|
1426
|
+
return this.put(`/pvss/v2/contratos/${encodeURIComponent(idContrato)}/servicio/${encodeURIComponent(idServicio)}`, body);
|
|
1427
|
+
}
|
|
1428
|
+
/**
|
|
1429
|
+
* Actualiza los datos de facturación de un servicio.
|
|
1430
|
+
*
|
|
1431
|
+
* Endpoint: PUT /pvss/v2/contratos/{idContrato}/servicios-facturacion/{idServicio}.
|
|
1432
|
+
*
|
|
1433
|
+
* @param idContrato - idReg opaco del contrato.
|
|
1434
|
+
* @param idServicio - idReg opaco del servicio.
|
|
1435
|
+
* @param body - Campos CTRTF_* a actualizar.
|
|
1436
|
+
* @returns Respuesta del API.
|
|
1437
|
+
*/
|
|
1438
|
+
async updateServicioFacturacion(idContrato, idServicio, body) {
|
|
1439
|
+
this.logWrite('updateServicioFacturacion', `PUT /pvss/v2/contratos/${idContrato}/servicios-facturacion/${idServicio}`, body);
|
|
1440
|
+
return this.put(`/pvss/v2/contratos/${encodeURIComponent(idContrato)}/servicios-facturacion/${encodeURIComponent(idServicio)}`, body);
|
|
1441
|
+
}
|
|
1442
|
+
/**
|
|
1443
|
+
* Alta de un texto de facturación de un servicio.
|
|
1444
|
+
*
|
|
1445
|
+
* Endpoint: POST /pvss/v2/contratos/{idContrato}/servicios-facturacion-txt/{idServicio}.
|
|
1446
|
+
*
|
|
1447
|
+
* @param idContrato - idReg opaco del contrato.
|
|
1448
|
+
* @param idServicio - idReg opaco del servicio.
|
|
1449
|
+
* @param body - Campos CTRTFL_* del texto.
|
|
1450
|
+
* @returns Respuesta del API.
|
|
1451
|
+
*/
|
|
1452
|
+
async createServicioFacturacionTxt(idContrato, idServicio, body) {
|
|
1453
|
+
this.logWrite('createServicioFacturacionTxt', `POST /pvss/v2/contratos/${idContrato}/servicios-facturacion-txt/${idServicio}`, body);
|
|
1454
|
+
return this.post(`/pvss/v2/contratos/${encodeURIComponent(idContrato)}/servicios-facturacion-txt/${encodeURIComponent(idServicio)}`, body);
|
|
1455
|
+
}
|
|
1456
|
+
/**
|
|
1457
|
+
* Alta de un registro de histórico de precios de un servicio.
|
|
1458
|
+
*
|
|
1459
|
+
* Endpoint: POST /pvss/v2/contratos/{idContrato}/servicios-historico-precios/{idServicio}.
|
|
1460
|
+
*
|
|
1461
|
+
* @param idContrato - idReg opaco del contrato.
|
|
1462
|
+
* @param idServicio - idReg opaco del servicio.
|
|
1463
|
+
* @param body - Campos SERVHPR_* del histórico.
|
|
1464
|
+
* @returns Respuesta del API (VoServiciosHistPr).
|
|
1465
|
+
*/
|
|
1466
|
+
async createServicioHistoricoPrecios(idContrato, idServicio, body) {
|
|
1467
|
+
this.logWrite('createServicioHistoricoPrecios', `POST /pvss/v2/contratos/${idContrato}/servicios-historico-precios/${idServicio}`, body);
|
|
1468
|
+
return this.post(`/pvss/v2/contratos/${encodeURIComponent(idContrato)}/servicios-historico-precios/${encodeURIComponent(idServicio)}`, body);
|
|
1469
|
+
}
|
|
1470
|
+
/**
|
|
1471
|
+
* Actualiza un registro de histórico de precios de un servicio.
|
|
1472
|
+
*
|
|
1473
|
+
* Endpoint: PUT /pvss/v2/contratos/{idContrato}/servicios-historico-precios/{idServicio}.
|
|
1474
|
+
*
|
|
1475
|
+
* @param idContrato - idReg opaco del contrato.
|
|
1476
|
+
* @param idServicio - idReg opaco del servicio.
|
|
1477
|
+
* @param body - Campos SERVHPR_* a actualizar.
|
|
1478
|
+
* @returns Respuesta del API.
|
|
1479
|
+
*/
|
|
1480
|
+
async updateServicioHistoricoPrecios(idContrato, idServicio, body) {
|
|
1481
|
+
this.logWrite('updateServicioHistoricoPrecios', `PUT /pvss/v2/contratos/${idContrato}/servicios-historico-precios/${idServicio}`, body);
|
|
1482
|
+
return this.put(`/pvss/v2/contratos/${encodeURIComponent(idContrato)}/servicios-historico-precios/${encodeURIComponent(idServicio)}`, body);
|
|
1483
|
+
}
|
|
1484
|
+
/**
|
|
1485
|
+
* Alta de un registro de opcionales de contrato.
|
|
1486
|
+
*
|
|
1487
|
+
* Endpoint: POST /ppre/v2/contratos/opcionales — body VoContratosOpcionales.
|
|
1488
|
+
* Campos requeridos por el API: CON2_CODEMP, CON2_DELEG, CON2_TIPOCONT,
|
|
1489
|
+
* CON2_NUMCONT, CON2_FCHCONT.
|
|
1490
|
+
*
|
|
1491
|
+
* @param body - Campos CON2_* del registro.
|
|
1492
|
+
* @returns El registro creado.
|
|
1493
|
+
*/
|
|
1494
|
+
async createContratoOpcionales(body) {
|
|
1495
|
+
this.logWrite('createContratoOpcionales', 'POST /ppre/v2/contratos/opcionales', body);
|
|
1496
|
+
return this.post('/ppre/v2/contratos/opcionales', body);
|
|
1497
|
+
}
|
|
1498
|
+
/**
|
|
1499
|
+
* Actualiza un registro de opcionales de contrato.
|
|
1500
|
+
*
|
|
1501
|
+
* Endpoint: PUT /ppre/v2/contratos/opcionales/{idReg}.
|
|
1502
|
+
*
|
|
1503
|
+
* @param idReg - idReg opaco del registro de opcionales.
|
|
1504
|
+
* @param body - Campos CON2_* a actualizar.
|
|
1505
|
+
* @returns Respuesta del API.
|
|
1506
|
+
*/
|
|
1507
|
+
async updateContratoOpcionales(idReg, body) {
|
|
1508
|
+
this.logWrite('updateContratoOpcionales', `PUT /ppre/v2/contratos/opcionales/${idReg}`, body);
|
|
1509
|
+
return this.put(`/ppre/v2/contratos/opcionales/${encodeURIComponent(idReg)}`, body);
|
|
1510
|
+
}
|
|
1511
|
+
/**
|
|
1512
|
+
* Log de auditoría de operaciones de escritura.
|
|
1513
|
+
*
|
|
1514
|
+
* Nivel info: operación + endpoint + claves del body (sin valores).
|
|
1515
|
+
* Nivel debug: body completo, para poder reconstruir la operación.
|
|
1516
|
+
*/
|
|
1517
|
+
logWrite(operation, endpoint, body) {
|
|
1518
|
+
logger.info({ operation, endpoint, fields: Object.keys(body) }, 'freematica write');
|
|
1519
|
+
logger.debug({ operation, endpoint, body }, 'freematica write body');
|
|
1520
|
+
}
|
|
1521
|
+
// ---------------------------------------------------------------------------
|
|
1242
1522
|
// Internal helpers
|
|
1243
1523
|
// ---------------------------------------------------------------------------
|
|
1244
1524
|
async listResource(path, opts) {
|