-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rediseño del redondeo de decimales #81
Comments
Acabo de hacer una prueba de implementación de esto y no pasa la validación del validador del Gobierno de España. Prácticamente casi ningún campo puede tener más de dos decimales por esta restricción: En el caso del schema v3.2 de FacturaE, que sí admite hasta 6 decimales (más bien obliga), tampoco serviría redondear solo al final ya que el resto de campos se tienen que redondear a dos decimales y las cuentas no salen: Teniendo en cuenta estas limitaciones no se me ocurre ninguna solución ya que, a mi parecer, estamos limitados por la especificación. @NeoRazorX, la rama feat/issue-81 tiene las modificaciones que he hecho para probar este cambio. Si se te ocurre alguna solución alternativa a #80, por favor, plantéala en esta conversación. |
@josemmo Me encuentro un caso que coincide totalmente con el descrito en la anterior issue. Los totales correctos de la factura son:
Mientras que Facturae-PHP cuando hace el cálculo de los impuestos, está dando valores por encima. Los datos esenciales a nivel de línea son:
El error para mi, sin mirarlo en el código, está en en que se calcula el importe de los impuestos para mostrarlo para cada línea, y se hace un sumatorio de este. Pero el valor que se está mostrando está ya redondeado a 2 dígitos, pero realmente dispone de más precisión, y sumar con o El error para mi, sin mirarlo en el código, está en en que se calcula el importe de los impuestos para mostrarlo para cada línea, y se hace un sumatorio de este. Pero el valor que se está mostrando está ya redondeado a 2 dígitos, pero realmente dispone de más precisión, y sumar con o sin precisión lo cambia todo. Este archivo creo que ejemplifica bastante bien el problema. La columnas con valores calculados son G, H, M y N; y son las que ponen en contraste el problema Si no recuerdo mal, fiscal y contablemente no hay nada al respecto que indique que debe hacerse de una u otra forma, lo que implica que ambas formas son correctas, pero todos los cálculos deben hacerse de la misma manera para evitar valores dispares. La única forma para simplificar este problema que se me ocurre, es que en lugar de realizar cálculos dentro de Facturae-PHP, hagas un traspaso de la información tal y como se te facilita, ya que entonces, si hay errores serán provocados por el origen y no por el intermediario. Y en este caso concreto, los correspondientes totales y subtotales no se solicitan, sino que son los que calculas y con los que aparecen las discrepancias. |
Hola @shawe,
Sí, eso es lo que hace la librería: calcula los impuestos para cada línea con dos decimales y los impuestos totales de la factura se obtienen sumando los de cada línea ya redondeados. Como ya he mencionado en anteriores ocasiones, esto de redondear con dos decimales no es porque a mí me apetezca sino porque lo pone en la especificación de FacturaE. Por ejemplo, en los totales de la factura, el campo "TotalTaxOutputs" se define como el "sumatorio de todas las Cuotas y Recargos de Equivalencia", y las cuotas de cada línea (campo "InvoiceLine/Tax/TotalAmount") deben ir con dos decimales si son euros. Esto no es ideal, pero hay que recordar que Facturae-PHP es una implementación de la especificación, y si la especificación está diseñada así poco se puede hacer. Igual que le dije a @NeoRazorX, por favor, si se te ocurre una solución compártela en este issue. |
El tema del redondeo es para enviárselo como piden, no porqué se ciñan a rajatabla con ello como estás entendiendo. Yo mismo he retocado un archivo que en el sumatorio de Facturae-PHP daba 0.01 de más y lo rechazaban, se lo puse tal y como lo tenía la factura de origen, y se volvió a mandar y se aceptó sin problemas. La definición que das, coincide con los valores que ya tenemos, otra cosa diferente, es que tu hagas el cálculo de la misma manera que nosotros, no arrastras todos los decimales hasta el final, y vas perdiendo precisión por el camino. Es importante tener en cuenta toda la precisión posible, pero en el momento de rellenar valores usar los redondeos tal y como solicita la especificación. En cuando obtienes "sumando los de cada línea ya redondeados", es cuando empiezas a provocar ese descuadre, nadie va a pagar línea a línea, sino que va a pagar el total del documento. Con lo que si, nosotros podemos mostrar que los "subtotales por línea" difieren de la realidad, pero lo hacen porqué no reflejan la precisión real que requiere la operación, pero eso no implica que el cálculo que hacemos por detrás esté mal, lo que está mal es verlo redondeado con una precisión menor cuando aún no estamos en lo que te implica el pago final. Si te estoy entiendo bien lo que justificaste, tu defiendes lo siguiente como correcto, si tienes 1000 líneas con total 123.123456789: Intenta procesar con su validador este último ejemplo del drive, a ver si te lo acepta de la forma que te expongo, y de la que tu lo haces, posiblemente acepte ambas y ya ves que cantidad de error de cálculo puede llegar a implicar hacerlo de una u otra forma. Pasé el archivo ods adjunto, para que vieras un caso concreto donde el fallo se produce, como está en el documento, que sucede con los sumatorios y redondeos, y los mismos resultados con lo que hace Facturae-PHP que es diferente y es el único que tiene esa discrepancia, y sinceramente, tampoco me cuadra el porqué de dicha diferencia. Entiendo que el ejemplo que te acabo de dar, también te serviría para provocar el problema con otros valores diferentes. Puedes intentar las pruebas con productos que cuesten menos de 0.01€ y que deban venderse a centenares o millares, y usando eso de ejemplo, creo que verás todavía más evidente que siempre necesitas arrastrar toda la precisión, hasta el momento de rellenar el documento final. Las soluciones que se me ocurren:
|
Hola @shawe, Vuelvo a incidir en esta frase que ya dije en el mensaje anterior:
Que sí, soy consciente de que al redondear línea a línea se pierde precisión. Pero no podemos cambiar lo que dice la especificación. Lo de redondear al final ya lo probé en la rama feat/issue-81 y el validador del Gobierno de España no da por válidas las facturas generadas porque no cumplen con la especificación (lo explico en detalle en este mensaje). La verdad que los documentos de Word/Excel que enlazas no me sirven de mucho para intentar dar con una posible solución a este problema. Si pudieras subir una factura XML que cumpla el schema FacturaE 3.2.2 según como lo hacéis en vuestra organización (es decir, sin perder precisión) me sería de gran ayuda. |
Te adjunto 1 zip con 2 XML generados por tu propio código, partiendo de los datos del ejemplo de mi anterior mensaje. Puedes comparar entre ambos ficheros, y verás que sólo he modificado el sumatorio de todas las líneas, su cálculo de impuestos y su correspondiente total, que es lo que adjunto en las capturas. Ambos pasan el validador cuando realmente no debería ser así en base a lo que explicas. Pero sucede lo que te comenté, ambas formas son legalmente correctas aunque una cause más error que la otra. Así están todas las líneas de esa factura en la base de datos: Y estos son los valores de la cabecera de la factura que tuve que corregir en el XML, porqué no reflejaba la realidad de dicho documento: |
Muchas gracias, @shawe. Este fin de semana intento sacar un rato para estudiarlo. |
- Redondeados valores totales en PropertiesTrait::getTotals() - Actualizado test unitario - Eliminadas líneas comentadas en src/Facturae.php > Relacionado con #81
Hola @shawe y @NeoRazorX, Creo que ya tengo una versión de la librería que implementa correctamente el nuevo redondeo de decimales.
|
- Añadidas constantes a clase Facturae - Actualizado FacturaeItem - Actualizados ExportableTrait, PropertiesTrait y UtilsTrait - Sustituido DecimalsTest por PrecisionTest - Actualizado InvoiceTest > Relacionado con #81
- Actualizado anexo de constantes - Añadido propiedades/precision.md > Relacionado con #81
He añadido una opción para poder cambiar entre el sistema de redondeo antiguo y el nuevo, por motivos de compatibilidad: $fac = new Facturae();
// [...]
$fac->setPrecision(Facturae::PRECISION_LINE); // Por defecto, redondeo antiguo
$fac->setPrecision(Facturae::PRECISION_INVOICE); // Nuevo sistema de redondeo |
Disculpa lo que me he demorado en darte respuesta. Basándome en el ejemplo de las 1000 líneas que provocaban el desajuste, ahora no lo veo y el importe me cuadra y además me pasan las 2 primeras validaciones sin problemas. En mi caso el único cambio ha sido el que has indicado como nuevo:
|
Gracias por la respuesta, @shawe. Voy a esperar unos días por si alguien más quiere dejar feedback y después sacaré la release. |
Ya está publicada la nueva versión (v1.7.0) que implementa los cambios de este issue. |
Hola, he probado la última versión en la que cambia el redondeo, para que me quede claro comop lo hace sería: 1.- Por línea, en cada linea a cada producto se le calcula su iva / re correspondiente y se redondea por ejemplo 2.- Por factura, se arrastran todos los decimales Es correcto?. o se calcula sumando todas las bases y de la base se le calcula el impuesto?. Muchas gracias. |
Hola @akitamostodos, Tienes varios ejemplos de cómo funcionan los dos modos de precisión en la documentación de la librería (https://josemmo.github.io/Facturae-PHP/propiedades/precision.html). |
Dado que este es un problema recurrente, voy a intentar rediseñar la forma en la que Facturae-PHP gestiona el redondeo de decimales dentro de una factura.
Ahora mismo se redondea un mismo valor varias veces con la pérdida de precisión que eso conlleva.
El objetivo es hacer el redondeo solo una vez (justo antes de generar el documento).
Este feat es un experimento y puede que no llegue a una versión estable si los validadores de FacturaE no admiten los cálculos de esta segunda forma.
The text was updated successfully, but these errors were encountered: