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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions