Some country need qr code for legal issues. Add a hook to allow this.

This commit is contained in:
Laurent Destailleur 2022-01-04 20:44:17 +01:00
parent 7228c762cd
commit 0189d92139
3 changed files with 136 additions and 5 deletions

View File

@ -811,6 +811,64 @@ abstract class CommonInvoice extends CommonObject
return -1;
}
}
/**
* Build string for ZATCA QR Code (Arabi Saudia)
*
* @return string String for ZATCA QR Code
*/
public function buildZATCAQRString()
{
global $conf;
$tmplang = new Translate('', $conf);
$tmplang->setDefaultLang('en_US');
$tmplang->load("main");
$datestring = dol_print_date($this->date, 'dayhourrfc');
$pricewithtaxstring = price($this->total_ttc, 0, $tmplang, 0, -1, 2);
$pricetaxstring = price($this->total_tva, 0, $tmplang, 0, -1, 2);
/*
$name = implode(unpack("H*", $this->thirdparty->name));
$vatnumber = implode(unpack("H*", $this->thirdparty->tva_intra));
$date = implode(unpack("H*", $datestring));
$pricewithtax = implode(unpack("H*", price2num($pricewithtaxstring, 2)));
$pricetax = implode(unpack("H*", $pricetaxstring));
var_dump(strlen($this->thirdparty->name));
var_dump(str_pad(dechex('9'), 2, '0', STR_PAD_LEFT));
var_dump($this->thirdparty->name);
var_dump(implode(unpack("H*", $this->thirdparty->name)));
var_dump(price($this->total_tva, 0, $tmplang, 0, -1, 2));
$s = '01'.str_pad(dechex(strlen($this->thirdparty->name)), 2, '0', STR_PAD_LEFT).$name;
$s .= '02'.str_pad(dechex(strlen($this->thirdparty->tva_intra)), 2, '0', STR_PAD_LEFT).$vatnumber;
$s .= '03'.str_pad(dechex(strlen($datestring)), 2, '0', STR_PAD_LEFT).$date;
$s .= '04'.str_pad(dechex(strlen($pricewithtaxstring)), 2, '0', STR_PAD_LEFT).$pricewithtax;
$s .= '05'.str_pad(dechex(strlen($pricetaxstring)), 2, '0', STR_PAD_LEFT).$pricetax;
$s .= ''; // Hash of xml invoice
$s .= ''; // ecda signature
$s .= ''; // ecda public key
$s .= ''; // ecda signature of public key stamp
*/
// Using TLV format
$s = pack('C1', 1).pack('C1', strlen($this->thirdparty->name)).$this->thirdparty->name;
$s .= pack('C1', 2).pack('C1', strlen($this->thirdparty->tva_intra)).$this->thirdparty->tva_intra;
$s .= pack('C1', 3).pack('C1', strlen($datestring)).$date;
$s .= pack('C1', 4).pack('C1', strlen($pricewithtaxstring)).$pricewithtaxstring;
$s .= pack('C1', 5).pack('C1', strlen($pricetaxstring)).$pricetaxstring;
$s .= ''; // Hash of xml invoice
$s .= ''; // ecda signature
$s .= ''; // ecda public key
$s .= ''; // ecda signature of public key stamp
$s = base64_encode($s);
return $s;
}
}

View File

