# Integración con Contifico (Facturación electrónica Ecuador)

> Documento de referencia técnica para retomar rápidamente el trabajo sobre la
> integración contable/facturación con Contifico.
> Última actualización de este análisis: 2026-10-08.

## 1. Propósito del proceso

La carpeta `contifico/` expone un conjunto de endpoints que sirven de
**puente entre la base de datos transaccional de Ecuador (Informix/SICE) y
la API externa de Contifico** (`https://api.contifico.com/sistema/api/v1/`),
un sistema de facturación electrónica y contabilidad usado por Automundial
Ecuador para timbrar documentos ante el SRI.

Se usa para:

- Sincronizar clientes y productos entre SICE y Contifico (creación
  automática si no existen).
- Generar en Contifico, a partir de un documento de SICE, y enviar al SRI:
  - Facturas (`FAC`)
  - Notas de crédito (`NCT`) por anulación de factura
  - Notas de crédito (`NCT`) por devolución de mercadería
  - Guías de remisión (inventario)

## 2. Archivos involucrados

| Archivo | Rol |
|---|---|
| `contifico/create_customer.php` | Proxy simple: recibe un JSON de cliente y lo reenvía a `POST /persona/` de Contifico. |
| `contifico/create_product.php` | Proxy simple: recibe un JSON de producto y lo reenvía a `POST /producto/` de Contifico. |
| `contifico/get_customers.php` | Proxy simple: consulta `GET /persona/?identificacion=` en Contifico. |
| `contifico/get_products.php` | Proxy simple: consulta `GET /producto/?codigo=` en Contifico. |
| `contifico/get_customer.php` | **Archivo vacío** (sin lógica). No usado. |
| `contifico/get_productos.php` | **Archivo vacío** (sin lógica). No usado. |
| `contifico/create_document.php` | Orquestador de **facturación**: arma y envía una factura (`FAC`) a Contifico y la timbra ante el SRI. |
| `contifico/create_document_credit_note.php` | Orquestador de **nota de crédito por anulación**: liga la NC a la factura original y la timbra. |
| `contifico/create_document_credit_note_return.php` | Orquestador de **nota de crédito por devolución de mercadería**: similar al anterior, con montos invertidos. |
| `contifico/create_document_shipping_guide.php` | Orquestador de **guía de remisión**: crea documento de inventario en Contifico (no se timbra ante el SRI, esa línea está comentada). |
| `lib/dao/famovDAO.php`, `siciaDAO.php`, `cncreDAO.php`, `fadevDAO.php`, `famovdetDAO.php`, `facliDAO.php`, `cbmovdetDAO.php` | Acceso a datos de SICE (Informix): cabeceras/detalles de facturas, notas de crédito, devoluciones, clientes, formas de pago. |
| `lib/param.inc.php` | Constantes de conexión a BD y credenciales de Contifico: `TOKEN_CONTIFICO` (POS), `API_KEY_CONTIFICO` (Authorization), `CATEGORY_ID_CONTIFICO` (categoría por defecto de productos nuevos). |
| `error_http.php` | Helpers `render_ws()` / `render_error()` para dar formato a las respuestas HTTP. |
| `generarLog.php` | Escribe el log mensual en texto plano (`log/contifico_*<AAAAMM>.txt`). |
| `lib/funcionesGenerales/envioCorreo.php` | Envío de correo de alerta cuando Contifico responde con error. |

Base de datos origen: **Informix** (SICE Ecuador), accedida vía `conexionDB.php`
con el objeto global `$DBe`.

## 3. Dos capas de la integración

### 3.1 Capa de "proxy" (CRUD directo contra Contifico)

`create_customer.php`, `create_product.php`, `get_customers.php`,
`get_products.php` son endpoints delgados: reciben la petición del cliente,
añaden las cabeceras de autenticación (`Authorization: <API_KEY_CONTIFICO>`)
y la reenvían tal cual a Contifico, devolviendo la respuesta. Sirven como
intermediarios para no exponer la API key de Contifico al front/otros
consumidores, y son invocados internamente por la capa de orquestación
(punto 3.2) vía HTTP, apuntando a sí mismos (`$enviroment` =
`api.automundial.app/app` o `/restApi`, hay inconsistencia entre archivos,
ver sección 6).

### 3.2 Capa de orquestación (generación de documentos)

Los 4 archivos `create_document*.php` siguen el mismo patrón general:

```
GET ?movdoc=<numero>-<ubicacion>
   │
   ├─▶ 1. Leer de Informix la cabecera/detalle del documento origen
   │        (factura, nota de crédito, devolución o guía)
   │
   ├─▶ 2. Resolver CLIENTE en Contifico
   │        └─ GET  contifico/get_customers.php?identificacion=<cedula/ruc>
   │        └─ si no existe → POST contifico/create_customer.php (lo crea)
   │
   ├─▶ 3. Resolver cada PRODUCTO en Contifico
   │        └─ GET  contifico/get_products.php?codigo=<codigo>
   │        └─ si no existe → POST contifico/create_product.php (lo crea)
   │
   ├─▶ 4. Armar el payload del documento (factura/NC/guía) con los
   │        IDs de cliente y productos ya resueltos en Contifico
   │
   ├─▶ 5. POST https://api.contifico.com/.../documento/  (crea el documento)
   │        (para guía: POST .../inventario/guia/)
   │
   └─▶ 6. PUT  https://api.contifico.com/.../documento/<id>/sri/
            (envía el documento a autorización del SRI; la guía NO hace este paso, está comentado)
```

El identificador `movdoc` llega como query string con formato
`"<numero_documento>-<ubicacion>"` (p.ej. `12345-810`), donde `810`/`820`
son los códigos de local que se traducen a punto de emisión/establecimiento
SRI (`001-001` y `002-003` respectivamente; cualquier otro valor cae en
`---`, ver `getEmisionPoint()`/`getLocation()`).

### 3.3 Detalle por tipo de documento

**`create_document.php` (Factura)**
- Lee: `SiciaDAO::getInformationTax`, `FamovDAO::getInvoiceRem/getInvoicePurchasing/getDetailInvoice2`, `CbmovdetDAO::getPaymentType`.
- Calcula IVA (15%), base gravable y total por línea, truncando/formateando a 2 decimales.
- Determina el tipo de cliente (`N` natural / `J` jurídico) a partir del 3er dígito de la cédula/RUC.
- Arma la forma de cobro (`EF` efectivo, `TC` tarjeta, `CQ` cheque, `TRA` transferencia) según el campo de forma de pago de SICE.
- Envía la factura (`tipo_documento=FAC`, `estado=P`, `electronico=true`) y luego la autoriza ante el SRI.

**`create_document_credit_note.php` (Nota de crédito por anulación)**
- Lee de `CncreDAO` (cabecera/detalle/total/iva de la nota de crédito) y `FamovDAO::getInvoiceSimple` (factura relacionada).
- Busca el `id` de la factura original en Contifico vía `GET /registro/documento/?tipo_registro=CLI&fecha_emision=...&persona_identificacion=...&tipo=FAC` y filtra por número de documento compuesto.
- Si la factura relacionada **no existe aún en Contifico**, hace un reintento automático: llama a `create_document.php` para crearla primero y luego reintenta el envío de la nota de crédito (máx. 2 intentos, variable `$attempts`).
- Envía `tipo_documento=NCT` con `documento_relacionado_id` apuntando a la factura.

**`create_document_credit_note_return.php` (Nota de crédito por devolución)**
- Variante de la anterior, pero el origen es una devolución de mercadería (`FadevDAO`/`FamovdetDAO`) en vez de una nota de crédito contable. Los montos/cantidades se invierten con `*-1` porque el movimiento de devolución en SICE se registra en signo contrario.
- Misma lógica de reintento ante factura relacionada inexistente en Contifico.

**`create_document_shipping_guide.php` (Guía de remisión)**
- Lee `FamovDAO::headerShippingGuide/detailShippingGuide`.
- Resuelve **dos** personas en Contifico: el destinatario (cliente) y el transportista (`desnit`), creándolos si no existen.
- Arma el payload de `POST /inventario/guia/` con `bodega_id` fijo (`"nRMdR6gzBfqZdl6Y"`), motivo (`VENTA` o `TRASLADO ENTRE BODEGAS` según `destip`) y limpia tildes/símbolos del campo "ruta" con `eliminar_simbolos()`.
- **No** llama al paso de autorización SRI (línea `sendSRI()` comentada): las guías de remisión no se timbran como facturas.

## 4. Autenticación y configuración

Las credenciales se definen como constantes globales en `lib/param.inc.php`
(no se repiten aquí por seguridad, ver ese archivo):

- `TOKEN_CONTIFICO` → identificador del punto de venta (`pos`), se envía en el body de cada documento y en la query de `get_customers`/creación de clientes.
- `API_KEY_CONTIFICO` → token enviado en el header `Authorization` de todas las llamadas directas a `api.contifico.com`.
- `CATEGORY_ID_CONTIFICO` → categoría por defecto usada al crear un producto nuevo en Contifico.

Hay credenciales de un ambiente anterior comentadas en el mismo archivo,
indicando que ya hubo al menos una rotación de llaves/entorno de Contifico.

## 5. Manejo de errores y logging

Cada endpoint define su propio archivo de log mensual en texto plano bajo
`log/contifico_<proceso><AAAAMM>.txt` (vía `GenerarLog::modificarLog`) y,
ante respuestas no exitosas de Contifico, envía un correo de alerta
(`EnvioCorreo::enviarCorreoOffice365_2` o `enviarCorreoAtwplus`) a una
dirección de técnico/contabilidad configurada en cada archivo.

Mapeo de respuesta HTTP → resultado (función `errorServices`, duplicada en
cada orquestador):

