josemmo / Facturae-PHP

📝 Genera, firma, envía y recibe facturas electrónicas sin necesidad de ninguna librería adicional
https://josemmo.github.io/Facturae-PHP/
MIT License
211 stars 96 forks source link

Cálculo incorrecto de base de impuestos al usar Facturae::PRECISION_LINE #133

Closed juanadamuzsimj closed 1 year ago

juanadamuzsimj commented 1 year ago

Buenas tardes!

Llevamos utilizando este paquete bastante tiempo sin problema pero hemos encontrado un error: Adjunto XSIG de los datos de factura en los que se nos calcula mal la base y el total.

image

Las cantidades sumadas que indica la cabecera "TaxesOutputs" no coincide con las de "InvoiceTotals" más la base.

La base real es 441.36 y la del paquete en "TaxesOutputs" es 441.34, por lo que fallo debe provenir de las operaciones en los decimales en las sumas de las bases supongo..

<?xml version="1.0" encoding="UTF-8"?>
<Facturae xmlns:fe="http://www.facturae.es/Facturae/2014/v3.2.1/Facturae">
    <FileHeader>
        <SchemaVersion>
            3.2.1
        </SchemaVersion>
        <Modality>
            I
        </Modality>
        <InvoiceIssuerType>
            EM
        </InvoiceIssuerType>
        <Batch>
            <BatchIdentifier>
                99999999R000061F
            </BatchIdentifier>
            <InvoicesCount>
                1
            </InvoicesCount>
            <TotalInvoicesAmount>
                <TotalAmount>
                    485.51
                </TotalAmount>
            </TotalInvoicesAmount>
            <TotalOutstandingAmount>
                <TotalAmount>
                    485.51
                </TotalAmount>
            </TotalOutstandingAmount>
            <TotalExecutableAmount>
                <TotalAmount>
                    485.51
                </TotalAmount>
            </TotalExecutableAmount>
            <InvoiceCurrencyCode>
                EUR
            </InvoiceCurrencyCode>
        </Batch>
    </FileHeader>
    <Parties>
        <SellerParty>
            <TaxIdentification>
                <PersonTypeCode>
                    J
                </PersonTypeCode>
                <ResidenceTypeCode>
                    R
                </ResidenceTypeCode>
                <TaxIdentificationNumber>
                    99999999R
                </TaxIdentificationNumber>
            </TaxIdentification>
            <LegalEntity>
                <CorporateName>
                    RAZON SOCIAL
                </CorporateName>
                <AddressInSpain>
                    <Address>
                        CALLE
                    </Address>
                    <PostCode>
                        00000
                    </PostCode>
                    <Town>
                        CIUDAD
                    </Town>
                    <Province>
                        CIUDAD
                    </Province>
                    <CountryCode>
                        ESP
                    </CountryCode>
                </AddressInSpain>
            </LegalEntity>
        </SellerParty>
        <BuyerParty>
            <TaxIdentification>
                <PersonTypeCode>
                    J
                </PersonTypeCode>
                <ResidenceTypeCode>
                    R
                </ResidenceTypeCode>
                <TaxIdentificationNumber>
                    99999999R
                </TaxIdentificationNumber>
            </TaxIdentification>
            <LegalEntity>
                <CorporateName>
                    CLIENTE CONTADO ,
                </CorporateName>
                <AddressInSpain>
                    <Address>
                        Domicilio de prueba
                    </Address>
                    <PostCode>
                        14005
                    </PostCode>
                    <Town>
                        CÓRDOBA
                    </Town>
                    <Province>
                        CÓRDOBA
                    </Province>
                    <CountryCode>
                        ESP
                    </CountryCode>
                </AddressInSpain>
            </LegalEntity>
        </BuyerParty>
    </Parties>
    <Invoices>
        <Invoice>
            <InvoiceHeader>
                <InvoiceNumber>
                    000061
                </InvoiceNumber>
                <InvoiceSeriesCode>
                    F
                </InvoiceSeriesCode>
                <InvoiceDocumentType>
                    FC
                </InvoiceDocumentType>
                <InvoiceClass>
                    OO
                </InvoiceClass>
            </InvoiceHeader>
            <InvoiceIssueData>
                <IssueDate>
                    2023-07-19
                </IssueDate>
                <InvoiceCurrencyCode>
                    EUR
                </InvoiceCurrencyCode>
                <TaxCurrencyCode>
                    EUR
                </TaxCurrencyCode>
                <LanguageName>
                    es
                </LanguageName>
            </InvoiceIssueData>
            <TaxesOutputs>
                <Tax>
                    <TaxTypeCode>
                        01
                    </TaxTypeCode>
                    <TaxRate>
                        10.00
                    </TaxRate>
                    <TaxableBase>
                        <TotalAmount>
                            441.34
                        </TotalAmount>
                    </TaxableBase>
                    <TaxAmount>
                        <TotalAmount>
                            44.13
                        </TotalAmount>
                    </TaxAmount>
                </Tax>
            </TaxesOutputs>
            <InvoiceTotals>
                <TotalGrossAmount>
                    441.36
                </TotalGrossAmount>
                <TotalGeneralDiscounts>
                    0.00
                </TotalGeneralDiscounts>
                <TotalGeneralSurcharges>
                    0.00
                </TotalGeneralSurcharges>
                <TotalGrossAmountBeforeTaxes>
                    441.36
                </TotalGrossAmountBeforeTaxes>
                <TotalTaxOutputs>
                    44.15
                </TotalTaxOutputs>
                <TotalTaxesWithheld>
                    0.00
                </TotalTaxesWithheld>
                <InvoiceTotal>
                    485.51
                </InvoiceTotal>
                <TotalOutstandingAmount>
                    485.51
                </TotalOutstandingAmount>
                <TotalExecutableAmount>
                    485.51
                </TotalExecutableAmount>
            </InvoiceTotals>
            <Items>
                <InvoiceLine>
                    <ItemDescription>
                        ARTICULO 1
                    </ItemDescription>
                    <Quantity>
                        3.4
                    </Quantity>
                    <UnitOfMeasure>
                        01
                    </UnitOfMeasure>
                    <UnitPriceWithoutTax>
                        16.90
                    </UnitPriceWithoutTax>
                    <TotalCost>
                        57.46
                    </TotalCost>
                    <GrossAmount>
                        57.46
                    </GrossAmount>
                    <TaxesOutputs>
                        <Tax>
                            <TaxTypeCode>
                                01
                            </TaxTypeCode>
                            <TaxRate>
                                10.00
                            </TaxRate>
                            <TaxableBase>
                                <TotalAmount>
                                    57.46
                                </TotalAmount>
                            </TaxableBase>
                            <TaxAmount>
                                <TotalAmount>
                                    5.75
                                </TotalAmount>
                            </TaxAmount>
                        </Tax>
                    </TaxesOutputs>
                </InvoiceLine>
                <InvoiceLine>
                    <ItemDescription>
                        ARTICULO 2
                    </ItemDescription>
                    <Quantity>
                        1.2
                    </Quantity>
                    <UnitOfMeasure>
                        01
                    </UnitOfMeasure>
                    <UnitPriceWithoutTax>
                        5.90
                    </UnitPriceWithoutTax>
                    <TotalCost>
                        7.08
                    </TotalCost>
                    <GrossAmount>
                        7.08
                    </GrossAmount>
                    <TaxesOutputs>
                        <Tax>
                            <TaxTypeCode>
                                01
                            </TaxTypeCode>
                            <TaxRate>
                                10.00
                            </TaxRate>
                            <TaxableBase>
                                <TotalAmount>
                                    7.08
                                </TotalAmount>
                            </TaxableBase>
                            <TaxAmount>
                                <TotalAmount>
                                    0.71
                                </TotalAmount>
                            </TaxAmount>
                        </Tax>
                    </TaxesOutputs>
                </InvoiceLine>
                <InvoiceLine>
                    <ItemDescription>
                        ARTICULO 3
                    </ItemDescription>
                    <Quantity>
                        1
                    </Quantity>
                    <UnitOfMeasure>
                        01
                    </UnitOfMeasure>
                    <UnitPriceWithoutTax>
                        8.90
                    </UnitPriceWithoutTax>
                    <TotalCost>
                        8.90
                    </TotalCost>
                    <GrossAmount>
                        8.90
                    </GrossAmount>
                    <TaxesOutputs>
                        <Tax>
                            <TaxTypeCode>
                                01
                            </TaxTypeCode>
                            <TaxRate>
                                10.00
                            </TaxRate>
                            <TaxableBase>
                                <TotalAmount>
                                    8.90
                                </TotalAmount>
                            </TaxableBase>
                            <TaxAmount>
                                <TotalAmount>
                                    0.89
                                </TotalAmount>
                            </TaxAmount>
                        </Tax>
                    </TaxesOutputs>
                </InvoiceLine>
                <InvoiceLine>
                    <ItemDescription>
                        ARTICULO 4
                    </ItemDescription>
                    <Quantity>
                        1.75
                    </Quantity>
                    <UnitOfMeasure>
                        01
                    </UnitOfMeasure>
                    <UnitPriceWithoutTax>
                        8.90
                    </UnitPriceWithoutTax>
                    <TotalCost>
                        15.58
                    </TotalCost>
                    <GrossAmount>
                        15.58
                    </GrossAmount>
                    <TaxesOutputs>
                        <Tax>
                            <TaxTypeCode>
                                01
                            </TaxTypeCode>
                            <TaxRate>
                                10.00
                            </TaxRate>
                            <TaxableBase>
                                <TotalAmount>
                                    15.58
                                </TotalAmount>
                            </TaxableBase>
                            <TaxAmount>
                                <TotalAmount>
                                    1.56
                                </TotalAmount>
                            </TaxAmount>
                        </Tax>
                    </TaxesOutputs>
                </InvoiceLine>
                <InvoiceLine>
                    <ItemDescription>
                        ARTICULO 5
                    </ItemDescription>
                    <Quantity>
                        2.65
                    </Quantity>
                    <UnitOfMeasure>
                        01
                    </UnitOfMeasure>
                    <UnitPriceWithoutTax>
                        6.90
                    </UnitPriceWithoutTax>
                    <TotalCost>
                        18.29
                    </TotalCost>
                    <GrossAmount>
                        18.29
                    </GrossAmount>
                    <TaxesOutputs>
                        <Tax>
                            <TaxTypeCode>
                                01
                            </TaxTypeCode>
                            <TaxRate>
                                10.00
                            </TaxRate>
                            <TaxableBase>
                                <TotalAmount>
                                    18.29
                                </TotalAmount>
                            </TaxableBase>
                            <TaxAmount>
                                <TotalAmount>
                                    1.83
                                </TotalAmount>
                            </TaxAmount>
                        </Tax>
                    </TaxesOutputs>
                </InvoiceLine>
                <InvoiceLine>
                    <ItemDescription>
                        ARTICULO 6
                    </ItemDescription>
                    <Quantity>
                        1.8
                    </Quantity>
                    <UnitOfMeasure>
                        01
                    </UnitOfMeasure>
                    <UnitPriceWithoutTax>
                        5.90
                    </UnitPriceWithoutTax>
                    <TotalCost>
                        10.62
                    </TotalCost>
                    <GrossAmount>
                        10.62
                    </GrossAmount>
                    <TaxesOutputs>
                        <Tax>
                            <TaxTypeCode>
                                01
                            </TaxTypeCode>
                            <TaxRate>
                                10.00
                            </TaxRate>
                            <TaxableBase>
                                <TotalAmount>
                                    10.62
                                </TotalAmount>
                            </TaxableBase>
                            <TaxAmount>
                                <TotalAmount>
                                    1.06
                                </TotalAmount>
                            </TaxAmount>
                        </Tax>
                    </TaxesOutputs>
                </InvoiceLine>
                <InvoiceLine>
                    <ItemDescription>
                        ARTICULO 7
                    </ItemDescription>
                    <Quantity>
                        1.95
                    </Quantity>
                    <UnitOfMeasure>
                        01
                    </UnitOfMeasure>
                    <UnitPriceWithoutTax>
                        8.90
                    </UnitPriceWithoutTax>
                    <TotalCost>
                        17.36
                    </TotalCost>
                    <GrossAmount>
                        17.36
                    </GrossAmount>
                    <TaxesOutputs>
                        <Tax>
                            <TaxTypeCode>
                                01
                            </TaxTypeCode>
                            <TaxRate>
                                10.00
                            </TaxRate>
                            <TaxableBase>
                                <TotalAmount>
                                    17.36
                                </TotalAmount>
                            </TaxableBase>
                            <TaxAmount>
                                <TotalAmount>
                                    1.74
                                </TotalAmount>
                            </TaxAmount>
                        </Tax>
                    </TaxesOutputs>
                </InvoiceLine>
                <InvoiceLine>
                    <ItemDescription>
                        ARTICULO 8
                    </ItemDescription>
                    <Quantity>
                        11.3
                    </Quantity>
                    <UnitOfMeasure>
                        01
                    </UnitOfMeasure>
                    <UnitPriceWithoutTax>
                        3.00
                    </UnitPriceWithoutTax>
                    <TotalCost>
                        33.90
                    </TotalCost>
                    <GrossAmount>
                        33.90
                    </GrossAmount>
                    <TaxesOutputs>
                        <Tax>
                            <TaxTypeCode>
                                01
                            </TaxTypeCode>
                            <TaxRate>
                                10.00
                            </TaxRate>
                            <TaxableBase>
                                <TotalAmount>
                                    33.90
                                </TotalAmount>
                            </TaxableBase>
                            <TaxAmount>
                                <TotalAmount>
                                    3.39
                                </TotalAmount>
                            </TaxAmount>
                        </Tax>
                    </TaxesOutputs>
                </InvoiceLine>
                <InvoiceLine>
                    <ItemDescription>
                        ARTICULO 9
                    </ItemDescription>
                    <Quantity>
                        46.13
                    </Quantity>
                    <UnitOfMeasure>
                        01
                    </UnitOfMeasure>
                    <UnitPriceWithoutTax>
                        5.90
                    </UnitPriceWithoutTax>
                    <TotalCost>
                        272.17
                    </TotalCost>
                    <GrossAmount>
                        272.17
                    </GrossAmount>
                    <TaxesOutputs>
                        <Tax>
                            <TaxTypeCode>
                                01
                            </TaxTypeCode>
                            <TaxRate>
                                10.00
                            </TaxRate>
                            <TaxableBase>
                                <TotalAmount>
                                    272.17
                                </TotalAmount>
                            </TaxableBase>
                            <TaxAmount>
                                <TotalAmount>
                                    27.22
                                </TotalAmount>
                            </TaxAmount>
                        </Tax>
                    </TaxesOutputs>
                </InvoiceLine>
            </Items>
            <PaymentDetails>
                <Installment>
                    <InstallmentDueDate>
                        2023-07-20
                    </InstallmentDueDate>
                    <InstallmentAmount>
                        485.51
                    </InstallmentAmount>
                    <PaymentMeans>
                        02
                    </PaymentMeans>
                    <AccountToBeDebited>
                        <IBAN>
                            0000000000000000000000000000
                        </IBAN>
                    </AccountToBeDebited>
                </Installment>
            </PaymentDetails>
        </Invoice>
    </Invoices>
