TiFactura · Notificador AFIP — informe de revisión
Ciclo de revisión del 2026-08-27 sobre el build v20260827: tus 4 consultas iniciales (memoria/CPU, puerto, CUIT, "PercIVA=99" de ALMACOR), la auditoría profunda de los IDs de impuestos hasta la respuesta viva de ARCA, y un Judgment Day delta con dos jueces ciegos.
01 — Primero lo importante
Sin maquillaje. Ordenado de más grave a menor. Cada ítem dice quién lo encontró y cómo quedó resuelto.
El config-template de ejemplo tenía comind: 4, impinterno: 5, iva: 6/7/8 — valores de demo, no del catálogo ARCA. Como estos IDs viajan tal cual al XML fiscal (<ar:Tributo><ar:Id>, verificado en el código del Manager), un copy-paste sin revisar habría mandado códigos de impuesto incorrectos a ARCA. Lo detectaste vos comparando contra tu config de producción legada.
Quedó: el template trae los códigos correctos (2/3/4/99, IVA 3/4/5) con la tabla oficial completa comentada, la fuente de cada valor, y el sello de la verificación en vivo. Ver Sección 03.
client: almacor venía pre-cargado: un instalador que editaba el password pero olvidaba el cliente levantaba un servicio emitiendo los tributos equivocados (ej.: un DINO facturando Impuesto Interno en vez de Percepción IVA). Lo confirmaron los dos jueces del Judgment Day.
Quedó: client: CHANGE_ME — el servicio se niega a arrancar hasta poner un cliente válido (doble fail-fast verificado: constructor + inyección condicional).
El template y la doc decían que los códigos de tributo 2/3/4 salían "del manual oficial" — pero el PDF no imprime el catálogo de tributos (solo evidencia los de IVA y el 99). Los valores eran correctos, la cita no. Encontrado por ambos jueces, de forma independiente.
Quedó: cada valor con su fuente honesta — y superado con creces: verificación en vivo contra el WS (Sección 03).
Buscaba el jar solo en target\ (repo de desarrollo) — en una instalación real (jar descargado del Release, al lado del .bat) fallaba con "No jar found". Además: el copy del bootstrap no chequeaba errores y el echo hardcodeaba el puerto 8080.
Quedó: busca el jar primero al lado del script, después en target\; copy verificado; mensajes sin puerto fijo. Lógica cmd.exe revisada línea por línea por los jueces (sin trampas de expansión).
Tu medición era real — pero no era un leak: sin -Xmx, la JVM dimensiona el heap según la RAM total del host. En máquinas grandes el proceso se infla sin necesitarlo.
Quedó: run.bat lanza con -Xms64m -Xmx256m. Medido: ~400 MB de proceso total (vs ~650). Sobra para los 6 clientes.
Medido acá: en reposo el consumo de CPU es 0% (el tiempo de CPU acumulado quedó congelado entre muestras). Lo que viste fue: el arranque (~30-40 s de JIT, normal), o el cron de dev — que dispara cada 1 segundo (* * * ? * *, heredado de los 6 originales, solo con perfil dev) — o una corrida procesando backlog real.
Quedó: producción usa el cron del YML externo (cada 5 min). El footgun de dev quedó documentado en el troubleshooting de /doc. El cockpit muestra el cron activo y la próxima corrida.
(a) No había forma de cambiar el 8080 si estaba ocupado. (b) El ente viajaba solo anidado (enteFacturador:{id}) — el Manager lo descarta y resuelve por fallback (funciona con 1 comercio; con 2+ daría error 500). Gap heredado de los 6 originales, no introducido por la unificación.
Quedó: server.port en el YML (+ troubleshooting "Port already in use"); nueva propiedad opcional tifactura.cuit que viaja top-level (el Manager resuelve por CUIT, v2). Vacía = comportamiento legacy intacto, goldens sin cambios. Visible en /status.
Dos confusiones en una: (1) ALMACOR no emite Percepción de IVA — su columna fmontopercepcionci es percepción Comercio e Industria (nombre traicionero); (2) el "99" no era un valor raro: es el código ARCA "Otro", que es exactamente cómo viaja la Percepción de IVA (en DINO y CARACOL) — Id 99 + descripción, dentro de <ar:Tributos>, no en el bloque de IVA.
Quedó: documentado en /doc con el formato XML exacto. Configurar perciva en ALMACOR no hace nada (su estrategia no lo lee) — si un día lo necesitara, es cambio de estrategia + columnas, no config.
Al arrancar con client: CHANGE_ME (o cualquier fallo de arranque), el contexto Spring moría pero el JVM quedaba vivo, con el puerto tomado, respondiendo 404 — el operador reintentaba y se comía "Port already in use". Lo encontró la batería E2E de esta revisión (los dos jueces del Judgment Day lo habían pasado por alto: verificaron que el contexto fallara, no que el proceso muriera).
Quedó: Application.main hace salida dura (System.exit(1)) ante cualquier fallo de arranque. Re-testeado: proceso muerto, puerto libre, cero javas vivos.
Pill de versión vacía en el cockpit antes del primer fetch · comillas de id.iva sin anotar (sacarlas rompe el arranque) · inconsistencias internas del manual (Sección 06 vs 07 sobre run.bat). Todo corregido.
02 — El job
| Ambiente | Valor | Dónde vive | Cómo cambiarlo |
|---|---|---|---|
| Producción | 0 0/5 * * * ? (cada 5 min) | YML externo config\application-prod.yml | Editar el YML y reiniciar — sin recompilar |
| Desarrollo | * * * ? * * (cada 1 segundo ⚠) | application-dev.properties (dentro del jar, solo perfil dev) | Editar esa línea; heredado de los 6 originales, solo para debug |
03 — Lo que más te preocupaba
Cuatro niveles de evidencia, todos coincidentes. El último es el definitivo: llamamos de verdad a FEParamGetTiposTributos y FEParamGetTiposIva (login WSAA con tu certificado de homologación, 2026-08-27).
| Id | Descripción | Vigente desde | ¿Lo usás? |
|---|---|---|---|
| 1 | Impuestos nacionales | 2010 | — |
| 2 | Impuestos provinciales | 2010 | ✓ ing.bruto (IIBB) |
| 3 | Impuestos municipales | 2010 | ✓ comind |
| 4 | Impuestos Internos | 2010 | ✓ impinterno |
| 5 | IIBB (específico) | 2017 | alternativa a 2 — cambio deliberado |
| 6 | Percepción de IVA (específico) | 2017 | alternativa a 99 — cambio deliberado |
| 7-9, 13 | Percepciones varias | 2017 | — |
| 99 | Otro (+ Desc "PERCEPCION IVA…") | 2010 | ✓ perciva |
04 — Cómo quedó
Un archivo por instalación, fuera del jar. Lo nuevo de este ciclo, marcado:
# config\application-prod.yml — al lado del jar (lo bootstrapea run.bat) tifactura: client: CHANGE_ME # NUEVO: no arranca hasta poner un cliente válido (fail-fast) cuit: "" # NUEVO: CUIT top-level p/ resolución v2 en el Manager (opcional) server: port: 8080 # NUEVO: cambiable si el puerto está ocupado spring: datasource: # TipreRetail (dino/almacor/becerra/tiziano) o TipreSucursales (caracol/cyre) url: jdbc:sqlserver://localhost:1433;databaseName=TipreRetail username: sa password: CHANGE_ME notify.to.afip.cron.scheduler: "0 0/5 * * * ?" # el job, cada 5 min id: # NUEVO: códigos oficiales + tabla ARCA completa comentada ente.facturador: 1 # id interno del Manager (NO es código ARCA) tributo: ing.bruto: 2 # Impuestos provinciales — VERIFICADO EN VIVO comind: 3 # Impuestos municipales — VERIFICADO EN VIVO impinterno: 4 # Impuestos Internos — VERIFICADO EN VIVO (no usar 10) perciva: 99 # "Otro" + Desc — así viaja la Percepción de IVA iva: { "0": 3, "105": 4, "21": 5 } # comillas obligatorias (anotado)
El template real (config-template\application-prod.yml) trae además la tabla oficial completa, las fuentes de cada valor y el sello de verificación en vivo.
05 — El sello