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:
sonikf 2024-11-13 23:41:00 +02:00 committed by GitHub
parent 2c4d1038d0
commit 1f2bb2969a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 377 additions and 123 deletions

View file

@ -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"));

View file

@ -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);
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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