</Facturae>

Gracias!

juanadamuzsimj commented 1 year ago

Hemos detectado el origen del error.

El paquete permite indicar si los redondeos se realizan por línea o por documento.

Esta configuración no se tiene en cuenta en el cálculo del array de los impuestos. (Nosotros usamos redondeo por línea)

public function getData(){} -> Línea 106

josemmo commented 1 year ago

Hola @juanadamuzsimj,

Si no recuerdo mal, el método FacturaeItem::getData() sí que tiene en cuenta el modo de redondeo de la factura. ¿Cuáles son los campos que faltan por redondear?

¿Podrías subir el desglose de importes de una factura de ejemplo indicando los campos que están bien redondeados y los que están mal?

juanadamuzsimj commented 1 year ago

Buenas tardes Josemmo, gracias por la rapidez en la respuesta lo primero.

Importante comentar que estamos usando la versión 1.7.7.

Lineas en software: image

Líneas despuesd e pasar por facturaE: image

En el ejemplo incial, si sumamos todas las bases de las líneas después de redondear nos da un total de 441,36. En el totalizado del paquete da correctamente lo mismo:

<TotalGrossAmount>
    441.36
</TotalGrossAmount>

Sin embargo, en el totalizado de los impuestos, en el iva 10% (que son todas las líneas) nos devuelve 441.34, que es la suma de todas las líneas sin redondear.

<TaxableBase>
  <TotalAmount>
      441.34
  </TotalAmount>
</TaxableBase>
josemmo commented 1 year ago

@juanadamuzsimj, no entiendo muy bien el problema.

En las capturas de pantalla que adjuntas, se ve que Facturae-PHP redondea a dos decimales los importes de cada línea y luego los suma para obtener el total de la factura. Ese es el comportamiento esperado para la precisión a nivel de línea como se detalla en la documentación.

¿Habéis probado a usar el otro modo de precisión (Facturae::PRECISION_INVOICE)?

josemmo commented 1 year ago

Hola de nuevo,

He probado la solución propuesta y no cambia ningún importe de la factura.

@juanadamuzsimj, como no entiendo el problema, ¿puedes subir el XML de una factura con los importes correctos y la explicación de cómo se debería calcular los importes que no coinciden?

Este es el script que estoy utilizando para generar la factura de prueba:

use josemmo\Facturae\Facturae;
use josemmo\Facturae\FacturaeParty;

$fac = new Facturae();
// $fac->setPrecision(Facturae::PRECISION_INVOICE); // Descomentar para redondear a nivel de factura
$fac->setNumber('TEST', '0001');
$fac->setIssueDate('2023-07-22');

$fac->setSeller(new FacturaeParty([
  'taxNumber' => 'A00000000',
  'name'      => 'Emisor S.A.',
  'address'   => 'C/ Emisor, 123',
  'postCode'  => '12345',
  'town'      => 'Madrid',
  'province'  => 'Madrid',
]));

$fac->setBuyer(new FacturaeParty([
  'taxNumber' => 'B00000000',
  'name'      => 'Receptor S.L.',
  'address'   => 'C/ Receptor, 123',
  'postCode'  => '54321',
  'town'      => 'Madrid',
  'province'  => 'Madrid',
]));

$fac->addItem('Línea #1', 16.9000,  3.40, Facturae::TAX_IVA, 10);
$fac->addItem('Línea #2',  5.9000,  1.20, Facturae::TAX_IVA, 10);
$fac->addItem('Línea #3',  8.9000,  1.00, Facturae::TAX_IVA, 10);
$fac->addItem('Línea #4',  8.9000,  1.75, Facturae::TAX_IVA, 10);
$fac->addItem('Línea #5',  6.9000,  2.65, Facturae::TAX_IVA, 10);
$fac->addItem('Línea #6',  5.9000,  1.80, Facturae::TAX_IVA, 10);
$fac->addItem('Línea #7',  8.9000,  1.95, Facturae::TAX_IVA, 10);
$fac->addItem('Línea #8',  3.0000, 11.30, Facturae::TAX_IVA, 10);
$fac->addItem('Línea #9',  5.9000, 46.13, Facturae::TAX_IVA, 10);

echo $fac->export();
juanadamuzsimj commented 1 year ago

Buenos días @josemmo, el error no se puede reproducir desde tu función con ->addItem() ya que esta función usa el precio con IVA al añadir a la factura la información.

Nosotros utilizamos "unitPriceWithoutTax" dentro de la línea.

Hemos hecho esta función para testear como nos indicas y nos sigue dando el mismo error:

public function addItemWithoutTax($desc, $unitPrice=null, $quantity=1, $taxType=null, $taxRate=null) {
        if ($desc instanceOf FacturaeItem) {
            $item = $desc;
        } else {
            $item = new FacturaeItem([
                "name" => is_array($desc) ? $desc[0] : $desc,
                "description" => is_array($desc) ? $desc[1] : null,
                "quantity" => $quantity,
                "unitPriceWithoutTax" => $unitPrice,
                "taxes" => array($taxType => $taxRate)
            ]);
        }
        $this->items[] = $item;
        return $this;
    }

Con tu función los totales serían:

array:14 [
  "taxesOutputs" => array:1 [▼
    "01" => array:1 [▼
      "10:0" => array:5 [▼
        "base" => 401.22
        "rate" => 10
        "surcharge" => 0
        "amount" => 40.122
        "surchargeAmount" => 0.0
      ]
    ]
  ]
  "taxesWithheld" => []
  "generalDiscounts" => []
  "generalCharges" => []
  "invoiceAmount" => 441.34
  "grossAmount" => "401.22"
  "totalGeneralDiscounts" => "0.00"
  "totalGeneralCharges" => "0.00"
  "totalTaxesOutputs" => "40.12"
  "totalTaxesWithheld" => "0.00"
  "totalReimbursableExpenses" => "0.00"
  "totalOutstandingAmount" => 441.34
  "totalExecutableAmount" => 441.34
  "grossAmountBeforeTaxes" => "401.22"
]

Con nuestra función:

array:14 [
  "taxesOutputs" => array:1 [▼
    "01" => array:1 [▼
      "10:0" => array:5 [▼
        "base" => 441.342
        "rate" => 10
        "surcharge" => 0
        "amount" => 44.1342
        "surchargeAmount" => 0.0
      ]
    ]
  ]
  "taxesWithheld" => []
  "generalDiscounts" => []
  "generalCharges" => []
  "invoiceAmount" => 485.51
  "grossAmount" => "441.36"
  "totalGeneralDiscounts" => "0.00"
  "totalGeneralCharges" => "0.00"
  "totalTaxesOutputs" => "44.15"
  "totalTaxesWithheld" => "0.00"
  "totalReimbursableExpenses" => "0.00"
  "totalOutstandingAmount" => 485.51
  "totalExecutableAmount" => 485.51
  "grossAmountBeforeTaxes" => "441.36"
]

Un Saludo!

josemmo commented 1 year ago

Hola @juanadamuzsimj,

Gracias por la respuesta, ya he entendido el problema. Lo marco como bug para arreglar.

josemmo commented 1 year ago

Hola @juanadamuzsimj,

He añadido unos cambios que deberían solucionar el fallo. Puedes descargar la última pre-release de la librería con Composer:

composer require josemmo/facturae-php:dev-develop

Por favor, pruébalo y confírmame si está arreglado.

juanadamuzsimj commented 1 year ago

Perfecto, te reporto mis pruebas en cuanto las haga!

Muchas gracias!

juanadamuzsimj commented 1 year ago

Buenos días! Las pruebas que hemos realizado son correctas por ahora, cerramos la incidencia.

Muchísimas gracias!