NEW: PDF Invoice show vat analysis per rate (#31381)
* Show vat analysis * Show vat analysis * Show vat analysis * fix white space * Update main.lang * Show vat analysis * Show vat analysis * add copyright * fix pre-commit * fix pre-commit * fix pre-commit * fix php-stan (8.2) * fix php-stan (8.2) * fix php-stan (8.2) * fix pre-commit tab * Update pdf_other.php --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
This commit is contained in:
parent
2c4d1038d0
commit
1f2bb2969a
6 changed files with 377 additions and 123 deletions
|
|
@ -6,7 +6,7 @@
|
|||
* Copyright (C) 2019 Ferran Marcet <fmarcet@2byte.es>
|
||||
* Copyright (C) 2021-2024 Anthony Berton <anthony.berton@bb2a.fr>
|
||||
* Copyright (C) 2022 Alexandre Spangaro <aspangaro@open-dsi.fr>
|
||||
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2024 Nick Fragoulis
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -128,6 +128,20 @@ if ($action == 'update') {
|
|||
dolibarr_set_const($db, "INVOICE_SHOW_SHIPPING_ADDRESS", GETPOSTINT("INVOICE_SHOW_SHIPPING_ADDRESS"), 'chaine', 0, '', $conf->entity);
|
||||
dolibarr_del_const($db, "INVOICE_SHOW_SHIPPING_ADDRESS", $conf->entity);
|
||||
}
|
||||
if (GETPOSTISSET('PDF_INVOICE_SHOW_VAT_ANALYSIS')) {
|
||||
dolibarr_set_const($db, "PDF_INVOICE_SHOW_VAT_ANALYSIS", GETPOSTINT("PDF_INVOICE_SHOW_VAT_ANALYSIS"), 'chaine', 0, '', $conf->entity);
|
||||
dolibarr_del_const($db, "PDF_INVOICE_SHOW_VAT_ANALYSIS", $conf->entity);
|
||||
}
|
||||
if (GETPOSTISSET('BARCODE_ON_SHIPPING_PDF')) {
|
||||
dolibarr_set_const($db, "BARCODE_ON_SHIPPING_PDF", GETPOSTINT("BARCODE_ON_SHIPPING_PDF"), 'chaine', 0, '', $conf->entity);
|
||||
}
|
||||
if (GETPOSTISSET('BARCODE_ON_RECEPTION_PDF')) {
|
||||
dolibarr_set_const($db, "BARCODE_ON_RECEPTION_PDF", GETPOSTINT("BARCODE_ON_RECEPTION_PDF"), 'chaine', 0, '', $conf->entity);
|
||||
}
|
||||
if (GETPOSTISSET('BARCODE_ON_STOCKTRANSFER_PDF')) {
|
||||
dolibarr_set_const($db, "BARCODE_ON_STOCKTRANSFER_PDF", GETPOSTINT("BARCODE_ON_STOCKTRANSFER_PDF"), 'chaine', 0, '', $conf->entity);
|
||||
}
|
||||
|
||||
// Terms of sale
|
||||
if ($_FILES['termsofsale']["name"]) {
|
||||
if (!preg_match('/(\.pdf)$/i', $_FILES['termsofsale']["name"])) { // Document can be used on a lot of different places. Only pdf can be supported.
|
||||
|
|
@ -143,16 +157,6 @@ if ($action == 'update') {
|
|||
}
|
||||
}
|
||||
|
||||
if (GETPOSTISSET('BARCODE_ON_SHIPPING_PDF')) {
|
||||
dolibarr_set_const($db, "BARCODE_ON_SHIPPING_PDF", GETPOSTINT("BARCODE_ON_SHIPPING_PDF"), 'chaine', 0, '', $conf->entity);
|
||||
}
|
||||
if (GETPOSTISSET('BARCODE_ON_RECEPTION_PDF')) {
|
||||
dolibarr_set_const($db, "BARCODE_ON_RECEPTION_PDF", GETPOSTINT("BARCODE_ON_RECEPTION_PDF"), 'chaine', 0, '', $conf->entity);
|
||||
}
|
||||
if (GETPOSTISSET('BARCODE_ON_STOCKTRANSFER_PDF')) {
|
||||
dolibarr_set_const($db, "BARCODE_ON_STOCKTRANSFER_PDF", GETPOSTINT("BARCODE_ON_STOCKTRANSFER_PDF"), 'chaine', 0, '', $conf->entity);
|
||||
}
|
||||
|
||||
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
|
||||
|
||||
header("Location: ".$_SERVER["PHP_SELF"]."?mainmenu=home&leftmenu=setup");
|
||||
|
|
@ -437,6 +441,19 @@ if (isModEnabled('invoice')) {
|
|||
}
|
||||
print '</td></tr>';
|
||||
|
||||
/* too late to have it enabled by default in v21
|
||||
print '<tr class="oddeven"><td>';
|
||||
print $form->textwithpicto($langs->trans("PDF_INVOICE_SHOW_VAT_ANALYSIS"), '');
|
||||
print '</td><td>';
|
||||
if ($conf->use_javascript_ajax) {
|
||||
print ajax_constantonoff('PDF_INVOICE_SHOW_VAT_ANALYSIS');
|
||||
} else {
|
||||
$arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
|
||||
print $form->selectarray("PDF_INVOICE_SHOW_VAT_ANALYSIS", $arrval, $conf->global->PDF_INVOICE_SHOW_VAT_ANALYSIS);
|
||||
}
|
||||
print '</td></tr>';
|
||||
*/
|
||||
|
||||
/* Keep this option hidden for the moment to avoid options inflation. We'll see later if it is used enough...
|
||||
print '<tr class="oddeven"><td>';
|
||||
print $form->textwithpicto($langs->trans("SUPPLIER_PROPOSAL_ADD_BILLING_CONTACT"), $langs->trans("SUPPLIER_PROPOSAL_ADD_BILLING_CONTACTMore"));
|
||||
|
|
|
|||
|
|
@ -796,10 +796,17 @@ class pdf_crabe extends ModelePDFFactures
|
|||
}
|
||||
$this->tva[$vatrate] += $tvaligne; // ->tva is abandoned, we use now ->tva_array that is more complete
|
||||
$vatcode = $object->lines[$i]->vat_src_code;
|
||||
if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
|
||||
if (getDolGlobalInt('PDF_INVOICE_SHOW_VAT_ANALYSIS')) {
|
||||
if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['tot_ht'])) {
|
||||
$this->tva_array[$vatrate . ($vatcode ? ' (' . $vatcode . ')' : '')]['tot_ht'] = 0;
|
||||
}
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate'=>$vatrate, 'vatcode'=>$vatcode, 'amount'=> $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne, 'tot_ht'=> $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['tot_ht'] + $object->lines[$i]->total_ht);
|
||||
} else {
|
||||
if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
|
||||
}
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
|
||||
}
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
|
||||
|
||||
if ($posYAfterImage > $posYAfterDescription) {
|
||||
$nexY = $posYAfterImage;
|
||||
|
|
@ -1161,6 +1168,65 @@ class pdf_crabe extends ModelePDFFactures
|
|||
|
||||
$pdf->SetFont('', '', $default_font_size - 1);
|
||||
|
||||
krsort($this->tva_array);
|
||||
|
||||
// Show VAT details
|
||||
if ($object->total_tva != 0 && getDolGlobalInt('PDF_INVOICE_SHOW_VAT_ANALYSIS')) {
|
||||
$pdf->SetFillColor(224, 224, 224);
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche, $posy);
|
||||
$titre = $outputlangs->transnoentities("VAT");
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L', true);
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 25, $posy);
|
||||
$titre = $outputlangs->transnoentities("NetTotal");
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L', true);
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 50, $posy);
|
||||
$titre = $outputlangs->transnoentities("VATAmount");
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L', true);
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 75, $posy);
|
||||
$titre = $outputlangs->transnoentities("AmountTotal");
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L', true);
|
||||
|
||||
$posy = $pdf->GetY();
|
||||
$tot_ht = 0;
|
||||
$tot_tva = 0;
|
||||
$tot_ttc = 0;
|
||||
|
||||
foreach ($this->tva_array as $tvakey => $tvaval) {
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche, $posy);
|
||||
$titre = round((float) $tvakey, 2) . "%";
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L');
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 25, $posy);
|
||||
$titre = price($tvaval['tot_ht']);
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L');
|
||||
$tot_ht += $tvaval['tot_ht'];
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 50, $posy);
|
||||
$titre = price($tvaval['amount']);
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L');
|
||||
$tot_tva += $tvaval['amount'];
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 75, $posy);
|
||||
$titre = price($tvaval['tot_ht'] + $tvaval['amount']);
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L');
|
||||
$tot_ttc += ($tvaval['tot_ht'] + $tvaval['amount']);
|
||||
|
||||
$posy = $pdf->GetY();
|
||||
}
|
||||
}
|
||||
|
||||
// If France, show VAT mention if not applicable
|
||||
if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
|
||||
$pdf->SetFont('', 'B', $default_font_size - 2);
|
||||
|
|
@ -1456,6 +1522,16 @@ class pdf_crabe extends ModelePDFFactures
|
|||
$pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($largcol2, $tab2_hl, price($sign * ($total_ht + (!empty($object->remise) ? $object->remise : 0)), 0, $outputlangs), 0, 'R', 1);
|
||||
|
||||
if (getDolGlobalInt('PDF_INVOICE_SHOW_VAT_ANALYSIS')) {
|
||||
$index++;
|
||||
$pdf->SetFillColor(255, 255, 255);
|
||||
$pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalVAT"), 0, 'L', 1);
|
||||
|
||||
$pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($largcol2, $tab2_hl, price($sign * $object->total_tva), 0, 'R', 1);
|
||||
}
|
||||
|
||||
// Show VAT by rates and total
|
||||
$pdf->SetFillColor(248, 248, 248);
|
||||
|
||||
|
|
@ -1542,34 +1618,35 @@ class pdf_crabe extends ModelePDFFactures
|
|||
}
|
||||
}
|
||||
|
||||
// VAT
|
||||
foreach ($this->tva_array as $tvakey => $tvaval) {
|
||||
if ($tvakey != 0) { // On affiche pas taux 0
|
||||
$this->atleastoneratenotnull++;
|
||||
if (!getDolGlobalInt('PDF_INVOICE_SHOW_VAT_ANALYSIS')) {
|
||||
// VAT
|
||||
foreach ($this->tva_array as $tvakey => $tvaval) {
|
||||
if ($tvakey != 0) { // On affiche pas taux 0
|
||||
$this->atleastoneratenotnull++;
|
||||
|
||||
$index++;
|
||||
$pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
|
||||
$index++;
|
||||
$pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
|
||||
|
||||
$tvacompl = '';
|
||||
if (preg_match('/\*/', $tvakey)) {
|
||||
$tvakey = str_replace('*', '', $tvakey);
|
||||
$tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
|
||||
$tvacompl = '';
|
||||
if (preg_match('/\*/', $tvakey)) {
|
||||
$tvakey = str_replace('*', '', $tvakey);
|
||||
$tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
|
||||
}
|
||||
$totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
|
||||
$totalvat .= ' ';
|
||||
if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') {
|
||||
$totalvat .= vatrate($tvaval['vatrate'], true).$tvacompl;
|
||||
} elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') {
|
||||
$totalvat .= $tvaval['vatcode'].$tvacompl;
|
||||
} elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
|
||||
$totalvat .= $tvacompl;
|
||||
} else {
|
||||
$totalvat .= vatrate($tvaval['vatrate'], true).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl;
|
||||
}
|
||||
$pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
|
||||
$pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($largcol2, $tab2_hl, price(price2num($tvaval['amount'], 'MT'), 0, $outputlangs), 0, 'R', 1);
|
||||
}
|
||||
$totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
|
||||
$totalvat .= ' ';
|
||||
if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') {
|
||||
$totalvat .= vatrate($tvaval['vatrate'], true).$tvacompl;
|
||||
} elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') {
|
||||
$totalvat .= $tvaval['vatcode'].$tvacompl;
|
||||
} elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
|
||||
$totalvat .= $tvacompl;
|
||||
} else {
|
||||
$totalvat .= vatrate($tvaval['vatrate'], true).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl;
|
||||
}
|
||||
$pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
|
||||
|
||||
$pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($largcol2, $tab2_hl, price(price2num($tvaval['amount'], 'MT'), 0, $outputlangs), 0, 'R', 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1042,10 +1042,17 @@ class pdf_octopus extends ModelePDFFactures
|
|||
}
|
||||
$this->tva[$vatrate] += $tvaligne; // ->tva is abandoned, we use now ->tva_array that is more complete
|
||||
$vatcode = $object->lines[$i]->vat_src_code;
|
||||
if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
|
||||
if (getDolGlobalInt('PDF_INVOICE_SHOW_VAT_ANALYSIS')) {
|
||||
if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['tot_ht'])) {
|
||||
$this->tva_array[$vatrate . ($vatcode ? ' (' . $vatcode . ')' : '')]['tot_ht'] = 0;
|
||||
}
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate'=>$vatrate, 'vatcode'=>$vatcode, 'amount'=> $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne, 'tot_ht'=> $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['tot_ht'] + $object->lines[$i]->total_ht);
|
||||
} else {
|
||||
if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
|
||||
}
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
|
||||
}
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
|
||||
|
||||
$nexY = max($nexY, $posYAfterImage);
|
||||
|
||||
|
|
@ -1328,6 +1335,65 @@ class pdf_octopus extends ModelePDFFactures
|
|||
|
||||
$pdf->SetFont('', '', $default_font_size - 1);
|
||||
|
||||
krsort($this->tva_array);
|
||||
|
||||
// Show VAT details
|
||||
if ($object->total_tva != 0 && getDolGlobalInt('PDF_INVOICE_SHOW_VAT_ANALYSIS')) {
|
||||
$pdf->SetFillColor(224, 224, 224);
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche, $posy);
|
||||
$titre = $outputlangs->transnoentities("VAT");
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L', true);
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 25, $posy);
|
||||
$titre = $outputlangs->transnoentities("NetTotal");
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L', true);
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 50, $posy);
|
||||
$titre = $outputlangs->transnoentities("VATAmount");
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L', true);
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 75, $posy);
|
||||
$titre = $outputlangs->transnoentities("AmountTotal");
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L', true);
|
||||
|
||||
$posy = $pdf->GetY();
|
||||
$tot_ht = 0;
|
||||
$tot_tva = 0;
|
||||
$tot_ttc = 0;
|
||||
|
||||
foreach ($this->tva_array as $tvakey => $tvaval) {
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche, $posy);
|
||||
$titre = round((float) $tvakey, 2) . "%";
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L');
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 25, $posy);
|
||||
$titre = price($tvaval['tot_ht']);
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L');
|
||||
$tot_ht += $tvaval['tot_ht'];
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 50, $posy);
|
||||
$titre = price($tvaval['amount']);
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L');
|
||||
$tot_tva += $tvaval['amount'];
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 75, $posy);
|
||||
$titre = price($tvaval['tot_ht'] + $tvaval['amount']);
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L');
|
||||
$tot_ttc += ($tvaval['tot_ht'] + $tvaval['amount']);
|
||||
|
||||
$posy = $pdf->GetY();
|
||||
}
|
||||
}
|
||||
|
||||
// If France, show VAT mention if not applicable
|
||||
if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
|
||||
$pdf->SetFont('', 'B', $default_font_size - 2);
|
||||
|
|
@ -1617,6 +1683,16 @@ class pdf_octopus extends ModelePDFFactures
|
|||
$pdf->MultiCell($largcol2, $tab2_hl, price($total_ht - $remise, 0, $outputlangs), 0, 'R', 1);
|
||||
}
|
||||
|
||||
if (getDolGlobalInt('PDF_INVOICE_SHOW_VAT_ANALYSIS')) {
|
||||
$index++;
|
||||
$pdf->SetFillColor(255, 255, 255);
|
||||
$pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalVAT"), 0, 'L', 1);
|
||||
|
||||
$pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($largcol2, $tab2_hl, price($sign * $object->total_tva), 0, 'R', 1);
|
||||
}
|
||||
|
||||
// Show VAT by rates and total
|
||||
$pdf->SetFillColor(248, 248, 248);
|
||||
|
||||
|
|
@ -1704,49 +1780,51 @@ class pdf_octopus extends ModelePDFFactures
|
|||
}
|
||||
//}
|
||||
|
||||
// VAT
|
||||
$tvas = array();
|
||||
$nblines = count($object->lines);
|
||||
for ($i = 0; $i < $nblines; $i++) {
|
||||
$tvaligne = $object->lines[$i]->total_tva;
|
||||
$vatrate = (string) $object->lines[$i]->tva_tx;
|
||||
if (!getDolGlobalInt('PDF_INVOICE_SHOW_VAT_ANALYSIS')) {
|
||||
// VAT
|
||||
$tvas = array();
|
||||
$nblines = count($object->lines);
|
||||
for ($i = 0; $i < $nblines; $i++) {
|
||||
$tvaligne = $object->lines[$i]->total_tva;
|
||||
$vatrate = (string) $object->lines[$i]->tva_tx;
|
||||
|
||||
if (($object->lines[$i]->info_bits & 0x01) == 0x01) {
|
||||
$vatrate .= '*';
|
||||
}
|
||||
if (! isset($tvas[$vatrate])) {
|
||||
$tvas[$vatrate] = 0;
|
||||
}
|
||||
$tvas[$vatrate] += $tvaligne;
|
||||
}
|
||||
|
||||
foreach ($tvas as $tvakey => $tvaval) {
|
||||
if ($tvakey != 0) { // On affiche pas taux 0
|
||||
$this->atleastoneratenotnull++;
|
||||
|
||||
$index++;
|
||||
$pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
|
||||
|
||||
$tvacompl = '';
|
||||
if (preg_match('/\*/', $tvakey)) {
|
||||
$tvakey = str_replace('*', '', $tvakey);
|
||||
$tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
|
||||
if (($object->lines[$i]->info_bits & 0x01) == 0x01) {
|
||||
$vatrate .= '*';
|
||||
}
|
||||
$totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
|
||||
$totalvat .= ' ';
|
||||
if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') {
|
||||
$totalvat .= vatrate($tvaval['vatrate'], 1).$tvacompl;
|
||||
} elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') {
|
||||
$totalvat .= $tvaval['vatcode'].$tvacompl;
|
||||
} elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
|
||||
$totalvat .= $tvacompl;
|
||||
} else {
|
||||
$totalvat .= vatrate($tvaval['vatrate'], 1).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl;
|
||||
if (! isset($tvas[$vatrate])) {
|
||||
$tvas[$vatrate] = 0;
|
||||
}
|
||||
$pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
|
||||
$tvas[$vatrate] += $tvaligne;
|
||||
}
|
||||
|
||||
$pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($largcol2, $tab2_hl, price(price2num($tvaval['amount'], 'MT'), 0, $outputlangs), 0, 'R', 1);
|
||||
foreach ($tvas as $tvakey => $tvaval) {
|
||||
if ($tvakey != 0) { // On affiche pas taux 0
|
||||
$this->atleastoneratenotnull++;
|
||||
|
||||
$index++;
|
||||
$pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
|
||||
|
||||
$tvacompl = '';
|
||||
if (preg_match('/\*/', $tvakey)) {
|
||||
$tvakey = str_replace('*', '', $tvakey);
|
||||
$tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
|
||||
}
|
||||
$totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
|
||||
$totalvat .= ' ';
|
||||
if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') {
|
||||
$totalvat .= vatrate($tvaval['vatrate'], 1).$tvacompl;
|
||||
} elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') {
|
||||
$totalvat .= $tvaval['vatcode'].$tvacompl;
|
||||
} elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
|
||||
$totalvat .= $tvacompl;
|
||||
} else {
|
||||
$totalvat .= vatrate($tvaval['vatrate'], 1).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl;
|
||||
}
|
||||
$pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
|
||||
|
||||
$pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($largcol2, $tab2_hl, price(price2num($tvaval['amount'], 'MT'), 0, $outputlangs), 0, 'R', 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
<?php
|
||||
/* Copyright (C) 2004-2014 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2008 Raphael Bertrand <raphael.bertrand@resultic.fr>
|
||||
* Copyright (C) 2010-2014 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
|
||||
* Copyright (C) 2012 Cédric Salvador <csalvador@gpcsolutions.fr>
|
||||
* Copyright (C) 2012-2014 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
|
||||
* Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
|
||||
* Copyright (C) 2017 Ferran Marcet <fmarcet@2byte.es>
|
||||
* Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2021-2024 Anthony Berton <anthony.berton@bb2a.fr>
|
||||
* Copyright (C) 2022-2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
|
||||
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024 Nick Fragoulis
|
||||
/* Copyright (C) 2004-2024 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2008 Raphael Bertrand <raphael.bertrand@resultic.fr>
|
||||
* Copyright (C) 2010-2014 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
|
||||
* Copyright (C) 2012 Cédric Salvador <csalvador@gpcsolutions.fr>
|
||||
* Copyright (C) 2012-2014 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
|
||||
* Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
|
||||
* Copyright (C) 2017 Ferran Marcet <fmarcet@2byte.es>
|
||||
* Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2018-2024 Anthony Berton <anthony.berton@bb2a.fr>
|
||||
* Copyright (C) 2022-2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
|
||||
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024 Nick Fragoulis
|
||||
* Copyright (C) 2024 Franck Moreau
|
||||
*
|
||||
* 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
|
||||
|
|
@ -961,10 +962,17 @@ class pdf_sponge extends ModelePDFFactures
|
|||
}
|
||||
$this->tva[$vatrate] += $tvaligne; // ->tva is abandoned, we use now ->tva_array that is more complete
|
||||
$vatcode = $object->lines[$i]->vat_src_code;
|
||||
if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
|
||||
if (getDolGlobalInt('PDF_INVOICE_SHOW_VAT_ANALYSIS')) {
|
||||
if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['tot_ht'])) {
|
||||
$this->tva_array[$vatrate . ($vatcode ? ' (' . $vatcode . ')' : '')]['tot_ht'] = 0;
|
||||
}
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate'=>$vatrate, 'vatcode'=>$vatcode, 'amount'=> $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne, 'tot_ht'=> $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['tot_ht'] + $object->lines[$i]->total_ht);
|
||||
} else {
|
||||
if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
|
||||
}
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
|
||||
}
|
||||
$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
|
||||
|
||||
$nexY = max($nexY, $posYAfterImage);
|
||||
|
||||
|
|
@ -1260,6 +1268,65 @@ class pdf_sponge extends ModelePDFFactures
|
|||
|
||||
$pdf->SetFont('', '', $default_font_size - 1);
|
||||
|
||||
krsort($this->tva_array);
|
||||
|
||||
// Show VAT details
|
||||
if ($object->total_tva != 0 && getDolGlobalInt('PDF_INVOICE_SHOW_VAT_ANALYSIS')) {
|
||||
$pdf->SetFillColor(224, 224, 224);
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche, $posy);
|
||||
$titre = $outputlangs->transnoentities("VAT");
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L', true);
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 25, $posy);
|
||||
$titre = $outputlangs->transnoentities("NetTotal");
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L', true);
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 50, $posy);
|
||||
$titre = $outputlangs->transnoentities("VATAmount");
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L', true);
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 75, $posy);
|
||||
$titre = $outputlangs->transnoentities("AmountTotal");
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L', true);
|
||||
|
||||
$posy = $pdf->GetY();
|
||||
$tot_ht = 0;
|
||||
$tot_tva = 0;
|
||||
$tot_ttc = 0;
|
||||
|
||||
foreach ($this->tva_array as $tvakey => $tvaval) {
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche, $posy);
|
||||
$titre = round((float) $tvakey, 2) . "%";
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L');
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 25, $posy);
|
||||
$titre = price($tvaval['tot_ht']);
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L');
|
||||
$tot_ht += $tvaval['tot_ht'];
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 50, $posy);
|
||||
$titre = price($tvaval['amount']);
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L');
|
||||
$tot_tva += $tvaval['amount'];
|
||||
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
$pdf->SetXY($this->marge_gauche + 75, $posy);
|
||||
$titre = price($tvaval['tot_ht'] + $tvaval['amount']);
|
||||
$pdf->MultiCell(25, 4, $titre, 0, 'L');
|
||||
$tot_ttc += ($tvaval['tot_ht'] + $tvaval['amount']);
|
||||
|
||||
$posy = $pdf->GetY();
|
||||
}
|
||||
}
|
||||
|
||||
// If France, show VAT mention if not applicable
|
||||
if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
|
||||
$pdf->SetFont('', '', $default_font_size - 2);
|
||||
|
|
@ -1711,6 +1778,16 @@ class pdf_sponge extends ModelePDFFactures
|
|||
$pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($largcol2, $tab2_hl, price($sign * ($total_ht + (!empty($object->remise) ? $object->remise : 0)), 0, $outputlangs), 0, 'R', 1);
|
||||
|
||||
if (getDolGlobalInt('PDF_INVOICE_SHOW_VAT_ANALYSIS')) {
|
||||
$index++;
|
||||
$pdf->SetFillColor(255, 255, 255);
|
||||
$pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalVAT"), 0, 'L', 1);
|
||||
|
||||
$pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($largcol2, $tab2_hl, price($sign * $object->total_tva), 0, 'R', 1);
|
||||
}
|
||||
|
||||
// Show VAT by rates and total
|
||||
$pdf->SetFillColor(248, 248, 248);
|
||||
|
||||
|
|
@ -1821,34 +1898,36 @@ class pdf_sponge extends ModelePDFFactures
|
|||
}
|
||||
}
|
||||
|
||||
// VAT
|
||||
foreach ($this->tva_array as $tvakey => $tvaval) {
|
||||
if ($tvakey != 0) { // On affiche pas taux 0
|
||||
$this->atleastoneratenotnull++;
|
||||
if (!getDolGlobalInt('PDF_INVOICE_SHOW_VAT_ANALYSIS')) {
|
||||
// VAT
|
||||
foreach ($this->tva_array as $tvakey => $tvaval) {
|
||||
if ($tvakey != 0) { // On affiche pas taux 0
|
||||
$this->atleastoneratenotnull++;
|
||||
|
||||
$index++;
|
||||
$pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
|
||||
$index++;
|
||||
$pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
|
||||
|
||||
$tvacompl = '';
|
||||
if (preg_match('/\*/', $tvakey)) {
|
||||
$tvakey = str_replace('*', '', $tvakey);
|
||||
$tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
|
||||
$tvacompl = '';
|
||||
if (preg_match('/\*/', $tvakey)) {
|
||||
$tvakey = str_replace('*', '', $tvakey);
|
||||
$tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
|
||||
}
|
||||
$totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
|
||||
$totalvat .= ' ';
|
||||
if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') {
|
||||
$totalvat .= vatrate($tvaval['vatrate'], 1).$tvacompl;
|
||||
} elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') {
|
||||
$totalvat .= $tvaval['vatcode'].$tvacompl;
|
||||
} elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
|
||||
$totalvat .= $tvacompl;
|
||||
} else {
|
||||
$totalvat .= vatrate($tvaval['vatrate'], 1).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl;
|
||||
}
|
||||
$pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
|
||||
|
||||
$pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($largcol2, $tab2_hl, price(price2num($tvaval['amount'], 'MT'), 0, $outputlangs), 0, 'R', 1);
|
||||
}
|
||||
$totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
|
||||
$totalvat .= ' ';
|
||||
if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') {
|
||||
$totalvat .= vatrate($tvaval['vatrate'], 1).$tvacompl;
|
||||
} elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') {
|
||||
$totalvat .= $tvaval['vatcode'].$tvacompl;
|
||||
} elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
|
||||
$totalvat .= $tvacompl;
|
||||
} else {
|
||||
$totalvat .= vatrate($tvaval['vatrate'], 1).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl;
|
||||
}
|
||||
$pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
|
||||
|
||||
$pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
|
||||
$pdf->MultiCell($largcol2, $tab2_hl, price(price2num($tvaval['amount'], 'MT'), 0, $outputlangs), 0, 'R', 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2579,6 +2579,7 @@ CaptchaDesc=If you want to protect your login page with a Captcha, you can choos
|
|||
DolibarrStandardCaptcha=A native captcha generated by Dolibarr
|
||||
SALES_ORDER_SHOW_SHIPPING_ADDRESS=Show shipping address
|
||||
SALES_ORDER_SHOW_SHIPPING_ADDRESSMore=Compulsory indication in some countries (France, ...)
|
||||
PDF_INVOICE_SHOW_VAT_ANALYSIS=Show vat analysis per rate
|
||||
MaxNbOfRecordOnListIsOk=You have a max size for lists is set to <b>%s</b> lines. This is a good value.
|
||||
YouHaveALargeAmountOfRecordOnLists=You have a default max size for lists set to <b>%s</b> lines. This is a large value that need scrolling to see all answers. It is better to have a value lower than <b>%s</b> and use pagination to see record over this number. Change this in menu Home - Setup - Display.
|
||||
RoundBorders=Round borders
|
||||
|
|
|
|||
|
|
@ -1317,6 +1317,8 @@ NbRecordQualified=Number of qualified records
|
|||
auto=auto
|
||||
UploadFile=Direct import of document
|
||||
OrClickToSelectAFile=or click to select a file on disk
|
||||
NetTotal=Net total
|
||||
VATAmount=VAT amount
|
||||
TotalDiscount=Total discount
|
||||
TotalHTBeforeDiscount=Total net before discount
|
||||
Contains=Contains
|
||||
|
|
|
|||
Loading…
Reference in a new issue