Cálculo de CFDI con complemento de pagos 2.0
Es frecuente tener conflictos para hacer los cálculos de los atributos que van en el
Complemento para recepción de Pagos versión 2.0, para ello se ha creado la utilería
CfdiUtils\SumasPagos20\Calculator
.
En resumen, los datos calculados son: Totales
, Pago\Impuestos
y Pago@MontoMínimo
.
También se provee de un escritor de los datos de los cálculos CfdiUtils\SumasPagos20\PagosWriter
para escribir en el nodo del complemento de pagos.
Importante: Para poder utilizar esta herramienta, es importante tener instalada la extensión
BCMath
.
Ejemplo de uso
<?php
use \CfdiUtils\SumasPagos20\Calculator;
use \CfdiUtils\SumasPagos20\Currencies;
use \CfdiUtils\SumasPagos20\PagosWriter;
/**
* La variable $pagos tiene el pago con los datos requeridos
* @var \CfdiUtils\Elements\Pagos20\Pagos $pagos
*/
// Se puede usar el método estático
PagosWriter::calculateAndPut($pagos);
// Se puede calcular y mandar a escribir
$pagosCalculator = new Calculator(
2, // Decimales a usar en los impuestos de los pagos
new Currencies(['MXN' => 2, 'USD' => '2', 'EUR' => 2]) // Monedas con decimales
);
$result = $pagosCalculator->calculate($pagos);
$pagosWriter = new PagosWriter($pagos);
$pagosWriter->writePago($result);
Origen de los datos
Para hacer los cálculos, se require de forma general un Pre-CFDI con algunos datos armados:
Pagos
: Nodo del complementoPago
: Nodo de un pago@Monto
: Atributo que establece el monto del pago (opcional para el cálculo).@MonedaP
: Moneda del pago (para saber los dígitos soportados).@TipoCambioP
: Factor de conversión de la moneda del pago a MXN.DocumentoRelacionado
: Nodo del documento relacionado.@ImpPagado
: Monto pagado.@EquivalenciaDR
: Factor de equivalencia de la moneda del documento a la moneda del pago.ImpuestosDR
: Nodo de impuestos del documento relacionado, con todos sus hijos y atributos.
Cálculo y resultado
La herramienta de cálculo obtiene los valores del Pre-CFDI y procesa cada elemento Pago
,
cada elemento hijo DocumentoRelacionado
y cada elemento hijo ImpuestosDR\RetencionesDR\RetencionDR
e ImpuestosDR\TrasladosDR\TrasladoDR
para calcular Totales e Información de pagos.
Los objetos devueltos son inmutables, en futuras versiones será reforzada esta característica. Adicionalmente, los objetos son exportables a formato JSON para proveer una mejor experiencia de desarrollo.
El resultado es un objeto CfdiUtils\SumasPagos20\Pagos
que contiene:
Pagos::getTotales(): Totales
: Información de totales.Pagos::getPagos(): Pago[]
: Arreglo de pagos.Pagos::getPago(int $index): Pago
: Obtiene un pago.
El objeto CfdiUtils\SumasPagos20\Totales
contiene:
Totales::getRetencionIva(): Decimal|null
.Totales::getRetencionIsr(): Decimal|null
.Totales::getRetencionIeps(): Decimal|null
.Totales::getTrasladoIva16Base(): Decimal|null
.Totales::getTrasladoIva16Importe(): Decimal|null
.Totales::getTrasladoIva08Base(): Decimal|null
.Totales::getTrasladoIva08Importe(): Decimal|null
.Totales::getTrasladoIva00Base(): Decimal|null
.Totales::getTrasladoIva00Importe(): Decimal|null
.Totales::getTrasladoIvaExento(): Decimal|null
.Totales::getTotal(): Decimal
.
En caso de devolver null
significa que no existe información para establecer en el total.
El objeto Pago
contiene:
Pago::getMonto(): Decimal
: Monto obtenido del nodo, o bien, el monto mínimo.Pago::getMontoMinimo(): Decimal
: Monto mínimo que debe existir en el atributoPago@Monto
.Pago::getTipoCambioP(): Decimal
: Tipo de cambio para MXN obtenido del atributoPago@Monto
.Pago::getImpuestos(): Impuestos
: Conjunto de impuestos que deben existir en el nodoPago\ImpuestosP
.
El objeto Impuestos
contiene:
Impuestos::getRetencion(string $impuesto): Impuesto
: Método para obtener una retención según su clave de impuesto.Impuestos::getTraslado(string $impuesto, string $tipoFactor, string $tasaCuota): Impuesto
: Método para obtener un traslado según su clave de impuesto, clave de tipo de factor y valor de tasa o cuota.
El objeto Impuesto
contiene:
Impuesto::getBase(): Decimal
: Valor del monto base.Impuesto::getImporte(): Decimal
: Valor del importe.
El objeto Decimal
:
Este es un objeto especial para realizar operaciones matemáticas con precisión.
Requiere de la librería BCMath
.
strval(Decimal)
:Decimal
es unStringable
, por lo que puede ser convertido a cadena de caracteres.Decimal::round(int $decimals): Decimal
: obtiene el valor redondeado a un número de decimales.
Nota de BCMath
Trabajar con números de punto flotante no es sencillo. Para el 99% de los casos con simplemente tener cuidado al leer, escribir, comparar, y redondear es suficiente. Sin embargo, este proceso resulta complicado para la función de truncado.
Por ello, es mejor usar la estrategia de trabajar con los números como cadenas de caracteres y delegar las operaciones
matemáticas a la extensión BCMath
Arbitrary Precision Mathematics.
Existen otras extensiones y otras formas de hacer esta tarea, sin embargo, esta estrategia es de las más aceptadas entre los desarrollos de PHP.