Saltar a contenido

Modelo de dominio

Entidades JPA y enums-tabla AFIP del backend. Todas son POJOs anotados con jakarta.persistence.*, viven en com.tipre.tifacturaonlinemanager.model.** y mapean tablas que administra el cliente (hbm2ddl=none). Para cómo se persisten ver Persistencia; para las reglas de negocio que las atan, Ciclo de facturación e Invariantes.

Fidelidad al esquema legacy

Los nombres de tabla/columna se respetan literalmente (PascalCase) con @Table/@Column. No hay snake_case: la naming strategy es PhysicalNamingStrategyStandardImpl. Varias entidades vienen generadas por Hibernate Tools del legacy y conservan imports Jackson 1.x (org.codehaus.jackson) que no se migran en Fase 1.

Mapa de entidades

Entidad Tabla Paquete Rol
Trx Trx model.trx Comprobante / transacción de facturación. Raíz del agregado.
TrxDetalle TrxDetalle model.trx Ítem de línea del comprobante.
AlicuotaIva Iva model.trx Alícuota de IVA del comprobante.
Tributo Tributos model.trx Tributo (otro impuesto) del comprobante.
Opcional Opcionales model.trx Dato opcional AFIP (clave/valor).
ComprobanteAsociado ComprobantesAsociados model.trx Comprobante asociado (NC/ND → factura original).
Caea Caeas model.trx CAEA otorgado por AFIP.
CaeaSinMovimiento CaeaSinMovimientos model.trx Informe "sin movimiento" de un PV bajo un CAEA.
EnteFacturador EntesFacturadores model Comercio emisor (cert AFIP por comercio).
SucPosPV SucPosPV model Mapeo sucursal+POS ↔ PV CAE/CAEA de AFIP.
Tarea Tareas model.tarea Definición de un job Quartz.
JobEjecucion JobEjecucion model.job Bitácora de cada corrida de un job.
TrxErrorLog TrxErrorLog model.error Log de errores para la grilla del cockpit.
TipoComprobante TiposComprobante model.afip Tipo de comprobante AFIP (enum-tabla).
TipoDocumento TiposDocumento model.afip Tipo de documento del receptor.
TipoConcepto TiposConcepto model.afip Concepto (productos/servicios/ambos).
TipoIva TiposIva model.afip Alícuota IVA catálogo.
TipoMoneda TiposMonedas model.afip Moneda.
TipoTributo TiposTributo model.afip Tipo de tributo.

Trx — el comprobante

Raíz del agregado de facturación. Id autogenerado (IDENTITY). Conserva tanto los datos de entrada (receptor, importes, ítems) como los valores devueltos por AFIP (cae, caeFchVto, fchProceso, caeBarCode, caea, caeaFchTope, resultado).

Campos clave (@Table(name = "Trx")):

Campo Columna Tipo Nota
id id Integer PK IDENTITY.
enteFacturador idEnteFacturador @ManyToOne LAZY, nullable=false Comercio emisor.
ptoVta ptoVta int Punto de venta.
tipoComprobante idTipoComprobante @ManyToOne LAZY, nullable=false
tipoConcepto idTipoConcepto @ManyToOne LAZY, nullable=false
tipoDocumento idTipoDocumento @ManyToOne LAZY, nullable=false
nroDocumento nroDocumento long DNI o CUIT/CUIL del receptor.
razonSocial, direccion, localidad, condicionIva idem String Datos del receptor.
comprobante comprobante Long Número de comprobante.
comprobanteFecha comprobanteFecha String Formato YYYYMMDD.
importeTotal, importeTotConc, importeNeto, importeOpEx, importeTributo, importeIva idem double Totales (neto no gravado / gravado / exento / suma tributos / suma IVA).
fechaServicioDesde/Hasta, fechaVencimientoPago idem String YYYYMMDD.
tipoMoneda idTipoMoneda @ManyToOne LAZY, nullable=false
montoCotizacion montoCotizacion double 1 para PES.
cae, caeFchVto, fchProceso, caeBarCode idem String Valores devueltos por AFIP.
caea, caeaFchTope idem String Si se facturó por CAEA.
resultado resultado String Resultado AFIP.
cbteFchHsGen cbteFchHsGen String Fecha-hora generación.
condicionIVAReceptorId condicionIVAReceptorId int Condición IVA del receptor (RG nueva).
email, medioPago, medioPagoCuota/Cupon/Autorizacion, observaciones idem String Datos comerciales.
comprobanteRelacionado comprobanteRelacionado String Para NC/ND.
nroTicketPos, nroSuc, nroPos idem String / Integer Origen POS.
version, reintentos, tipofacturacion, trxoriginal idem String/Integer/Long Metadatos de procesamiento.

Relaciones @OneToMany (LAZY, mappedBy="trx", cascade=REMOVE): alicuotaIvas, tributos, opcionales, comprobantesAsociados, trxDetalles (este último con @OrderBy("id")).

Lógica embebida en la entidad

Trx tiene un @PreUpdate que, si hay cae y caeFchVto, calcula caeBarCode con calculoDigitoVerificador(cuit, codComp, ptoVta, cae, vtoCae) (algoritmo del código de barras AFIP). También expone helpers @Transient: getFullComprobante(), getFullFullComprobante(), getComprobanteFechaDMY/YMD(), getCaeFchVtoDMY(), getMedioPagoFull().

Hijos de Trx

TrxDetalle (@Table(name = "TrxDetalle"))

Ítem de línea. PK id IDENTITY. trx (@ManyToOne LAZY, nullable=false, @JsonIgnore+@XmlTransient), tipoIva (@ManyToOne). Campos: ean, descripcion (String); cantidad, precioNetoUnitario, impuestoInternoUnitario, precioTotal (Double).

AlicuotaIva (@Table(name = "Iva"))

PK id IDENTITY. trx (@ManyToOne LAZY, nullable=false), tipoIva (@ManyToOne). Campos: baseImponible, importe (double).

Tributo (@Table(name = "Tributos"))

PK id IDENTITY. trx (@ManyToOne LAZY), tipoTributo (@ManyToOne). Campos: descripcion (String), baseImponible, alicuota, importe (double). Helper @Transient getDescripcionFull() (anexa (%alicuota) si > 0).

Opcional (@Table(name = "Opcionales"))

Ojo con la PK: el campo identidad se llama uid y mapea la columna uid (IDENTITY). El campo id (String) es el código del dato opcional AFIP, no la PK. valor (String) es el contenido. trx (@ManyToOne LAZY, nullable=false).

CAEA

Caea (@Table(name = "Caeas"))

CAEA otorgado por AFIP. PK natural: caea (String), no autogenerada. enteFacturador (@ManyToOne LAZY, nullable=false, @JsonIgnore/@XmlTransient). Campos: periodo, orden (Integer); fchVigDesde, fchVigHasta, fchTopeInf, fchProceso (String); movimientos (Integer, default 0, @JsonIgnore/@XmlTransient). Constantes: PERIODO_FORMAT_YYYYMM, FCH_FORMAT_YYYYMMDD, QUINCENA_1=1, QUINCENA_2=2.

CaeaSinMovimiento (@Table(name = "CaeaSinMovimientos"))

Informe "sin movimiento" de un PV bajo un CAEA. Clave compuesta vía @IdClass(CaeaSinMovimientoId.class): caea (String) + enteFacturador (@ManyToOne LAZY, parte del id) + ptoVta (int). Campo fchProceso (Date, default new Date()).

EnteFacturador (@Table(name = "EntesFacturadores"))

Comercio emisor. PK id IDENTITY. Es donde vive la config AFIP por comercio: el cert ya no sale del .yml.

Campo Columna Nota
razonSocial razonSocial (unique)
cuit cuit helper @Transient getCuitAsLong().
direccion, condicionIva, ingresosBrutos, inicioActividades idem Datos fiscales.
backGroundHeaderPath, backGroundFacturaPath, emailPath, layout idem Render de PDF/email.
token, sign idem (length=2000) TA de WSAA cacheado (@XmlTransient).
expirationTime expirationTime (@Temporal TIMESTAMP) Vencimiento del TA.
habilitado habilitado (booleanbit)
certP12Path, certP12Password, certP12Alias idem (@XmlTransient) Certificado AFIP por comercio (antes en afip.cert.*). Si alias vacío se usa el CUIT.

SucPosPV (@Table(name = "SucPosPV"))

Relaciona Sucursal + POS físico con los nros de PV de AFIP. PK id IDENTITY. UQ (suc, pos) → el lookup devuelve a lo sumo 1 fila.

Campo Columna Nota
suc, pos suc, pos (nullable=false) Sucursal y POS físico.
pvcae pvcae (nullable=false) PV de AFIP para CAE.
pvcaea pvcaea (Integer, nullable) PV de AFIP para CAEA.
validadoArcaPvcae validadoArcaPVCae (@Temporal TIMESTAMP) Fecha validación del PV CAE contra AFIP (FEParamGetPtosVenta). null = no validado.
validadoArcaPvcaea validadoArcaPVCaea (@Temporal TIMESTAMP) Idem CAEA.
fechaUltObtencionPos fFechaUltObtencionPOS (@Temporal TIMESTAMP) Handoff de una sola vez: getCaea lo sella; el ABM lo resetea a null ante cualquier cambio.

Tarea / JobEjecucion / TrxErrorLog

Tarea (@Table(name = "Tareas"))

Definición de un job Quartz. PK id (String, @NotNull). Campos: descripcion, programacion (cron, @NotNull), jobProcessor (clase del job, @NotNull).

JobEjecucion (@Table(name = "JobEjecucion"))

Bitácora de una corrida de un job (la graba CommonJob al terminar; el cockpit muestra la última por job). PK id IDENTITY. Campos: tareaId (String, nullable=false, length=100), jobNombre (String, length=200), inicio (@Temporal TIMESTAMP, nullable=false), fin (@Temporal TIMESTAMP), resultado ('OK'|'ERROR', length=10), error (String, length=2000).

TrxErrorLog (@Table(name = "TrxErrorLog"))

Error de transacción para la grilla del cockpit. Dos orígenes: 'AFIP' (servicio→ARCA, lo graba CockpitMetrics.recordError) y 'POS' (POS→servicio, lo graba TrafficLoggingFilter). PK id IDENTITY. Campos: fecha (@Temporal TIMESTAMP, nullable=false), origen ('POS'|'AFIP', length=10), tipo (CAE/CAEA/TOKEN/CONSULTA o SOAP/REST, length=30), mensaje (length=2000), referencia (URI POS o detalle AFIP, length=300).

Enums-tabla AFIP

No son enum de Java

Son entidades JPA (@Entity) que mapean tablas de catálogo AFIP. Funcionan como enums de dominio pero viven en la base. PK no autogenerada (la define AFIP), salvo donde se indique.

Entidad Tabla PK Campos
TipoComprobante TiposComprobante id (Integer) descripcion, letra, codigo, leyenda (String); discriminaIva, discriminaTributos, usaSubtotal (booleanbit). Constructor TipoComprobante(Integer id).
TipoDocumento TiposDocumento id (Integer) descripcion (unique).
TipoConcepto TiposConcepto id (Integer) descripcion (unique).
TipoIva TiposIva id (Integer) descripcion (unique), alicuota (double).
TipoMoneda TiposMonedas id (String) descripcion (unique).
TipoTributo TiposTributo id (Integer) descripcion (unique).

TipoComprobante, TipoDocumento, TipoConcepto y TipoMoneda llevan @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) (serialización JSON con proxies lazy de Hibernate).

Por dónde seguir