En de la recepción a la garantía: cómo cerrar una obra pública en ConstruWare explicamos que el sistema calcula la amortización del anticipo en cada estimación. Eso es cierto y sigue siéndolo. Lo que ese artículo no cubría —y que verificamos ahora directamente en el código— es un momento fiscal distinto: cuándo se causa el IVA del anticipo. La Ley del IVA lo causa cuando el dinero se cobra, no cuando se factura el trabajo ejecutado, y en ConstruWare (repo medware-construccion) no existe ningún punto del código que emita un comprobante en el momento en que el anticipo entra.
Lo que exige la ley: el IVA de un anticipo se causa al cobrarlo, no al facturar la obra
La Ley del Impuesto al Valor Agregado (LIVA, texto vigente publicado por la Cámara de Diputados del H. Congreso de la Unión, última reforma DOF 12-11-2021) fija el momento de causación en el artículo 17:
"Artículo 17.- En la prestación de servicios se tendrá obligación de pagar el impuesto en el momento en el que se cobren efectivamente las contraprestaciones y sobre el monto de cada una de ellas [...]"
Un anticipo de obra es, precisamente, el cobro de una parte de la contraprestación antes de que el trabajo esté ejecutado. La ley no espera a que se facture la estimación para causar el impuesto: lo causa en cuanto el contratista recibe el dinero. La guía de llenado de CFDI del SAT (Anexo 20, Apéndice 2, "Procedimiento para la emisión de los CFDI en el caso de anticipos recibidos") detalla el mecanismo con tres comprobantes: un CFDI de Ingreso por el valor del anticipo al recibirlo (clave de producto/servicio 84111506, "Servicios de facturación", con la descripción "Anticipo del bien o servicio"), un segundo CFDI de Ingreso por el valor total de la obra cuando se concreta, y un tercer comprobante —de Egreso o, según el caso, relacionado con tipo de relación 07 ("CFDI por aplicación de anticipo")— que aplica el anticipo ya cobrado contra ese total.
Lo que sí hace ConstruWare: amortizar el anticipo, estimación por estimación
El seguimiento del anticipo como saldo interno está bien resuelto. Cada obra guarda su advance_mxn (el monto entregado) y su advance_amortization_rate (el porcentaje que se descuenta en cada estimación), y esa tasa se hereda del contrato, no se vuelve a capturar estimación por estimación —evita justamente que el anticipo nunca se termine de amortizar (estimates.service.ts:166-169). El saldo pendiente se calcula como lo entregado menos lo ya amortizado en estimaciones aprobadas: las canceladas y los borradores no cuentan, así que una estimación que nunca se aprobó no le resta saldo al anticipo (advanceState(), estimates.service.ts:584-612). Y al aprobar una nueva estimación, el cálculo excluye su propia amortización del tope que se le aplica a ella misma, para no descontarse a sí misma del saldo que está a punto de reducir (estimates.service.ts:220-222).
Lo que no hace: emitir ningún CFDI cuando el anticipo se recibe
Revisamos el módulo de facturación completo (services/projects/src/invoices/invoices.service.ts) y el que crea y actualiza la obra (services/projects/src/projects/projects.service.ts). El único punto que emite un CFDI en todo el sistema es stampEstimate(), y factura exclusivamente lo ejecutado: sus renglones vienen de loadItems(), que trae las partidas de la estimación con su clave del SAT (invoices.service.ts:894-929) y nunca incluye el anticipo ni su amortización como concepto. Esto es intencional y está documentado en el propio código para el fondo de garantía —"la retención es un acuerdo de pago entre las partes, no un impuesto retenido" (invoices.service.ts:225-227)— pero la misma exclusión aplica al anticipo sin que exista un comprobante que lo compense en algún otro punto.
advance_mxn se escribe cuando se da de alta o se edita la obra (projects.service.ts:163, :278): son sentencias UPDATE/INSERT sobre una columna de la base de datos, nada que llame al proveedor de timbrado. Búsqueda exhaustiva en el proveedor de CFDI real (packages/nest-core/src/cfdi/facturama.provider.ts) de TipoRelacion, CfdiRelacionado o un tipo de comprobante distinto de Ingreso: el adaptador arma CfdiType: 'I' fijo (línea 149) para el único comprobante que existe, el de la estimación. El catálogo c_TipoRelacion —incluida la clave 07 que exige el SAT para ligar un CFDI de anticipo con la factura final— no aparece en ningún archivo del repositorio fuera del proveedor simulado de pruebas (packages/nest-core/src/cfdi/mock.provider.ts), que no se usa en producción.
En la práctica: un contratista que recibe $500,000 de anticipo en ConstruWare ve ese monto reflejado correctamente como saldo pendiente y lo ve descontarse, poco a poco, del efectivo a cobrar en cada estimación —pero el sistema nunca generó el comprobante fiscal que la ley exige emitir en el momento del cobro. El IVA de ese anticipo se causó cuando el dinero entró, no cuando se aprobó la primera estimación semanas o meses después.
| Elemento | Qué dice la norma / qué hace ConstruWare |
|---|---|
| Momento en que se causa el IVA de un anticipo | Art. 17, LIVA — al cobrarse, no al facturar el trabajo ejecutado |
| Comprobante que exige el SAT al recibir el anticipo | CFDI de Ingreso, clave 84111506, descripción "Anticipo del bien o servicio" (Anexo 20, Apéndice 2) |
| Comprobante que liga la factura final con el anticipo ya cobrado | CFDI relacionado tipo 07, "CFDI por aplicación de anticipo" |
| Seguimiento del saldo del anticipo en ConstruWare | Correcto: se amortiza por estimación aprobada, hereda la tasa del contrato, no se autodescuenta |
| CFDI emitido al recibir el anticipo en ConstruWare | Ninguno: advance_mxn es sólo una columna de la obra, sin llamada al proveedor de timbrado |
Qué sigue siendo tuyo mientras tanto
Mientras ConstruWare no emita el CFDI de anticipo, el contratista tiene que decidir y timbrar ese comprobante por su cuenta —fuera del sistema— en cuanto recibe el dinero, y luego relacionarlo manualmente contra la estimación cuando ConstruWare la facture. Saltarse ese primer comprobante no cambia cuándo se causó el impuesto: sólo retrasa cuándo se declaró.
Preguntas frecuentes
¿ConstruWare calcula mal el anticipo?
No. El saldo y su amortización por estimación están bien calculados: la tasa se hereda del contrato, las estimaciones canceladas o en borrador no descuentan saldo, y una estimación no se autodescuenta al aprobarse.
¿ConstruWare emite algún comprobante cuando se recibe el anticipo?
No. El monto se guarda como una columna de la obra (advance_mxn); ningún código llama al proveedor de timbrado en ese momento.
¿Y cuando se factura la estimación, ahí sí se refleja el anticipo?
El CFDI de la estimación factura el 100% de lo ejecutado; el anticipo sólo reduce cuánto efectivo hay que cobrar, fuera del comprobante fiscal, igual que el fondo de garantía.
¿Por qué importa la diferencia de momento?
Porque el art. 17 de la LIVA causa el impuesto cuando se cobra, no cuando se factura el trabajo. Sin el CFDI de anticipo al recibirlo, el IVA de ese dinero queda sin declararse en el periodo en que la ley lo exige.
Fuentes consultadas: Ley del Impuesto al Valor Agregado, texto vigente publicado por la Cámara de Diputados del H. Congreso de la Unión, última reforma DOF 12-11-2021, artículo 17. Anexo 20, Guía de llenado de los comprobantes fiscales digitales por Internet, Apéndice 2 ("Procedimiento para la emisión de los CFDI en el caso de anticipos recibidos"), Servicio de Administración Tributaria. Este artículo es orientativo y no sustituye una revisión de tu caso por tu contador o asesor fiscal.
Ve el flujo real del anticipo en tu propia demo
Te mostramos en vivo cómo ConstruWare amortiza el anticipo en cada estimación, y qué parte del timbrado sigue corriendo fuera del sistema.
Agenda una demo gratis