@ -428,15 +428,54 @@ class pdf_crabe extends ModelePDFFactures
}
$pagenb++;
// Output header (logo, ref and address blocks). This is first call for first page.
$top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs);
$pdf->SetFont('', '', $default_font_size - 1);
$pdf->MultiCell(0, 3, ''); // Set interline to 3
$pdf->SetTextColor(0, 0, 0);
$tab_top = 90 + $top_shift;
// $pdf->GetY() here can't be used. It is bottom of the second addresse box but first one may be higher
// $tab_top is y where we must continue content (90 = 42 + 48: 42 is height of logo and ref, 48 is address blocks)
$tab_top = 90 + $top_shift; // top_shift is an addition for linked objects or addons (0 in most cases)
$tab_top_newpage = (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD) ? 42 + $top_shift : 10);
// You can add more thing under header here, if you increase $extra_under_address_shift too.
$extra_under_address_shift = 0;
if (! empty($conf->global->INVOICE_ADD_ZATCA_QR_CODE)) {
$qrcodestring = $object->buildZATCAQRString();
$qrcodecolor = array('25', '25', '25');
// set style for QR-code
$styleQr = array(
'border' => false,
'padding' => 0,
'fgcolor' => $qrcodecolor,
'bgcolor' => false, //array(255,255,255)
'module_width' => 1, // width of a single module in points
'module_height' => 1 // height of a single module in points
);
$pdf->write2DBarcode($qrcodestring, 'QRCODE,M', $this->marge_gauche, $tab_top - 5, 25, 25, $styleQr, 'N');
$extra_under_address_shift += 25;
}
// Call hook printUnderHeaderPDFline
$parameters = array(
'object' => $object,
'i' => $i,
'pdf' =>& $pdf,
'outputlangs' => $outputlangs,
'hidedetails' => $hidedetails
);
$reshook = $hookmanager->executeHooks('printUnderHeaderPDFline', $parameters, $this); // Note that $object may have been modified by hook
if (!empty($hookmanager->resArray['extra_under_address_shift'])) {
$extra_under_address_shift += $hookmanager->resArray['extra_under_header_shift'];
}
$tab_top += $extra_under_address_shift;
$tab_top_new_page += $extra_under_address_shift;
// Incoterm
$height_incoterms = 0;
if (!empty($conf->incoterm->enabled)) {
$desc_incoterms = $object->getIncotermsForPDF();
if ($desc_incoterms) {
@ -1644,7 +1683,7 @@ class pdf_crabe extends ModelePDFFactures
* @param int $showaddress 0=no, 1=yes
* @param Translate $outputlangs Object lang for output
* @param Translate $outputlangsbis Object lang for output bis
* @return void
* @return int top shift of linked object lines
*/
protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null)
{

View File

@ -417,13 +417,47 @@ class pdf_sponge extends ModelePDFFactures
$pdf->MultiCell(0, 3, ''); // Set interline to 3
$pdf->SetTextColor(0, 0, 0);
// You can add more thing undr header here, if you increase top_shift too.
// TODO
// $pdf->GetY() here can't be used. It is bottom of the second addresse box but first one may be higher
// $tab_top is y where we must continue content (90 = 42 + 48: 42 is height of logo and ref, 48 is address blocks)
$tab_top = 90 + $top_shift; // top_shift is an addition for linked objects or addons (0 in most cases)
$tab_top_newpage = (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD) ? 42 + $top_shift : 10);
// You can add more thing under header here, if you increase $extra_under_address_shift too.
$extra_under_address_shift = 0;
if (! empty($conf->global->INVOICE_ADD_ZATCA_QR_CODE)) {
$qrcodestring = $object->buildZATCAQRString();
$qrcodecolor = array('25', '25', '25');
// set style for QR-code
$styleQr = array(
'border' => false,
'padding' => 0,
'fgcolor' => $qrcodecolor,
'bgcolor' => false, //array(255,255,255)
'module_width' => 1, // width of a single module in points
'module_height' => 1 // height of a single module in points
);
$pdf->write2DBarcode($qrcodestring, 'QRCODE,M', $this->marge_gauche, $tab_top - 5, 25, 25, $styleQr, 'N');
$extra_under_address_shift += 25;
}
// Call hook printUnderHeaderPDFline
$parameters = array(
'object' => $object,
'i' => $i,
'pdf' =>& $pdf,
'outputlangs' => $outputlangs,
'hidedetails' => $hidedetails
);
$reshook = $hookmanager->executeHooks('printUnderHeaderPDFline', $parameters, $this); // Note that $object may have been modified by hook
if (!empty($hookmanager->resArray['extra_under_address_shift'])) {
$extra_under_address_shift += $hookmanager->resArray['extra_under_header_shift'];
}
$tab_top += $extra_under_address_shift;
$tab_top_new_page += $extra_under_address_shift;
// Define heigth of table for lines (for first page)
$tab_height = $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext;
@ -1863,7 +1897,7 @@ class pdf_sponge extends ModelePDFFactures
* @param int $showaddress 0=no, 1=yes (usually set to 1 for first page, and 0 for next pages)
* @param Translate $outputlangs Object lang for output
* @param Translate $outputlangsbis Object lang for output bis
* @return void
* @return int top shift of linked object lines
*/
protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null)
{