| HTTP Contifico | Resultado | Acción |
|---|---|---|
| 200 / 201 | `Ok` | Log informativo, sin correo |
| 400 | `BadRequest` | Log + correo de alerta |
| 404 | `BadRequest` | Log + correo de alerta |
| 409 | `Conflict` | Log + correo de alerta |
| otro | `NotImplemented` | Log + correo de alerta |

En `create_document_credit_note*.php`, un error 400 con mensaje
`"id incorrecto"` dispara un **reintento automático** (crear primero la
factura relacionada) antes de reportar el error final.

## 6. Observaciones de la validación (riesgos / inconsistencias detectadas)

- **`$enviroment` inconsistente entre archivos**: `create_document.php` usa
  `api.automundial.app/restApi`, mientras que los otros 3 orquestadores usan
  `api.automundial.app/app` (ambos están hardcodeados y la alternativa queda
  comentada). Si ambos hosts no exponen exactamente la misma carpeta
  `contifico/`, las llamadas internas a `get_customers.php` /
  `create_customer.php` / etc. pueden fallar silenciosamente.
- **Credenciales hardcodeadas** en `lib/param.inc.php` (no en variables de
  entorno), incluyendo un juego de llaves anterior comentado en el mismo
  archivo.
- **`error_reporting(0)`** está activo en casi todos los endpoints
  (excepto `create_document.php`), lo que oculta warnings/notices de PHP
  que podrían señalar datos faltantes (por ejemplo, índices inexistentes
  en arrays de Informix) y dificulta el diagnóstico en producción.
- **Salida de depuración (`print_r`/`echo`) mezclada con la respuesta JSON**:
  los orquestadores imprimen trazas de depuración (`print_r($data)`,
  `echo "-starting customer"`, etc.) directamente al *response body* antes
  del `header('Content-Type: application/json')` efectivo, lo que puede
  romper el parseo JSON por parte de quien consuma estos endpoints.
- **Sin validación de entrada**: `$_REQUEST['movdoc']` se usa directamente
  con `explode('-', ...)` sin verificar que el parámetro exista o tenga el
  formato esperado; un `movdoc` mal formado genera `Undefined offset`
  silenciado por `error_reporting(0)` y continúa ejecutándose con datos
  parciales.
- **Lógica de negocio duplicada** (más de 10 funciones idénticas o casi
  idénticas: `calculateDocumentNumber`, `getEmisionPoint`, `getLocation`,
  `customerType`, `fomatDate`, `preparateDataCustomer`,
  `getCustomerPartner`, `createCustomerPartner`, `getProductPartner`,
  `createProductPartner`, `errorServices`...) copiada y pegada en los 4
  archivos de orquestación, en vez de extraerse a una librería común
  (`lib/contifico/...`). Esto implica que cualquier corrección (p.ej. un
  bug en el cálculo de IVA) debe replicarse manualmente en cada archivo.
- **Mapeo de tipo de persona (`N`/`J`) frágil**: se basa en comparar el
  3er carácter de la cédula/RUC como dígito (`$documentNumber[2] < 6`) en
  vez de usar la longitud del documento (10 = cédula/natural, 13 = RUC) o
  una validación de dígito verificador.
- **Guías de remisión sin envío a SRI**: la llamada a `sendSRI()` está
  comentada en `create_document_shipping_guide.php`; si el proceso de
  negocio requiere que la guía quede autorizada electrónicamente, falta
  ese paso (puede ser intencional si Contifico autoriza las guías de otra
  forma, pero no hay comentario que lo aclare).
- **Archivos muertos**: `get_customer.php` y `get_productos.php` están
  vacíos; se recomienda eliminarlos o implementarlos si en algún momento
  fueron pensados como variantes singulares de `get_customers.php` /
  `get_products.php`.
- **Reintentos limitados y acoplados por variables globales**: el mecanismo
  de reintento en las notas de crédito usa `global $InfoCreditNote` /
  `global $invoiceDocument` dentro de funciones (`sendInvoice`), lo cual
  funciona pero acopla fuertemente el flujo y dificulta testear estas
  funciones de forma aislada.

## 7. Resumen de endpoints

| Endpoint | Método | Parámetro principal | Qué hace |
|---|---|---|---|
| `contifico/get_customers.php` | GET | `identificacion` | Busca persona en Contifico |
| `contifico/create_customer.php` | POST | body JSON persona | Crea persona en Contifico |
| `contifico/get_products.php` | GET | `codigo` | Busca producto en Contifico |
| `contifico/create_product.php` | POST | body JSON producto | Crea producto en Contifico |
| `contifico/create_document.php` | GET | `movdoc=<num>-<loc>` | Genera y timbra una factura |
| `contifico/create_document_credit_note.php` | GET | `movdoc=<num>-<loc>` | Genera y timbra una NC por anulación |
| `contifico/create_document_credit_note_return.php` | GET | `movdoc=<num>-<loc>` | Genera y timbra una NC por devolución |
| `contifico/create_document_shipping_guide.php` | GET | `movdoc=<num>-<loc>` | Genera una guía de remisión (sin timbrar) |
