Skip to content

Retenciones. Múltiples pagos para una factura. #258

@jmaxb2691

Description

@jmaxb2691

Hoy me topé con un detalle para en las retenciones. Si una factura de proveedor se paga en cuotas, es decir, tiene más de un pago y se van a realizar la retención con más de uno de ellos. No se puede hacer un loop de los pagos a pesar que el template lo permita.

Fragmento:

    {% if det.pagos %}
    {% for pay in det.pagos %}
    <cac:Payment>
        <cbc:ID>{{ loop.index }}</cbc:ID>
        <cbc:PaidAmount currencyID="{{ pay.moneda }}">{{ pay.importe|n_format }}</cbc:PaidAmount>
        <cbc:PaidDate>{{ pay.fecha|date('Y-m-d') }}</cbc:PaidDate>
    </cac:Payment>
    {% endfor %}
    {% endif %}

Entonces, si se hace algo como esto:

sac:SUNATRetentionDocumentReference
<cbc:ID schemeID="01">FE01-2234</cbc:ID>
cbc:IssueDate2025-11-02</cbc:IssueDate>
<cbc:TotalInvoiceAmount currencyID="PEN">30.00</cbc:TotalInvoiceAmount>
cac:Payment
cbc:ID1</cbc:ID>
<cbc:PaidAmount currencyID="PEN">30.00</cbc:PaidAmount>
cbc:PaidDate2025-11-01</cbc:PaidDate>
</cac:Payment>
cac:Payment
cbc:ID2</cbc:ID>
<cbc:PaidAmount currencyID="PEN">36.00</cbc:PaidAmount>
cbc:PaidDate2025-11-01</cbc:PaidDate>
</cac:Payment>
sac:SUNATRetentionInformation
<sac:SUNATRetentionAmount currencyID="PEN">1.98</sac:SUNATRetentionAmount>
sac:SUNATRetentionDate2025-11-09</sac:SUNATRetentionDate>
<sac:SUNATNetTotalPaid currencyID="PEN">64.02</sac:SUNATNetTotalPaid>
</sac:SUNATRetentionInformation>
</sac:SUNATRetentionDocumentReference>

Nos genera el siguiente error:

Error al enviar a SUNAT: 0306 | {'message':'No se puede leer (parsear) el archivo XML - Detalle: http://xxx.xxx.xxx/ol-ti-itemision-otroscpe-gem/guia_remision_gem: cvc-complex-type 2.4: in element {urn:sunat:names:specification:ubl:peru:schema:xsd:SunatAggregateComponents-1}SUNATRetentionDocumentReference of type {urn:sunat:names:specification:ubl:peru:schema:xsd:SunatAggregateComponents-1}SUNATRetentionDocumentReferenceType, found (in namespace urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2), but next item should be end-element'}

Esto se debe a que dentro del XSD:

<!-- Retencion -->
<xsd:complexType name="SUNATRetentionDocumentReferenceType">
	<xsd:sequence>
		<xsd:element ref="cbc:ID" />
		<xsd:element ref="cbc:IssueDate" />
		<xsd:element ref="cbc:TotalInvoiceAmount" />
		<xsd:element ref="cac:Payment" minOccurs="0" maxOccurs="1" />
		<xsd:element ref="SUNATRetentionInformation" minOccurs="0"
			maxOccurs="1" />
	</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="SUNATRetentionInformationType">
	<xsd:sequence>
		<xsd:element ref="SUNATRetentionAmount" />
		<xsd:element ref="SUNATRetentionDate" />
		<xsd:element ref="SUNATNetTotalPaid" />
		<xsd:element ref="cac:ExchangeRate" minOccurs="0"
			maxOccurs="1" />
	</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="SUNATRetentionDateType">
	<xsd:simpleContent>
		<xsd:extension base="udt:DateType" />
	</xsd:simpleContent>
</xsd:complexType>
<!-- Fin Retencion -->

<xsd:element ref="cac:Payment" minOccurs="0" maxOccurs="1" />

Solo se puede hacer un pago por factura.

Por otro lado, para el número de pago se genera por un loop:
cbc:ID{{ loop.index }}</cbc:ID>

Entonces siempre será uno.

Entonces he agregado unos métodos para el número de pago:

/**
 * Número de pago.
 *
 * @var int
 */
private $numero;


/**
 * @return int
 */
public function getNumero(): ?int
{
    return $this->numero;
}

/**
 * @param float $numero
 *
 * @return Payment
 */
public function setNumero(?int $numero): Payment
{
    $this->numero = $numero;

    return $this;
}

y usarlo así:

$payment = (new Payment())
	->setMoneda($currency)
	->setFecha($date_payment)
	->setImporte($amount)
	->setNumero($r->payment_number);

De modo que se utilice el número de pago a la factura que se haya determinado en el sistema.

Con eso conseguí esto:

sac:SUNATRetentionDocumentReference
<cbc:ID schemeID="01">FE01-2234</cbc:ID>
cbc:IssueDate2025-11-02</cbc:IssueDate>
<cbc:TotalInvoiceAmount currencyID="PEN">66.00</cbc:TotalInvoiceAmount>
cac:Payment
cbc:ID1</cbc:ID>
<cbc:PaidAmount currencyID="PEN">30.00</cbc:PaidAmount>
cbc:PaidDate2025-11-01</cbc:PaidDate>
</cac:Payment>
cac:Payment
cbc:ID2</cbc:ID>
<cbc:PaidAmount currencyID="PEN">36.00</cbc:PaidAmount>
cbc:PaidDate2025-11-01</cbc:PaidDate>
</cac:Payment>
sac:SUNATRetentionInformation
<sac:SUNATRetentionAmount currencyID="PEN">1.98</sac:SUNATRetentionAmount>
sac:SUNATRetentionDate2025-11-09</sac:SUNATRetentionDate>
<sac:SUNATNetTotalPaid currencyID="PEN">64.02</sac:SUNATNetTotalPaid>
</sac:SUNATRetentionInformation>
</sac:SUNATRetentionDocumentReference>

y se aceptó el xml

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions