Guías de tareas¶
Recetas concretas para tareas puntuales. A diferencia de la Referencia (que describe qué hay) o de Entender el sistema (que explica por qué), acá el foco es cómo hago X, paso a paso.
Casi todo esto pega contra AFIP homologación
Las recetas de CAE/CAEA asumen el perfil dev (AFIP en HOMOLOGACION) y el backend arriba. Nunca corras un "test de prueba" apuntando a producción: algunos endpoints emiten comprobantes reales. Si no tenés el backend levantado, mirá primero Setup del entorno.
Backend¶
Emitir un CAE de prueba¶
Emite una Factura B de Consumidor Final por $121 (neto 100 + IVA 21) contra AFIP homologación, para un POS configurado.
- Asegurate de tener un
SucPosPVcargado (ver más abajo) y de saber susuc/pos. - Pegale al test runner del cockpit:
- La respuesta trae
{ok, durationMs, comprobante, cae, resultado, caeFchVto, traffic}.resultado: "A"= aprobado. El bloquetraffictiene el XML SOAP exacto que se mandó/recibió de ARCA.
Probar el anti-doble-facturación
Reenviá el mismo nroTicketPos y vas a recibir el CAE existente en vez de uno nuevo: ejercita la idempotencia del flujo real (fecaeSolicitarNextGen).
Es un CAE real en homologación
El backend loguea un WARN ruidoso ([COCKPIT-CAE-PRUEBA] EMITIENDO CAE REAL…). Solo usalo en el ambiente de prueba. Detalle en Cockpit.
Configurar un SucPosPV¶
SucPosPV mapea sucursal + POS físico → punto de venta AFIP. El ABM va gateado por secret.
- Definí el secret al arrancar (env var
COCKPIT_ADMIN_SECRET, ya está enrun.bat). Sin secret, el ABM responde503. - Dá de alta el mapeo (mandando el secret en el header
X-Cockpit-Secret):curl -X POST http://localhost:8080/api/cockpit/sucpospv ^ -H "X-Cockpit-Secret: %COCKPIT_ADMIN_SECRET%" ^ -H "Content-Type: application/json" ^ -d "{\"suc\": 1, \"pos\": 1, \"pvcae\": 3, \"pvcaea\": 4}"pvcaeaes opcional (un POS puede facturar solo CAE). - Verificá la lista:
- (Opcional) Validá los PV contra AFIP a demanda:
curl -X POST http://localhost:8080/api/cockpit/sucpospv/1/validar-arca ^ -H "X-Cockpit-Secret: %COCKPIT_ADMIN_SECRET%"409= el PV no existe o está bloqueado en AFIP;502= AFIP no respondió.
Detalle de códigos y revalidación en Cockpit.
Correr el smoke contra AFIP homologación¶
El smoke pega contra la red real de AFIP con el cert .p12. Está gateado (@EnabledIfSystemProperty): no corre en el mvn test normal.
:: atajo del repo (equivale al comando de abajo)
tt.bat
:: o explícito:
mvn -o test -Dtest=AfipHomologacionSmokeTest -Dafipsmoke=true -Dafip.p12.password=<clave-del-p12>
AfipHomologacionSmokeTest hace el flujo end-to-end de lectura: WSAA LoginCms (firma CMS → token) + WSFE FECompUltimoAutorizado (read-only, no emite).
El TA tiene cooldown — corré el smoke UNA vez
AFIP rechaza el re-login si ya hay un TA vigente ("ya posee un TA valido") por ~12 h. El propio test lo avisa. No lo corras en loop. La clave del .p12 va por system property (-Dafip.p12.password=…), nunca en el repo.
Hay smoke tests hermanos para otros flujos: CaeaHomologacionSmokeTest (CAEA) y, contra DB real, CockpitRealDbSmokeTest / RealDbSchemaValidationTest (perfil realdb, gateados aparte).
Ver el estado de los jobs¶
Devuelve una fila por job con cron, ultimaEjecucion, resultado (OK/ERROR), error y proximaEjecucion. Para entender qué hace cada job y cómo dar de alta uno nuevo, mirá Jobs Quartz.
Despliegue (Windows)¶
Instalar como servicio con NSSM¶
En producción el backend corre como servicio de Windows (arranca solo con el sistema, se reinicia ante caídas, no depende de una consola abierta). Usamos NSSM (Non-Sucking Service Manager), que envuelve java.exe como servicio con apagado graceful, logs rotados y arranque automático.
Prerequisitos
- El fat jar
tifactura-spring.jarya compilado en elAppDirectory(generalo conmvn -DskipTests package— debe ser el jar de Spring Boot, no el "thin jar"). - JDK instalado (apuntá
java.exea la versión con la que validaste el jar; ver nota de versión abajo). - NSSM en el
PATH(o invocalo con su ruta completa). - La base SQL Server accesible y las variables de entorno configuradas (ver más abajo — el servicio no usa
run.bat). - Creá la carpeta de logs antes de arrancar:
mkdir c:\Work\TiFacturaOnlineNext\logs.
Registro y configuración del servicio (corré en una consola como administrador):
nssm install TiFacturaOnlineNext "c:\Program Files\Java\jdk-21\bin\java.exe"
nssm set TiFacturaOnlineNext AppParameters "-Dserver.shutdown=graceful -Dspring.lifecycle.timeout-per-shutdown-phase=15s -jar tifactura-spring.jar"
nssm set TiFacturaOnlineNext AppDirectory "c:\Work\TiFacturaOnlineNext"
nssm set TiFacturaOnlineNext Start SERVICE_AUTO_START
nssm set TiFacturaOnlineNext AppStdout "c:\Work\TiFacturaOnlineNext\logs\service.out.log"
nssm set TiFacturaOnlineNext AppStderr "c:\Work\TiFacturaOnlineNext\logs\service.err.log"
nssm set TiFacturaOnlineNext AppRotateFiles 1
nssm set TiFacturaOnlineNext AppRotateOnline 1
nssm set TiFacturaOnlineNext AppRotateBytes 10485760
nssm set TiFacturaOnlineNext AppStopMethodConsole 20000
nssm set TiFacturaOnlineNext AppStopMethodWindow 5000
nssm set TiFacturaOnlineNext AppStopMethodThreads 5000
nssm set TiFacturaOnlineNext DisplayName "TiFactura Online (Spring)"
nssm set TiFacturaOnlineNext Description "Backend facturacion AFIP - Spring Boot (java directo, graceful shutdown)"
Las variables de entorno son obligatorias — el servicio no lee run.bat
Corriendo como servicio no existen las variables que setea run.bat. Cargalas con AppEnvironmentExtra (una línea, pares CLAVE=valor) antes de iniciar, o el arranque falla (DB, secret del ABM, auth del cockpit):
nssm set TiFacturaOnlineNext AppEnvironmentExtra ^
DB_PASS=tu_password ^
COCKPIT_ADMIN_SECRET=tu_secret ^
COCKPIT_USER=tu_usuario ^
COCKPIT_PASS=tu_clave
DB_USER, DB_HOST, AFIP_CUIT, etc.). Detalle de cada una en Configuración y perfiles.
Qué hace cada parámetro clave
-Dserver.shutdown=graceful+timeout-per-shutdown-phase=15s— al frenar el servicio, Spring deja terminar las requests/jobs en curso (hasta 15 s) antes de cerrar. Importante para no cortar una emisión de CAE a la mitad.AppStopMethodConsole 20000— NSSM le da 20 s a la app para apagarse sola (envía Ctrl-C) antes de forzar; es mayor que los 15 s de Spring a propósito, para que el graceful complete. Recién después prueba cerrar ventana (...Window) y matar hilos (...Threads).AppRotate*— rotaservice.out.log/service.err.logal superar 10 MB (AppRotateBytes), incluso en caliente (AppRotateOnline).Start SERVICE_AUTO_START— arranca con Windows.
Operar el servicio¶
nssm start TiFacturaOnlineNext :: iniciar
nssm stop TiFacturaOnlineNext :: detener (graceful)
nssm restart TiFacturaOnlineNext :: reiniciar
nssm status TiFacturaOnlineNext :: estado (SERVICE_RUNNING / SERVICE_STOPPED)
nssm edit TiFacturaOnlineNext :: editar la config en una ventana
nssm remove TiFacturaOnlineNext confirm :: desinstalar el servicio
También sirven los comandos nativos de Windows (sc start TiFacturaOnlineNext, services.msc). Tras arrancar, verificá: el cockpit en http://localhost:8080/cockpit y el log en c:\Work\TiFacturaOnlineNext\logs\service.out.log.
La versión de Java tiene que ser la soportada
El ejemplo apunta a jdk-21, pero usá la misma versión con la que validaste el jar. El proyecto compila para Java 17 y es sensible a la versión del runtime (con un JDK demasiado nuevo el arranque puede romper). Antes de instalar el servicio, confirmá que el jar levanta a mano con ese java.exe:
Documentación¶
Correr esta doc en local¶
Abrí http://127.0.0.1:8000. mkdocs serve recarga en vivo al editar.
Validar que no haya links rotos¶
Antes de pushear:
Exportar la doc a un PDF¶
El sitio se exporta a un único PDF (con portada, índice y los diagramas Mermaid renderizados) vía mkdocs-exporter. La primera vez hay que instalar el Chromium headless:
El export está desactivado por defecto (para que serve/build sean rápidos). Se activa con la variable PDF_EXPORT:
El PDF queda en site/pdf/tifacturaonline-documentacion.pdf.
Mermaid y el separador ;
Mermaid usa ; como separador de sentencias: no uses ; dentro del texto de un nodo o el diagrama no compila (usá <br/> para saltos de línea). La portada vive en pdf-cover.html y el hook que renderiza Mermaid en el PDF es docs/assets/wait-mermaid.js — no lo borres.
Por dónde seguir¶
- Setup del entorno — levantar el backend de cero.
- Cockpit y Jobs Quartz — la referencia de los endpoints que usás acá.
- El ciclo de facturación — qué significan CAE, CAEA y los resultados que ves.