feat(core): total de descuentos globales en notas de crédito y débito - #277
gustavoam-asdf wants to merge 1 commit into
Conversation
5380a99 to
f6c9a9d
Compare
SUNAT's XML guide for the electronic credit note defines a total for global discounts, but there is no way to set it with Greenter today. Field 25 of the guide, "Total de Descuentos": > A traves de este elemento se debe indicar el valor total de los descuentos > realizados de ser el caso. Su proposito es permitir consignar en el > comprobante de pago la sumatoria de los descuentos de cada linea > (descuentos por item). > > Ubicacion: //CreditNote/cac:LegalMonetaryTotal/cbc:AllowanceTotalAmount The sibling field is already there: BaseSale has `sumOtrosCargos` and both note templates render `cbc:ChargeTotalAmount`. Only the discount twin was missing, so a note cannot report discounts at all. - `sumOtrosDescuentos` moves from Invoice to BaseSale, right next to `sumOtrosCargos`. Invoice keeps its public API by inheritance and drops the duplicated property; the setter now returns `self` with a `@return $this` docblock, exactly like `setSumOtrosCargos` already did. - `notacr2.1` and `notadb2.1` render `cbc:AllowanceTotalAmount` before `cbc:ChargeTotalAmount`, which is the order `MonetaryTotalType` requires. - Two tests, one per note type, asserting the node and validating the document against the UBL schema. Related to thegreenter#232: this covers the global discount half of that report. The debit note interest reason mentioned there is not addressed here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
f6c9a9d to
a5e540f
Compare
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #277 +/- ##
=========================================
Coverage 95.87% 95.87%
Complexity 1312 1312
=========================================
Files 173 173
Lines 5477 5477
=========================================
Hits 5251 5251
Misses 226 226
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Ya no se puede usar el manual en PDF (2017) como referencia, actualmente el excel de validaciones es la fuente para cualquier modificacion, la ultima actualización fue en agosto 2026. Alli no se incluye ese tag, eso inidica que aunque el UBL 2.1 lo soporte, SUNAT no lo validará.
|


Relacionado con #232, la mitad de los descuentos globales en notas.
El problema
Una nota de crédito o débito no puede declarar descuentos hoy. El campo existe en el estándar de SUNAT, pero no hay forma de rellenarlo desde Greenter.
La guía de elaboración de documentos XML de la nota de crédito UBL 2.1, campo 25 «Total de Descuentos»:
Por qué se nota que falta
El hermano ya está:
BaseSaletienesumOtrosCargosy las dos plantillas de nota ya emitencbc:ChargeTotalAmount. Solo faltaba el gemelo de descuentos.El cambio
sumOtrosDescuentosse mueve deInvoiceaBaseSale, justo al lado desumOtrosCargos.Invoiceconserva su API pública por herencia y pierde la propiedad duplicada; el setter pasa a devolverselfcon docblock@return $this, que es exactamente lo que ya hacíasetSumOtrosCargos.notacr2.1ynotadb2.1emitencbc:AllowanceTotalAmountantes decbc:ChargeTotalAmount, que es el orden que exigeMonetaryTotalType.Verificación
composer run-script lint(phpstan) →[OK] No errorsvendor/bin/phpunit packages/xml packages/core→ 50/50, incluidos los tests de factura, que son los que caerían si mover el campo hubiera roto algoassertSchema()No pude correr psalm en local: no está en
vendor/, lo instala la CI aparte.Sobre
cac:AllowanceChargeEste PR no añade nodos
cac:AllowanceChargea las notas, aunque el issue pueda sugerirlo. La guía de SUNAT no los contempla en la nota: en toda su tabla de estructura no aparece ese elemento, ni encac:CreditNoteLineni en la cabecera, y la línea esID → CreditedQuantity → LineExtensionAmount → PricingReference → TaxTotal → Item → Price.Lo comprobé además contra el ambiente de pruebas de SUNAT: un
cac:AllowanceChargedentro de unacac:CreditNoteLinese tolera —CDR 0— pero SUNAT lo ignora, y sigue exigiendoLineExtensionAmount = Price × CreditedQuantity. Rebajar la línea por el descuento, que es lo que sí acepta en una factura, se rechaza con el error 3271. Por eso el único camino que la guía define para esto es el total, y es lo que implementa este PR.Queda fuera lo otro que menciona #232, el motivo de interés por mora en la nota de débito.
Sobre el Quality Gate de SonarCloud
Marca «19.4% Duplication on New Code». Son las 3 líneas del bloque
AllowanceTotalAmount, idénticas en las dos plantillas de nota (6 de 31 líneas nuevas). Es la misma forma que ya tiene el bloqueChargeTotalAmountjusto al lado, y que el resto de nodos compartidos entreinvoice2.1,notacr2.1ynotadb2.1: son plantillas hermanas, no código factorizable. Extraer un partial de Twig para tres líneas de XML iría contra cómo está escrito todo lo demás, así que lo dejo como está — pero dímelo si prefieres otra cosa.🤖 Generated with Claude Code