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 (boolean → bit) |
|
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 (boolean → bit). 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¶
- Persistencia — dialecto, flush MANUAL, naming, DDL.
- Ciclo de facturación — cómo se usan estas entidades.
- Invariantes — reglas que no se rompen.