diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index 8ce7fb24aeb..74ff2141820 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -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; + } } diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 037074bce23..f9c6c1a9ee3 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -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) { diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 8d01927e1dc..68216c7315e 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -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) {