ingreso-documentos-effi

star 0

Ingresa documentos a Effi (https://effi.com.co) a partir de un origen externo (PDF factura proveedor, pedido cliente, planilla ajuste, mensaje WhatsApp, dictado). Cubre remisiones de compra, cotizaciones de venta, remisiones/facturas de venta, notas crédito, ajustes y traslados de inventario. Usa cuando el usuario adjunta o describe cualquier documento o transacción comercial para registrar en Effi. Aplica el flujo de 10 pasos antecedentes → análisis → mapeo → identificar raro → decidir → JSON → dry-run → POST → verificación rigurosa de totales y detalles.

larevo1111 By larevo1111 schedule Updated 6/5/2026

name: ingreso-documentos-effi description: Ingresa documentos a Effi (https://effi.com.co) a partir de un origen externo (PDF factura proveedor, pedido cliente, planilla ajuste, mensaje WhatsApp, dictado). Cubre remisiones de compra, cotizaciones de venta, remisiones/facturas de venta, notas crédito, ajustes y traslados de inventario. Usa cuando el usuario adjunta o describe cualquier documento o transacción comercial para registrar en Effi. Aplica el flujo de 10 pasos antecedentes → análisis → mapeo → identificar raro → decidir → JSON → dry-run → POST → verificación rigurosa de totales y detalles.

Ingreso de documentos a Effi

Workflow universal para registrar CUALQUIER transacción comercial en Effi a partir de un origen externo. Cada tipo de documento (compra, venta, ajuste, traslado) usa este mismo flujo, solo cambia la referencia técnica específica.

Saltarse el orden = errores costosos. El paso 1-2 (antecedentes) es el más importante y el que más se omite.

⚠️ Regla cero

NUNCA construir el JSON sin antes investigar cómo se han ingresado transacciones similares. Cada par (tercero × tipo de documento × item) tiene una "tradición" en OS (qué cods, cómo agrupar líneas, qué unidades, qué cuenta/caja). Esa tradición es la verdad — el documento externo es solo materia prima.

Mapa: tipo de documento → referencia técnica

Identificá primero qué tipo de transacción es. Después seguí el flujo de 10 pasos abajo usando el archivo de referencia correspondiente para los campos del endpoint:

Origen / intención Tipo Effi Endpoint Referencia técnica
Factura de proveedor (compra) Remisión de compra /app/remision_c/crear reference/remision_compra.md
Cotización a cliente Cotización de venta /app/cotizacion/crear reference/cotizacion_venta.md (crear al primer caso)
Entrega física a cliente Remisión de venta /app/remision/crear reference/remision_venta.md (crear al primer caso)
Documento fiscal a cliente Factura de venta /app/factura/crear reference/factura_venta.md (crear al primer caso)
Devolución cliente con factura Nota crédito de venta /app/nota_credito_v/crear reference/nota_credito_venta.md (crear al primer caso)
Mercancía entre bodegas Traslado de inventario /app/traslado_inventario/crear reference/traslado_inventario.md (crear al primer caso)
Sobrante/faltante físico Ajuste de inventario /app/ajuste_inventario/crear reference/ajuste_inventario.md (crear al primer caso)
Transformación interna Orden de producción /app/orden_produccion/crear usar skill produccion-recetas + effi-tecnico

Para detalles transversales (autenticación, sesión, scraping, formato números/fechas, espionaje de endpoints) → usar skill effi-tecnico.


Workflow universal — checklist obligatorio

Copiá este checklist y marcá cada paso al completarlo:

Progreso ingreso:
- [ ] Paso 1: Antecedentes del TERCERO (NIT + variaciones nombre + ID Effi real)
- [ ] Paso 2: Antecedentes del TIPO DE DOCUMENTO con este tercero (últimas 3-5)
- [ ] Paso 3: Análisis de líneas del documento fuente
- [ ] Paso 4: Mapeo cods/conceptos externos → cods Effi
- [ ] Paso 5: Identificar lo RARO (4 sub-casos — ver §5)
- [ ] Paso 6: Decidir lo raro (descifrar con más data O preguntar a Santi)
- [ ] Paso 7: Construir JSON con campos del endpoint específico
- [ ] Paso 8: Dry-run + validación numérica INDEPENDIENTE de montos
- [ ] Paso 9: POST a Effi (interpretar errores e iterar)
- [ ] Paso 10: VERIFICACIÓN — TOTALES primero, DETALLES después

Paso 1 — Antecedentes del tercero

Buscar al tercero por TODAS las pistas:

SELECT _pk, nombre, numero_de_identificacion, forma_de_pago, fecha_ultima_compra
FROM zeffi_proveedores       -- o zeffi_clientes
WHERE numero_de_identificacion LIKE '%<NIT_sin_guiones>%'
   OR nombre LIKE '%<keyword1>%'
   OR nombre LIKE '%<keyword2>%'

⚠️ El nombre en factura suele diferir del nombre Effi (ej: factura dice "UNION COMERCIAL ROPTIE S.A.", Effi tiene "UNICOR S.A.").

Obtener el ID Effi REAL (_pk local ≠ ID que el form espera):

import re
r = s.get('https://effi.com.co/app/<modulo>')
# Buscar documento histórico del tercero → su data-<tercero>
# Regex: capturar data-id y data-proveedor/cliente con cualquier comilla
patron = r'data-id=. (\\d+).\\S* data-(proveedor|cliente)=. (\\d+)'
# (en código real: data-id="(\d+)"...data-(proveedor|cliente)="(\d+)")
m = re.search(patron, r.text)  # m.group(3) = ID Effi del tercero

Si el tercero no tiene NINGÚN documento histórico → opciones:

  • Crear el primer documento manualmente desde la UI para que su data-* quede registrado
  • O scrapear listado paginado de proveedores/clientes

Ver patrones específicos en reference/terceros_conocidos.md.


Paso 2 — Antecedentes del documento con este tercero

Antes de mapear códigos, revisar las 3-5 últimas transacciones del MISMO TIPO con el MISMO tercero:

-- Remisiones de compra (ejemplo):
SELECT id_remision, fecha_de_compra, remision_del_proveedor, total_bruto, total_neto, observacion
FROM zeffi_remisiones_compra_encabezados
WHERE proveedor LIKE '%<tercero>%'
ORDER BY CAST(id_remision AS UNSIGNED) DESC LIMIT 5;

-- Detalle de cada una:
SELECT cod_articulo, descripcion, cantidad, precio_bruto_unitario
FROM zeffi_remisiones_compra_detalle WHERE id_remision='<id>';

Identificar patrones:

  • Cods recurrentes que ese tercero suele suministrar/comprar
  • Cómo se agrupan líneas (¿envases con tapa juntos? ¿granel y empacado separados?)
  • Rangos típicos de cantidad y precio
  • Forma de pago habitual
  • Bodega típica
  • Observaciones recurrentes

Paso 3 — Análisis de líneas del documento fuente

Para cada línea del PDF/origen, extraer:

Dato Notas
Código interno del tercero (no nos sirve directo, sirve para cross-reference)
Descripción exacta clave para mapeo
UDM (unidad de medida) PAQUETE, CAJA, KG, UND, LT
Cantidad en UDM número
Precio por UDM número
Valor total línea para validar cálculo
% IVA o tasa aplicada 19%, 5%, Exento, etc.
Lote/serie si aplica número o vacío

⚠️ UDM atípicas — conversión: si UDM dice PAQUETE X N UNIDADES, en Effi cantidad = cant_paq × N y precio = precio_paq / N.

Ejemplo: 3 PAQUETE × 24 unid × $20,640 = $61,920 → Effi: cantidad=72, precio=$860.


Paso 4 — Mapeo cods externos → cods Effi

Estrategia en orden de prioridad:

  1. Histórico con el MISMO tercero (del Paso 2) — si la descripción matchea, usar ese cod.
  2. Histórico con OTROS terceros (importante si el tercero actual no tiene ese item):
    SELECT d.cod_articulo, d.descripcion, e.proveedor, COUNT(*) usos
    FROM zeffi_remisiones_compra_detalle d
    JOIN zeffi_remisiones_compra_encabezados e ON d.id_remision=e.id_remision
    WHERE d.descripcion LIKE '%<keyword>%' AND d.vigencia='Vigente'
    GROUP BY d.cod_articulo, d.descripcion, e.proveedor
    ORDER BY usos DESC;
    
  3. Búsqueda directa en catálogo:
    SELECT id, nombre, categoria, costo_manual, stock_total_empresa
    FROM zeffi_inventario
    WHERE vigencia='Vigente' AND nombre LIKE '%<keyword1>%' AND nombre LIKE '%<keyword2>%'
    
  4. Glosario OS (SL/LT/SC, abreviaturas) → reference/glosario_origensilvestre.md

Validar cada mapeo: el cod elegido debería tener al menos 1-2 transacciones históricas (con el mismo o con otro tercero).


Paso 5 — Identificar lo RARO

Antes de construir el JSON, clasificar cada línea como estándar o rara. Si es rara, identificar a cuál de estos 4 sub-casos pertenece (cada uno tiene tratamiento distinto en el Paso 6):

Sub-caso A: Item habitual del tercero, agrupación atípica

El item es estándar de este tercero, pero la factura lo presenta agrupado distinto (ej: tapas que normalmente vienen incluidas en el envase, ahora separadas).

Pista: comparar con la línea equivalente en remisiones anteriores del mismo tercero. Si tradicionalmente venía agrupado → AGRUPAR igual en Effi (consolidar precio en una sola línea con el cod del item principal).

Caso conocido — envases UNICOR + sus tapas: tradicionalmente OS ingresa envase + tapa en UNA SOLA LÍNEA con el cod del envase y precio combinado, aunque la factura las traiga separadas.

Sub-caso B: Item NO habitual del tercero pero SÍ habitual de OTRO tercero

El tercero está bien identificado, pero este item normalmente viene de otro proveedor. Usualmente es compra de emergencia / sustituto temporal (el proveedor habitual no tenía disponibilidad).

Pista: el item probablemente sí está en el catálogo Effi con un cod existente (el cod del proveedor habitual). Buscar:

-- 1) ¿Existe en catálogo?
SELECT id, nombre, categoria FROM zeffi_inventario
WHERE vigencia='Vigente' AND nombre LIKE '%<keyword>%';
-- 2) ¿Quién lo suministra normalmente?
SELECT e.proveedor, COUNT(*) usos, MAX(e.fecha_de_compra) ultima
FROM zeffi_remisiones_compra_detalle d
JOIN zeffi_remisiones_compra_encabezados e ON d.id_remision=e.id_remision
WHERE d.cod_articulo='<cod>' GROUP BY e.proveedor ORDER BY usos DESC;

→ Usar el cod existente (no crear cod nuevo). Anotar en la observacion de la línea: "Compra a <tercero> por desabasto de <proveedor habitual>". Esto deja trazabilidad de la sustitución para el análisis de costos futuros.

Sub-caso C: Item genuinamente nuevo (nunca antes comprado/vendido a NADIE)

No existe en el catálogo Effi para ningún cod equivalente, o no hay histórico.

Acción: PARAR. Antes de cargar la transacción, crear el cod en Effi (/app/articulo/crear — ver skill effi-tecnico §3). Después de creado, usar el cod nuevo en la línea.

Sub-caso D: Cantidad o precio atípicos (>20% del histórico)

Item conocido con cod conocido, pero el valor está muy fuera del rango normal.

Pista: investigar antes de cargar — ¿descuento puntual? ¿error de UDM? ¿cambio de presentación? ¿oferta?

Acción: confirmar con Santi o con el proveedor antes de cargar (un precio 30% más alto cargado por error queda mal en costos por meses).


Paso 6 — Decidir lo raro

Para cada línea rara, según su sub-caso:

Sub-caso Acción
A (agrupación atípica) Consolidar/separar según tradición histórica
B (sustituto temporal) Usar cod existente + anotar sustitución en observación de línea
C (item nuevo) Crear cod en Effi primero, luego usarlo
D (valor atípico) Confirmar con Santi/proveedor antes de cargar

Si la pista histórica es ambigua o conflictiva → PREGUNTAR a Santi, mostrándole:

  • Las líneas raras tal como vienen en el documento
  • Las líneas equivalentes en transacciones previas (para comparar)
  • Tu propuesta de resolución
  • La ambigüedad concreta

No improvisar nunca. Un supuesto silencioso genera un descuadre que se descubre meses después en un inventario, multiplicado por cada vez que aplicaste ese supuesto.


Paso 7 — Construir JSON

Estructura específica por tipo de documento en reference/<tipo>.md. Reglas universales:

  • Fechas: formato según endpoint (OPs DD/MM/YYYY, compras YYYY-MM-DD). Ver effi-tecnico §5.
  • Números: punto decimal en JSON; Effi internamente usa coma.
  • t_egreso y cod_articulo mutuamente excluyentes (compras): si hay cod, "t_egreso": "default".
  • descripcion obligatorio cuando hay cod_articulo — usar nombre EXACTO de zeffi_inventario.nombre.
  • impuestos: ["1"] = IVA 19% (ver tabla completa en effi-tecnico §3).
  • valor en formas_pago EXACTO con subtotal + impuestos − retenciones calculados. Effi rechaza diferencias de centavos.
  • proveedor_id/cliente_id = ID Effi (Paso 1), NO _pk local.

Paso 8 — Dry-run + validación montos

python3 scripts/import_<tipo>_post.py /tmp/<documento>.json --dry-run

Validación numérica INDEPENDIENTE (no del script):

import json
d = json.load(open('/tmp/<documento>.json'))
sub = sum(c['cantidad']*c['precio'] for c in d['conceptos'])
iva = sum(c['cantidad']*c['precio']*0.19 for c in d['conceptos'] if '1' in c['impuestos'])
total = sub + iva
print(f'SUBTOTAL = ${sub:,.2f}  (documento: $X)')
print(f'IVA      = ${iva:,.2f}  (documento: $X)')
print(f'TOTAL    = ${total:,.2f}  (documento: $X)')

Aceptable: diferencias ≤ $1 por redondeo del proveedor. Diferencias mayores → revisar precios unitarios (suele faltar precisión decimal).


Paso 9 — POST a Effi e interpretar errores

python3 scripts/import_<tipo>_post.py /tmp/<documento>.json

Esperar <TIPO>_CREADA:<id>. Si HTTP 200 pero <p> en body, leer mensaje y corregir.

Errores genéricos:

Mensaje Causa probable Fix
"Ha ocurrido un error al procesar..." proveedor_id/cliente_id inválido Usar ID Effi (Paso 1), no _pk
"La suma de... debe ser igual al total..." valor no cuadra con subtotal+IVA Recalcular y poner valor exacto
"El campo X es obligatorio" Falta campo en concepto Agregar (típicamente descripcion)
"No puedes seleccionar Artículo y Tipo de egreso al mismo tiempo" t_egreso ≠ "default" cuando hay cod "t_egreso": "default"

Errores específicos por tipo → en reference/<tipo>.md.


Paso 10 — VERIFICACIÓN rigurosa (obligatorio, sin excepciones)

Primero TOTALES, después DETALLES.

10a. Sync BD

cd scripts && node export_<tipo>.js && cd ..
node scripts/import_all.js | grep <tipo>
python3 scripts/sync_a_vps.py --tablas <tipo>_encabezados,<tipo>_detalle

10b. Verificación TOTALES (cabecera)

SELECT id_<tipo>, <campos relevantes>, total_bruto, impuestos, total_neto, estado
FROM zeffi_<tipo>_encabezados WHERE id_<tipo>='<id_creada>'

Cuadrar contra documento fuente:

  • total_bruto (sin IVA) ✓
  • impuestos (IVA) ✓
  • total_neto (con IVA) — aceptar diff ≤ $1 por redondeo del proveedor
  • Datos del tercero ✓
  • Fechas ✓
  • Estado correcto ✓

Si NO cuadra: NO declarar éxito. Investigar.

10c. Verificación DETALLES (líneas)

SELECT cod_articulo, descripcion, cantidad, precio_bruto_unitario, precio_neto_total
FROM zeffi_<tipo>_detalle WHERE id_<tipo>='<id_creada>' ORDER BY CAST(cod_articulo AS UNSIGNED)

Por cada línea:

  • cantidad × precio_bruto_unitario = subtotal línea ✓
  • precio_neto_total = subtotal × (1 + tasa_iva) ✓
  • cod_articulo y descripcion corresponden al item ✓

Si NO cuadra: anular la transacción y reintentar con corrección.


Materiales de referencia

Para flujo técnico Effi (sesión, scraping, espionaje de endpoints, formato números/fechas) → skill effi-tecnico. Para producción → skills produccion-recetas + effi-tecnico.

Anti-patrones

❌ Construir JSON sin revisar histórico del tercero (Pasos 1-2) ❌ Asumir que items "separados en documento" van separados en Effi (ej: tapas UNICOR) ❌ Crear cod nuevo cuando ya existe uno equivalente (ej: comprarle envase 750 a sustituto y crear cod paralelo) ❌ Usar _pk local de BD como ID del tercero (Effi usa otro ID) ❌ Poner t_egreso: "1" cuando hay cod_articulo ❌ Declarar éxito sin verificar totales+detalles en BD post-creación ❌ Saltarse "lo raro" en lugar de identificar a cuál sub-caso (A/B/C/D) pertenece ❌ Aceptar diferencias >$1 entre documento y BD sin investigar ❌ Crear el documento múltiples veces "porque no cargó" sin verificar primero

Install via CLI
npx skills add https://github.com/larevo1111/Integraciones_OS --skill ingreso-documentos-effi
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator