*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
';print_r($object->thirdparty);exit;
// if (empty($object->thirdparty)) $objimp = FALSE;
// $data = [];
// for ($i = 0; $i < count($object->lines); $i++) {
// $descuento = 0;
// if (empty($object->lines[$i]->fk_product)) {
// if ($object->lines[$i]->remise_percent > 0) {
// $descuento = (100 - round($object->lines[$i]->remise_percent, 2)) / 100;
// if ($conf->multicurrency->enabled) {
// $descuento = (round($object->lines[$i]->multicurrency_subprice, 2) - (round($object->lines[$i]->multicurrency_subprice, 2) * $descuento));
// } else {
// $descuento = round($object->lines[$i]->subprice, 2) - (round($object->lines[$i]->subprice, 2) * $descuento);
// }
// $descuento = $descuento * $object->lines[$i]->qty;
// $data[$i] = ['Descuento' => number_format($descuento, 2, '.', '')]; //JGG Solo se incluye si existe descuento
// }
// $data[$i] = [
// 'Descripcion' => mb_convert_encoding(strip_tags($object->lines[$i]->desc), 'UTF-8'),
// 'Cantidad' => $object->lines[$i]->qty,
// 'ValorUnitario' => number_format(abs($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice), 2, '.', ''),
// //'Importe' => number_format(abs(($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht) - $descuento), 2, ".", ""),
// 'Importe' => number_format(abs(($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht) + $descuento), 2, ".", ""),
// 'ClaveUnidad' => $object->lines[$i]->array_options['options_cfdixml_umed'],
// //'NoIdentificacion' => , // Serial Number
// 'ClaveProdServ' => $object->lines[$i]->array_options['options_cfdixml_claveprodserv'],
// // 'CuentaPredial' => , //TODO
// 'ObjetoImp' => $objimp ? $object->lines[$i]->array_options['options_cfdixml_objetoimp'] : '01',
// ];
// } else {
// // include DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
// $product = new Product($db);
// $product->fetch($object->lines[$i]->fk_product);
// // echo $object->lines[$i]->product_label;
// if ($object->lines[$i]->remise_percent > 0) {
// $desctotal = (float)($object->lines[$i]->qty) * (float)($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice);
// $descuento = ($desctotal * (float)($object->lines[$i]->remise_percent)) / 100;
// }
// $data[$i] = [
// 'Descripcion' => mb_convert_encoding(strip_tags($product->label), 'UTF8'),
// 'Cantidad' => $object->lines[$i]->qty,
// 'ValorUnitario' => number_format(abs($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice), 2, '.', ''),
// //'Importe' => number_format(abs(($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht) - $descuento), 2,".",""),
// 'Importe' => number_format(abs(($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht) + $descuento), 2, ".", ""),
// 'ClaveUnidad' => $product->array_options['options_cfdixml_umed'],
// //'NoIdentificacion' => , // Serial Number
// 'ClaveProdServ' => $product->array_options['options_cfdixml_claveprodserv'],
// // 'CuentaPredial' => , //TODO
// 'ObjetoImp' => $objimp ? $product->array_options['options_cfdixml_objetoimp'] : '01',
// ];
// }
// $resico = checkReceptor($object);
// if ($resico) {
// $var_codes = '001';
// $descuento ? $data[$i]['Descuento'] = number_format($descuento, 2, ".", "") : null;
// $data[$i]['Impuestos']['Traslados'] = [
// 'Base' => number_format(abs($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht), 2, '.', ''),
// 'Impuesto' => $object->lines[$i]->vat_src_code,
// 'TipoFactor' => 'Tasa',
// 'TasaOCuota' => number_format($object->lines[$i]->tva_tx / 100, 6, ".", ""),
// 'Importe' => number_format(abs(($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_total_tva : $object->lines[$i]->total_tva)), 2, ".", ""),
// ];
// //Calc revenuestamp by line;
// $sql = "SELECT f.revenuestamp FROM " . MAIN_DB_PREFIX . "facture f where rowid = " . $object->id;
// $resql = $db->query($sql);
// if ($resql) {
// $obj = $db->fetch_object($resql);
// }
// $percent = (float)price2num(($conf->multicurrency->enabled) ? (abs($obj->revenuestamp) * 100) / $object->multicurrency_total_ht : (abs($obj->revenuestamp) * 100) / $object->total_ht, 'MT');
// //$percent = (abs($obj->revenuestamp) * 100) / $conf->multicurrency->enabled ? $object->multicurrency_total_ht : $object->total_ht;
// $total_ht_line = ($conf->multicurrency->enabled ? ($object->lines[$i]->multicurrency_total_ht * $percent) : ($object->lines[$i]->total_ht * $percent)) / 100;
// $data[$i]['Impuestos']['Retencion'] = [
// 'Base' => number_format(abs($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht), 2, ".", ""),
// 'Impuesto' => $var_codes,
// 'TipoFactor' => 'Tasa',
// 'TasaOCuota' => number_format($percent / 100, 6, ".", ""),
// 'Importe' => number_format(abs($total_ht_line), 2, ".", ""),
// ];
// return $data;
// }
// // echo $descuento;exit;
// $descuento ? $data[$i]['Descuento'] = number_format($descuento, 2, ".", "") : null;
// $descuento ? $data[$i]['Importe'] = number_format($data[$i]['Importe'], 2, ".", "") : $data[$i]['Importe']; //JGG
// if ($objimp) {
// // Calcular y formatear los valores antes de asignarlos al array
// $base = abs($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht);
// $importe = abs($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_total_tva : $object->lines[$i]->total_tva);
// $tasa = (float)$object->lines[$i]->tva_tx / 100;
// // Asignar los valores al array
// $data[$i]['Impuestos']['Traslados'] = [
// 'Base' => number_format($base, 2, ".", ""),
// 'Impuesto' => $object->lines[$i]->vat_src_code,
// 'TipoFactor' => 'Tasa',
// 'TasaOCuota' => number_format($tasa, 6, ".", ""),
// 'Importe' => number_format($importe, 2, ".", ""),
// ];
// if ($object->pos_source > 0 && $object->lines[$i]->tva_tx > 0) {
// $data[$i]['Impuestos']['Traslados']['Impuesto'] = '002';
// }
// }
// }
// return $data;
// }
function getConceptos(Facture $object)
{
global $conf, $db;
$objimp = TRUE;
$object->fetch_thirdparty();
if (empty($object->thirdparty)) $objimp = FALSE;
// Validar RESICO
$emisor = getEmisor();
$rfiscal = $emisor['RegimenFiscal'];
$rfc_emisor = $emisor['Rfc'];
$is_resico = ($rfiscal == '626' && strlen($rfc_emisor) == 14);
$rfc_receptor = '';
if (!empty($object->thirdparty)) {
$rfc_receptor = $object->thirdparty->idprof1;
}
$apply_retention = ($is_resico && strlen($rfc_receptor) == 13);
var_dump($apply_retention);
exit;
$data = [];
for ($i = 0; $i < count($object->lines); $i++) {
$descuento = 0;
if (empty($object->lines[$i]->fk_product)) {
if ($object->lines[$i]->remise_percent > 0) {
$descuento = (100 - round($object->lines[$i]->remise_percent, 2)) / 100;
if ($conf->multicurrency->enabled) {
$descuento = (round($object->lines[$i]->multicurrency_subprice, 2) - (round($object->lines[$i]->multicurrency_subprice, 2) * $descuento));
} else {
$descuento = round($object->lines[$i]->subprice, 2) - (round($object->lines[$i]->subprice, 2) * $descuento);
}
$descuento = $descuento * $object->lines[$i]->qty;
$data[$i] = ['Descuento' => number_format($descuento, 2, '.', '')];
}
$data[$i] = [
'Descripcion' => mb_convert_encoding(strip_tags($object->lines[$i]->desc), 'UTF-8'),
'Cantidad' => $object->lines[$i]->qty,
'ValorUnitario' => number_format(abs($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice), 2, '.', ''),
'Importe' => number_format(abs(($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht) + $descuento), 2, ".", ""),
'ClaveUnidad' => $object->lines[$i]->array_options['options_cfdixml_umed'],
'ClaveProdServ' => $object->lines[$i]->array_options['options_cfdixml_claveprodserv'],
'ObjetoImp' => $objimp ? $object->lines[$i]->array_options['options_cfdixml_objetoimp'] : '01',
];
} else {
$product = new Product($db);
$product->fetch($object->lines[$i]->fk_product);
if ($object->lines[$i]->remise_percent > 0) {
$desctotal = (float)($object->lines[$i]->qty) * (float)($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice);
$descuento = ($desctotal * (float)($object->lines[$i]->remise_percent)) / 100;
}
$data[$i] = [
'Descripcion' => mb_convert_encoding(strip_tags($product->label), 'UTF8'),
'Cantidad' => $object->lines[$i]->qty,
'ValorUnitario' => number_format(abs($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice), 2, '.', ''),
'Importe' => number_format(abs(($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht) + $descuento), 2, ".", ""),
'ClaveUnidad' => $product->array_options['options_cfdixml_umed'],
'ClaveProdServ' => $product->array_options['options_cfdixml_claveprodserv'],
'ObjetoImp' => $objimp ? $product->array_options['options_cfdixml_objetoimp'] : '01',
];
}
$descuento ? $data[$i]['Descuento'] = number_format($descuento, 2, ".", "") : null;
$descuento ? $data[$i]['Importe'] = number_format($data[$i]['Importe'], 2, ".", "") : $data[$i]['Importe'];
if ($objimp) {
$base = abs($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht);
$importe = abs($conf->multicurrency->enabled ? $object->lines[$i]->multicurrency_total_tva : $object->lines[$i]->total_tva);
$tasa = (float)$object->lines[$i]->tva_tx / 100;
$data[$i]['Impuestos']['Traslados'] = [
'Base' => number_format($base, 2, ".", ""),
'Impuesto' => $object->lines[$i]->vat_src_code,
'TipoFactor' => 'Tasa',
'TasaOCuota' => number_format($tasa, 6, ".", ""),
'Importe' => number_format($importe, 2, ".", ""),
];
if ($object->pos_source > 0 && $object->lines[$i]->tva_tx > 0) {
$data[$i]['Impuestos']['Traslados']['Impuesto'] = '002';
}
if ($apply_retention) {
$retencion_importe = $base * 0.0125;
$data[$i]['Impuestos']['Retenciones'] = [
'Base' => number_format($base, 2, ".", ""),
'Impuesto' => '001', // ISR
'TipoFactor' => 'Tasa',
'TasaOCuota' => number_format(0.0125, 6, ".", ""),
'Importe' => number_format($retencion_importe, 2, ".", ""),
];
}
}
}
return $data;
}
/**
* Optimización
*/
/*
function getPayments(Paiement $object)
{
global $db, $conf;
$data = [];
$invoice = new Facture($db);
$tipocambio = null;
$fecha_pago = dol_print_date($object->date, '%Y-%m-%d %H:%M:%S');
$fecha_pago = str_replace(" ", "T", $fecha_pago);
$moneda = ($object->amount == $object->multicurrency_amount) ? $conf->currency : '';
$data[0] = [
'pago' => [
'FechaPago' => $fecha_pago,
'FormaDePagoP' => $object->type_code,
'TipoCambioP' => $tipocambio ? $tipocambio : 1,
'Monto' => round($moneda ? $object->amount : $object->multicurrency_amount, 2),
'MonedaP' => $moneda ?: ''
]
];
$sql = 'SELECT f.rowid as facid
FROM ' . MAIN_DB_PREFIX . 'paiement_facture as pf, ' . MAIN_DB_PREFIX . 'facture as f, ' . MAIN_DB_PREFIX . 'societe as s
WHERE pf.fk_facture = f.rowid
AND f.fk_soc = s.rowid
AND f.entity IN (' . getEntity('invoice') . ')
AND pf.fk_paiement = ' . ((int) $object->id);
$resql = $db->query($sql);
if ($resql) {
$num = $db->num_rows($resql);
if ($num > 0) {
$i = 0;
while ($i < $num) {
$obj = $db->fetch_object($resql);
$invoice->fetch($obj->facid);
// Obtener la suma de todos los pagos anteriores para esta factura
$sql = "SELECT SUM(amount) as total_paid_prev
FROM " . MAIN_DB_PREFIX . "paiement_facture
WHERE fk_facture = " . $obj->facid . "
AND fk_paiement < " . $object->id;
$resqlprevpay = $db->query($sql);
$total_paid_prev = 0;
if ($resqlprevpay && ($row = $db->fetch_object($resqlprevpay))) {
$total_paid_prev = $row->total_paid_prev ?: 0;
}
// Obtener el monto del pago actual
$sql = "SELECT amount, multicurrency_amount
FROM " . MAIN_DB_PREFIX . "paiement_facture
WHERE fk_facture = " . $obj->facid . "
AND fk_paiement = " . $object->id;
$resqlcurrpay = $db->query($sql);
$current_payment = 0;
$current_payment_multi = 0;
if ($resqlcurrpay && ($row = $db->fetch_object($resqlcurrpay))) {
$current_payment = $row->amount;
$current_payment_multi = $row->multicurrency_amount;
}
// Cálculos
$total_ttc = $moneda ? $invoice->total_ttc : $invoice->multicurrency_total_ttc;
$saldo_anterior = $total_ttc - $total_paid_prev;
$total_paid = $total_paid_prev + ($moneda ? $current_payment : $current_payment_multi);
$saldo_insoluto = max($total_ttc - $total_paid, 0);
$numparcialidad = ceil($total_paid / $total_ttc);
$objetoimp = '02';
$impuesto = '002';
$c_tasaocuota = number_format($invoice->total_tva / $invoice->total_ht, 6, ".", "");
$data[0]['pago']['DoctoRelacionado'][$i] = [
'IdDocumento' => $invoice->array_options['options_cfdixml_UUID'],
'MonedaDR' => $invoice->multicurrency_code,
'NumParcialidad' => $numparcialidad,
'ImpSaldoAnt' => round($saldo_anterior, 2),
'ImpPagado' => round($moneda ? $current_payment : $current_payment_multi, 2),
'ImpSaldoInsoluto' => round($saldo_insoluto, 2),
'MetodoDePagoDR' => $invoice->array_options['options_cfdixml_metodopago'],
'ObjetoImpDR' => $objetoimp,
'EquivalenciaDR' => $tipocambio ? ($conf->global->CFDIXML_PAGO20_ACTIVE ? number_format($tipocambio, 10, ".", "") : $tipocambio) : 1
];
// Cálculo de impuestos
$base = $moneda ? $current_payment : $current_payment_multi;
$importe = $base - ($base / (1 + $c_tasaocuota));
$data[0]['pago']['DoctoRelacionado'][$i]['ImpuestosDR'][$i] = [
'BaseDR' => number_format($base - $importe, 6, ".", ""),
'ImporteDR' => number_format($importe, 6, ".", ""),
'ImpuestoDR' => $impuesto,
'TasaOCuotaDR' => $c_tasaocuota,
'TipoFactorDR' => 'Tasa',
];
$i++;
}
// Cálculo de totales
$total_base = 0;
$total_impuesto = 0;
foreach ($data[0]['pago']['DoctoRelacionado'] as $docto) {
$total_base += $docto['ImpuestosDR'][0]['BaseDR'];
$total_impuesto += $docto['ImpuestosDR'][0]['ImporteDR'];
}
$data[0]['pago']['Impuestosp']['Traslados'][0] = [
'BaseP' => number_format($total_base, 6, '.', ''),
'ImporteP' => number_format($total_impuesto, 6, '.', ''),
'ImpuestoP' => $impuesto,
'TasaOCuotaP' => $c_tasaocuota,
'TipoFactorP' => 'Tasa',
];
$total_pagos = $data[0]['pago']['Monto'];
$c_tasaocuota_rounded = number_format($c_tasaocuota, 2);
if ($c_tasaocuota_rounded == '0.16') {
$data[0]['totales'][0] = [
'MontoTotalPagos' => round($total_pagos, 2),
'TotalTrasladosBaseIVA16' => round($total_base, 2),
'TotalTrasladosImpuestoIVA16' => round($total_impuesto, 2)
];
} elseif ($c_tasaocuota_rounded == '0.08') {
$data[0]['totales'][0] = [
'MontoTotalPagos' => round($total_pagos, 2),
'TotalTrasladosBaseIVA8' => round($total_base, 2),
'TotalTrasladosImpuestoIVA8' => round($total_impuesto, 2)
];
} elseif ($c_tasaocuota_rounded == '0.00') {
$data[0]['totales'][0] = [
'MontoTotalPagos' => round($total_pagos, 2),
'TotalTrasladosBaseIVA0' => round($total_base, 2),
'TotalTrasladosImpuestoIVA0' => round($total_impuesto, 2)
];
}
}
}
echo '';print_r($data);die;
return $data;
}
*/
function getPayments(Paiement $object)
{
global $db, $conf;
$data = [];
$invoice = new Facture($db);
$tipocambio = null;
$fecha_pago = '';
$sql = "SELECT datec from " . MAIN_DB_PREFIX . "paiement WHERE rowid = ". $object->id;
$resql = $db->query($sql);
if($resql) {
$obj = $db->fetch_object($resql);
$fecha_pago =$obj->datec;
}
// Formato de fecha requerido por el SAT
// echo '';print_r($fecha_pago);die;
$fecha_pago = str_replace(" ", "T", $fecha_pago);
// Verificación de moneda
$moneda = ($object->amount == $object->multicurrency_amount) ? $conf->currency : '';
$data[0] = [
'pago' => [
'FechaPago' => $fecha_pago,
'FormaDePagoP' => getSatPaymentType($object->type_code),
'TipoCambioP' => $tipocambio ?: 1,
'Monto' => round($moneda ? $object->amount : $object->multicurrency_amount, 2),
'MonedaP' => $moneda ?: ''
]
];
// Buscar facturas pagadas
$sql = "SELECT f.rowid as facid
FROM " . MAIN_DB_PREFIX . "paiement_facture as pf
INNER JOIN " . MAIN_DB_PREFIX . "facture as f ON pf.fk_facture = f.rowid
WHERE pf.fk_paiement = " . ((int)$object->id);
$resql = $db->query($sql);
if ($resql) {
$i = 0;
while ($obj = $db->fetch_object($resql)) {
$invoice->fetch($obj->facid);
// Pagos anteriores
$sql = "SELECT SUM(amount) as total_paid_prev
FROM " . MAIN_DB_PREFIX . "paiement_facture
WHERE fk_facture = " . $obj->facid . " AND fk_paiement < " . $object->id;
$res = $db->query($sql);
$total_paid_prev = ($res && ($row = $db->fetch_object($res))) ? $row->total_paid_prev : 0;
// Pago actual
$sql = "SELECT amount, multicurrency_amount
FROM " . MAIN_DB_PREFIX . "paiement_facture
WHERE fk_facture = " . $obj->facid . " AND fk_paiement = " . $object->id;
$res = $db->query($sql);
$row = $db->fetch_object($res);
$amount = $row->amount ?? 0;
$multicurrency_amount = $row->multicurrency_amount ?? 0;
$total_ttc = $moneda ? $invoice->total_ttc : $invoice->multicurrency_total_ttc;
$pagado = $moneda ? $amount : $multicurrency_amount;
$saldo_anterior = $total_ttc - $total_paid_prev;
$saldo_insoluto = max($total_ttc - ($total_paid_prev + $pagado), 0);
$numparcialidad = ceil(($total_paid_prev + $pagado) / $total_ttc);
// Documento relacionado
$data[0]['pago']['DoctoRelacionado'][$i] = [
'IdDocumento' => $invoice->array_options['options_cfdixml_UUID'],
'MonedaDR' => $invoice->multicurrency_code,
'NumParcialidad' => $numparcialidad,
'ImpSaldoAnt' => round($saldo_anterior, 2),
'ImpPagado' => round($pagado, 2),
'ImpSaldoInsoluto' => round($saldo_insoluto, 2),
'MetodoDePagoDR' => $invoice->array_options['options_cfdixml_metodopago'],
'ObjetoImpDR' => '02',
'EquivalenciaDR' => $tipocambio ?: 1
];
// ImpuestosDR
foreach ($invoice->lines as $line) {
$base = $line->total_ht;
// IVA
if ((float)$line->tva_tx > 0) {
$data[0]['pago']['DoctoRelacionado'][$i]['ImpuestosDR']['TrasladosDR'][] = [
'BaseDR' => number_format($base, 6, '.', ''),
'ImporteDR' => number_format($line->total_tva, 6, '.', ''),
'ImpuestoDR' => '002',
'TasaOCuotaDR' => number_format($line->tva_tx / 100, 6, '.', ''),
'TipoFactorDR' => 'Tasa'
];
}
// IEPS
if ((float)$line->localtax1_tx == 8.0) {
$data[0]['pago']['DoctoRelacionado'][$i]['ImpuestosDR']['TrasladosDR'][] = [
'BaseDR' => number_format($base, 6, '.', ''),
'ImporteDR' => number_format($line->total_localtax1, 6, '.', ''),
'ImpuestoDR' => '003',
'TasaOCuotaDR' => number_format($line->localtax1_tx / 100, 6, '.', ''),
'TipoFactorDR' => 'Tasa'
];
}
// IVA 0%
if ((float)$line->tva_tx == 0) {
$data[0]['pago']['DoctoRelacionado'][$i]['ImpuestosDR']['TrasladosDR'][] = [
'BaseDR' => number_format($base, 6, '.', ''),
'ImporteDR' => '0.000000',
'ImpuestoDR' => '002',
'TasaOCuotaDR' => '0.000000',
'TipoFactorDR' => 'Tasa'
];
}
// Retenciones
if ((float)$line->localtax2_tx > 0) {
$data[0]['pago']['DoctoRelacionado'][$i]['ImpuestosDR']['RetencionesDR'][] = [
'BaseDR' => number_format($base, 6, '.', ''),
'ImporteDR' => number_format($line->total_localtax2, 6, '.', ''),
'ImpuestoDR' => '002',
'TasaOCuotaDR' => number_format($line->localtax2_tx / 100, 6, '.', ''),
'TipoFactorDR' => 'Tasa'
];
}
}
$i++;
}
// Agrupar totales
$totales = [
'MontoTotalPagos' => round($data[0]['pago']['Monto'], 2)
];
$traslados = [];
$retenciones = [];
foreach ($data[0]['pago']['DoctoRelacionado'] as $doc) {
// Traslados
foreach ($doc['ImpuestosDR']['TrasladosDR'] ?? [] as $traslado) {
$key = $traslado['ImpuestoDR'] . '-' . $traslado['TasaOCuotaDR'];
if (!isset($traslados[$key])) {
$traslados[$key] = ['BaseP' => 0, 'ImporteP' => 0, 'ImpuestoP' => $traslado['ImpuestoDR'], 'TasaOCuotaP' => $traslado['TasaOCuotaDR']];
}
$traslados[$key]['BaseP'] += (float)$traslado['BaseDR'];
$traslados[$key]['ImporteP'] += (float)$traslado['ImporteDR'];
}
// Retenciones
foreach ($doc['ImpuestosDR']['RetencionesDR'] ?? [] as $retencion) {
$imp = $retencion['ImpuestoDR'];
if (!isset($retenciones[$imp])) {
$retenciones[$imp] = 0;
}
$retenciones[$imp] += (float)$retencion['ImporteDR'];
}
}
// Insertar traslados
$j = 0;
foreach ($traslados as $t) {
$data[0]['pago']['Impuestosp']['Traslados'][$j] = array_merge($t, ['TipoFactorP' => 'Tasa']);
if ($t['ImpuestoP'] === '002') {
if ($t['TasaOCuotaP'] === '0.160000') {
$totales['TotalTrasladosBaseIVA16'] = round($t['BaseP'], 2);
$totales['TotalTrasladosImpuestoIVA16'] = round($t['ImporteP'], 2);
} elseif ($t['TasaOCuotaP'] === '0.080000') {
$totales['TotalTrasladosBaseIVA8'] = round($t['BaseP'], 2);
$totales['TotalTrasladosImpuestoIVA8'] = round($t['ImporteP'], 2);
} elseif ($t['TasaOCuotaP'] === '0.000000') {
$totales['TotalTrasladosBaseIVA0'] = round($t['BaseP'], 2);
$totales['TotalTrasladosImpuestoIVA0'] = round($t['ImporteP'], 2);
}
}
$j++;
}
// Insertar retenciones
$k = 0;
foreach ($retenciones as $imp => $importe) {
$data[0]['pago']['Impuestosp']['Retenciones'][$k++] = [
'ImpuestoP' => $imp,
'ImporteP' => number_format($importe, 2, '.', '')
];
if ($imp == '001') $totales['TotalRetencionesISR'] = round($importe, 2);
if ($imp == '002') $totales['TotalRetencionesIVA'] = round($importe, 2);
if ($imp == '003') $totales['TotalRetencionesIEPS'] = round($importe, 2);
}
$data[0]['totales'][0] = $totales;
}
// echo '';print_r($data);die;
return $data;
}
function createFromCurrent(User $user, Facture $object)
{
global $db, $conf;
// Source invoice load
$facture = new Facture($db);
// Retrieve all extrafield
// fetch optionals attributes and labels
$object->fetch_optionals();
if (!empty($object->array_options)) {
$extrafields['extrafields'] = $object->array_options;
foreach ($extrafields as $extrafield) {
if ($extrafield['options_cfdixml_usocfdi']) {
$facture->array_options['options_cfdixml_usocfdi'] = $extrafield['options_cfdixml_usocfdi'];
}
if ($extrafield['options_cfdixml_metodopago']) {
$facture->array_options['options_cfdixml_metodopago'] = $extrafield['options_cfdixml_metodopago'];
}
if ($extrafield['options_cfdixml_exportacion']) {
$facture->array_options['options_cfdixml_exportacion'] = $extrafield['options_cfdixml_exportacion'];
}
if ($extrafield['options_cfdixml_doctorel']) {
$facture->array_options['options_cfdixml_doctorel'] = $object->id;
}
// $facture->array_options
}
//Borrar datos relativos al timbrado
// $facture->array_options = $object->array_options;
}
foreach ($object->lines as &$line) {
$line->fetch_optionals(); //fetch extrafields
}
$facture->fk_facture_source = $object->id;
$facture->type = 1;
$facture->socid = $object->socid;
$facture->date = $object->date;
$facture->date_pointoftax = $object->date_pointoftax;
$facture->note_public = $object->note_public;
$facture->note_private = $object->note_private;
$facture->ref_client = $object->ref_client;
$facture->modelpdf = $object->model_pdf; // deprecated
$facture->model_pdf = $object->model_pdf;
$facture->fk_project = $object->fk_project;
$facture->cond_reglement_id = $object->cond_reglement_id;
$facture->mode_reglement_id = $object->mode_reglement_id;
$facture->remise_absolue = $object->remise_absolue;
$facture->remise_percent = $object->remise_percent;
$facture->origin = $object->origin;
$facture->origin_id = $object->origin_id;
$facture->lines = $object->lines; // Array of lines of invoice
$facture->situation_counter = $object->situation_counter;
$facture->situation_cycle_ref = $object->situation_cycle_ref;
$facture->situation_final = $object->situation_final;
$facture->retained_warranty = $object->retained_warranty;
$facture->retained_warranty_fk_cond_reglement = $object->retained_warranty_fk_cond_reglement;
$facture->retained_warranty_date_limit = $object->retained_warranty_date_limit;
$facture->fk_user_author = $user->id;
// Loop on each line of new invoice
// foreach ($facture->lines as $i => $tmpline) {
// $facture->lines[$i]->fk_prev_id = $this->lines[$i]->rowid;
// if ($invertdetail) {
// $facture->lines[$i]->subprice = -$facture->lines[$i]->subprice;
// $facture->lines[$i]->total_ht = -$facture->lines[$i]->total_ht;
// $facture->lines[$i]->total_tva = -$facture->lines[$i]->total_tva;
// $facture->lines[$i]->total_localtax1 = -$facture->lines[$i]->total_localtax1;
// $facture->lines[$i]->total_localtax2 = -$facture->lines[$i]->total_localtax2;
// $facture->lines[$i]->total_ttc = -$facture->lines[$i]->total_ttc;
// $facture->lines[$i]->ref_ext = '';
// }
// }
// dol_syslog(get_class($this)."::createFromCurrent invertdetail=".$invertdetail." socid=".$this->socid." nboflines=".count($facture->lines));
$facid = $facture->create($user);
if ($facid <= 0) {
$object->error = $facture->error;
$object->errors = $facture->errors;
} elseif ($object->type == Facture::TYPE_SITUATION && !empty($conf->global->INVOICE_USE_SITUATION)) {
$object->fetchObjectLinked('', '', $object->id, 'facture');
foreach ($object->linkedObjectsIds as $typeObject => $Tfk_object) {
foreach ($Tfk_object as $fk_object) {
$facture->add_object_linked($typeObject, $fk_object);
}
}
$facture->add_object_linked('facture', $object->fk_facture_source);
}
return $facid;
}
function num2letras($num, $fem = true, $dec = true)
{
$matuni[2] = "dos";
$matuni[3] = "tres";
$matuni[4] = "cuatro";
$matuni[5] = "cinco";
$matuni[6] = "seis";
$matuni[7] = "siete";
$matuni[8] = "ocho";
$matuni[9] = "nueve";
$matuni[10] = "diez";
$matuni[11] = "once";
$matuni[12] = "doce";
$matuni[13] = "trece";
$matuni[14] = "catorce";
$matuni[15] = "quince";
$matuni[16] = "dieciseis";
$matuni[17] = "diecisiete";
$matuni[18] = "dieciocho";
$matuni[19] = "diecinueve";
$matuni[20] = "veinte";
$matunisub[2] = "dos";
$matunisub[3] = "tres";
$matunisub[4] = "cuatro";
$matunisub[5] = "quin";
$matunisub[6] = "seis";
$matunisub[7] = "sete";
$matunisub[8] = "ocho";
$matunisub[9] = "nove";
$matdec[2] = "veint";
$matdec[3] = "treinta";
$matdec[4] = "cuarenta";
$matdec[5] = "cincuenta";
$matdec[6] = "sesenta";
$matdec[7] = "setenta";
$matdec[8] = "ochenta";
$matdec[9] = "noventa";
$matsub[3] = 'mill';
$matsub[5] = 'bill';
$matsub[7] = 'mill';
$matsub[9] = 'trill';
$matsub[11] = 'mill';
$matsub[13] = 'bill';
$matsub[15] = 'mill';
$matmil[4] = 'millones';
$matmil[6] = 'billones';
$matmil[7] = 'de billones';
$matmil[8] = 'millones de billones';
$matmil[10] = 'trillones';
$matmil[11] = 'de trillones';
$matmil[12] = 'millones de trillones';
$matmil[13] = 'de trillones';
$matmil[14] = 'billones de trillones';
$matmil[15] = 'de billones de trillones';
$matmil[16] = 'millones de billones de trillones';
$num = trim((string)@$num);
if ($num[0] == '-') {
$neg = 'menos ';
$num = substr($num, 1);
} else
$neg = '';
while ($num[0] == '0') $num = substr($num, 1);
if ($num[0] < '1' or $num[0] > 9) $num = '0' . $num;
$zeros = true;
$punt = false;
$ent = '';
$fra = '';
for ($c = 0; $c < strlen($num); $c++) {
$n = $num[$c];
if (!(strpos(".,'''", $n) === false)) {
if ($punt) break;
else {
$punt = true;
continue;
}
} elseif (!(strpos('0123456789', $n) === false)) {
if ($punt) {
if ($n != '0') $zeros = false;
$fra .= $n;
} else
$ent .= $n;
} else
break;
}
$ent = ' ' . $ent;
if ($dec and $fra and !$zeros) {
$fin = ' punto';
for ($n = 0; $n < strlen($fra); $n++) {
if (($s = $fra[$n]) == '0')
$fin .= ' cero';
elseif ($s == '1')
$fin .= $fem ? ' una' : ' un';
else
$fin .= ' ' . $matuni[$s];
}
} else
$fin = '';
if ((int)$ent === 0) return 'Cero ' . $fin;
$tex = '';
$sub = 0;
$mils = 0;
$neutro = false;
while (($num = substr($ent, -3)) != ' ') {
$ent = substr($ent, 0, -3);
if (++$sub < 3 and $fem) {
$matuni[1] = 'una';
$subcent = 'as';
} else {
$matuni[1] = $neutro ? 'un' : 'uno';
$subcent = 'os';
}
$t = '';
$n2 = substr($num, 1);
if ($n2 == '00') {
} elseif ($n2 < 21)
$t = ' ' . $matuni[(int)$n2];
elseif ($n2 < 30) {
$n3 = $num[2];
if ($n3 != 0) $t = 'i' . $matuni[$n3];
$n2 = $num[1];
$t = ' ' . $matdec[$n2] . $t;
} else {
$n3 = $num[2];
if ($n3 != 0) $t = ' y ' . $matuni[$n3];
$n2 = $num[1];
$t = ' ' . $matdec[$n2] . $t;
}
$n = $num[0];
if ($n == 1) {
$t = ' ciento' . $t;
} elseif ($n == 5) {
$t = ' ' . $matunisub[$n] . 'ient' . $subcent . $t;
} elseif ($n != 0) {
$t = ' ' . $matunisub[$n] . 'cient' . $subcent . $t;
}
if ($sub == 1) {
} elseif (!isset($matsub[$sub])) {
if ($num == 1) {
$t = ' mil';
} elseif ($num > 1) {
$t .= ' mil';
}
} elseif ($num == 1) {
$t .= ' ' . $matsub[$sub] . '�n';
} elseif ($num > 1) {
$t .= ' ' . $matsub[$sub] . 'ones';
}
if ($num == '000') $mils++;
elseif ($mils != 0) {
if (isset($matmil[$sub])) $t .= ' ' . $matmil[$sub];
$mils = 0;
}
$neutro = true;
$tex = $t . $tex;
}
$tex = $neg . substr($tex, 1) . $fin;
return ucfirst($tex);
}
function getPaymentNum(Facture $object, $xmlContents = null)
{
global $db;
if (empty($xml)) {
$sql = "SELECT count(*) as nb FROM " . MAIN_DB_PREFIX . "paiement_facture";
$sql .= " WHERE fk_facture = " . $object->id;
$resql = $db->query($sql);
if ($resql) {
$obj = $db->fetch_object($resql);
return $obj->nb;
}
}
$cfdi = \CfdiUtils\Cfdi::newFromString($xmlContents);
$cfdi->getVersion(); // (string) 3.3
$cfdi->getDocument(); // clon del objeto DOMDocument
$cfdi->getSource(); // (string) getNode();
$pagos = $comprobante->searchNodes('cfdi:Complemento', 'pago20:Pagos', 'pago20:Pago');
$pagoCounter = 0;
$pagoCount = $pagos->count();
foreach ($pagos as $pago) {
$pagoCounter = $pagoCounter + 1;
$doctoRelacionados = $pago->searchNodes('pago20:DoctoRelacionado');
foreach ($doctoRelacionados as $doctoRelacionado) {
if ($doctoRelacionado['IdDocumento'] == $object->array_options['options_cfdixml_UUID']) {
return $doctoRelacionado['NumParcialidad'];
}
}
}
// echo '';print_r($doctoRelacionado->DoctoRelacionado);
}
function typent_array($mode = 0, $filter = '')
{
// phpcs:enable
global $db, $langs, $mysoc;
$effs = array();
$sql = "SELECT id, code, libelle";
$sql .= " FROM " . $db->prefix() . "c_typent";
$sql .= " WHERE active = 1 AND (fk_country IS NULL OR fk_country = " . (empty($mysoc->country_id) ? '0' : $mysoc->country_id) . ")";
if ($filter) {
$sql .= " " . $filter;
}
$sql .= " ORDER by position, id";
$resql = $db->query($sql);
if ($resql) {
$num = $db->num_rows($resql);
$i = 0;
while ($i < $num) {
$objp = $db->fetch_object($resql);
if (!$mode) {
$key = $objp->id;
} else {
$key = $objp->code;
}
if ($langs->trans($objp->code) != $objp->code) {
$effs[$key] = $langs->trans($objp->code);
} else {
$effs[$key] = $objp->libelle;
}
if ($effs[$key] == '-') {
$effs[$key] = '';
}
$i++;
}
$db->free($resql);
}
return $effs;
}
function checkReceptor(Facture $object)
{
global $db, $conf;
$emisor = getEmisor();
$rfiscal = $emisor['RegimenFiscal'];
if ($rfiscal != 626) {
return false;
}
$sql = "SELECT c.code FROM " . MAIN_DB_PREFIX . "c_typent c ";
$sql .= "WHERE c.id = " . $conf->global->CFDIXML_RESICO;
$resql = $db->query($sql);
if (!$resql) {
return false;
}
$typentobj = $db->fetch_object($resql);
if ($typentobj->code == 'P_FISICA') {
$sql = "SELECT c.code FROM " . MAIN_DB_PREFIX . "c_typent c ";
$sql .= "LEFT JOIN " . MAIN_DB_PREFIX . "societe s on s.fk_typent = c.id ";
$sql .= "WHERE s.rowid = " . $object->socid;
$resql2 = $db->query($sql);
if ($resql2) {
$soctypent = $db->fetch_object($resql2);
if ($soctypent->code != 'P_MORAL') {
return false;
}
}
}
return true;
}
// Función auxiliar para calcular el número de pago
function getPaymentsNum($invoice, $total_paid_prev)
{
$payment_num = 1;
if ($total_paid_prev > 0) {
$payment_num = ceil($total_paid_prev / $invoice->total_ttc) + 1;
}
return $payment_num;
}
function getSatPaymentType($type_code)
{
global $db;
$code = '';
$idpayment = dol_getIdFromCode($db, $type_code, 'c_paiement', 'code');
$sql = "SELECT code FROM " . MAIN_DB_PREFIX . "cfdixml_forma_pago where fk_c_paiement = " . $idpayment;
$resql = $db->query($sql);
if ($resql) {
$obj = $db->fetch_object($resql);
$code = $obj->code;
return $code;
} else {
return -1;
}
}