From 0b5bf953d7af542abca30ebb41f2db12add3f214 Mon Sep 17 00:00:00 2001 From: Benoit Vianin Date: Sat, 4 Mar 2023 17:04:33 +0100 Subject: [PATCH 1/7] Add support for QR IBAN and reference --- .../facture/doc/pdf_swissqr.modules.php | 3983 +++++++++-------- 1 file changed, 2007 insertions(+), 1976 deletions(-) diff --git a/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php b/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php index fefb8df..8909773 100644 --- a/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php @@ -47,859 +47,860 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; */ class pdf_swissqr extends ModelePDFFactures { - /** - * @var DoliDb Database handler - */ - public $db; - - /** - * @var string model name - */ - public $name; - - /** - * @var string model description (short text) - */ - public $description; - - /** - * @var int Save the name of generated file as the main doc when generating a doc with this template - */ - public $update_main_doc_field; - - /** - * @var string document type - */ - public $type; - - /** - * @var array Minimum version of PHP required by module. - * e.g.: PHP ≥ 5.6 = array(5, 6) - */ - public $phpmin = array(5, 6); - - /** - * Dolibarr version of the loaded document - * @var string - */ - public $version = 'dolibarr'; - - /** - * @var int page_largeur - */ - public $page_largeur; - - /** - * @var int page_hauteur - */ - public $page_hauteur; - - /** - * @var array format - */ - public $format; - - /** - * @var int marge_gauche - */ - public $marge_gauche; - - /** - * @var int marge_droite - */ - public $marge_droite; - - /** - * @var int marge_haute - */ - public $marge_haute; - - /** - * @var int marge_basse - */ - public $marge_basse; - - /** - * Issuer - * @var Societe Object that emits - */ - public $emetteur; - - /** - * @var bool Situation invoice type - */ - public $situationinvoice; - - /** - * @var float X position for the situation progress column - */ - public $posxprogress; - - - /** - * Constructor - * - * @param DoliDB $db Database handler - */ - public function __construct($db) - { - global $conf, $langs, $mysoc; - - // Translations - $langs->loadLangs(array("main", "bills")); - - $this->db = $db; - $this->name = "SwissQR"; - $this->description = 'Swiss QR invoice'; - $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template - - // Dimension page - $this->type = 'pdf'; - $formatarray = pdf_getFormat(); - $this->page_largeur = $formatarray['width']; - $this->page_hauteur = $formatarray['height']; - $this->format = array($this->page_largeur, $this->page_hauteur); - $this->marge_gauche = isset($conf->global->MAIN_PDF_MARGIN_LEFT) ? $conf->global->MAIN_PDF_MARGIN_LEFT : 10; - $this->marge_droite = isset($conf->global->MAIN_PDF_MARGIN_RIGHT) ? $conf->global->MAIN_PDF_MARGIN_RIGHT : 10; - $this->marge_haute = isset($conf->global->MAIN_PDF_MARGIN_TOP) ? $conf->global->MAIN_PDF_MARGIN_TOP : 10; - $this->marge_basse = isset($conf->global->MAIN_PDF_MARGIN_BOTTOM) ? $conf->global->MAIN_PDF_MARGIN_BOTTOM : 10; - - $this->option_logo = 1; // Display logo - $this->option_tva = 1; // Manage the vat option FACTURE_TVAOPTION - $this->option_modereg = 1; // Display payment mode - $this->option_condreg = 1; // Display payment terms - $this->option_multilang = 1; // Available in several languages - $this->option_escompte = 1; // Displays if there has been a discount - $this->option_credit_note = 1; // Support credit notes - $this->option_freetext = 1; // Support add of a personalised text - $this->option_draft_watermark = 1; // Support add of a watermark on drafts - $this->watermark = ''; - - // Get source company - $this->emetteur = $mysoc; - if (empty($this->emetteur->country_code)) { - $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined - } - - // Define position of columns - $this->posxdesc = $this->marge_gauche + 1; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { - $this->posxtva = 101; - $this->posxup = 118; - $this->posxqty = 135; - $this->posxunit = 151; - } else { - $this->posxtva = 110; - $this->posxup = 126; - $this->posxqty = 145; - $this->posxunit = 162; - } - $this->posxprogress = 151; // Only displayed for situation invoices - $this->posxdiscount = 162; - $this->posxprogress = 174; - $this->postotalht = 174; - if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) || !empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) { - $this->posxtva = $this->posxup; - } - $this->posxpicture = $this->posxtva - (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH) ? 20 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH); // width of images - if ($this->page_largeur < 210) { // To work with US executive format - $this->posxpicture -= 20; - $this->posxtva -= 20; - $this->posxup -= 20; - $this->posxqty -= 20; - $this->posxunit -= 20; - $this->posxdiscount -= 20; - $this->posxprogress -= 20; - $this->postotalht -= 20; - } - - $this->tva = array(); - $this->tva_array = array(); - $this->localtax1 = array(); - $this->localtax2 = array(); - $this->atleastoneratenotnull = 0; - $this->atleastonediscount = 0; - $this->situationinvoice = false; - } - - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Function to build pdf onto disk - * - * @param Facture $object Object to generate - * @param Translate $outputlangs Lang output object - * @param string $srctemplatepath Full path of source filename for generator using a template file - * @param int $hidedetails Do not show line details - * @param int $hidedesc Do not show desc - * @param int $hideref Do not show ref - * @return int 1=OK, 0=KO - */ - public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0) - { - // phpcs:enable - global $user, $langs, $conf, $mysoc, $hookmanager, $nblines; - - dol_syslog("write_file outputlangs->defaultlang=".(is_object($outputlangs) ? $outputlangs->defaultlang : 'null')); - - if (!is_object($outputlangs)) { - $outputlangs = $langs; - } - // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO - if (!empty($conf->global->MAIN_USE_FPDF)) { - $outputlangs->charset_output = 'ISO-8859-1'; - } - - // Load translation files required by the page - $outputlangs->loadLangs(array("main", "bills", "products", "dict", "companies")); - - // Show Draft Watermark - if ($object->statut == $object::STATUS_DRAFT && (!empty($conf->global->FACTURE_DRAFT_WATERMARK))) { - $this->watermark = $conf->global->FACTURE_DRAFT_WATERMARK; - } - - global $outputlangsbis; - $outputlangsbis = null; - if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && $outputlangs->defaultlang != $conf->global->PDF_USE_ALSO_LANGUAGE_CODE) { - $outputlangsbis = new Translate('', $conf); - $outputlangsbis->setDefaultLang($conf->global->PDF_USE_ALSO_LANGUAGE_CODE); - $outputlangsbis->loadLangs(array("main", "bills", "products", "dict", "companies")); - } - - $nblines = count($object->lines); - - // Loop on each lines to detect if there is at least one image to show - $realpatharray = array(); - if (!empty($conf->global->MAIN_GENERATE_INVOICES_WITH_PICTURE)) { - for ($i = 0; $i < $nblines; $i++) { - if (empty($object->lines[$i]->fk_product)) { - continue; - } - - $objphoto = new Product($this->db); - $objphoto->fetch($object->lines[$i]->fk_product); - - $pdir = get_exdir($object->lines[$i]->fk_product, 2, 0, 0, $objphoto, 'product').$object->lines[$i]->fk_product."/photos/"; - $dir = $conf->product->dir_output.'/'.$pdir; - - $realpath = ''; - foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) { - $filename = $obj['photo']; - //if ($obj['photo_vignette']) $filename='thumbs/'.$obj['photo_vignette']; - $realpath = $dir.$filename; - break; - } - - if ($realpath) { - $realpatharray[$i] = $realpath; - } - } - } - if (count($realpatharray) == 0) { - $this->posxpicture = $this->posxtva; - } - - if ($conf->facture->dir_output) { - $object->fetch_thirdparty(); - - $deja_regle = $object->getSommePaiement((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? 1 : 0); - $amount_credit_notes_included = $object->getSumCreditNotesUsed((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? 1 : 0); - $amount_deposits_included = $object->getSumDepositsUsed((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? 1 : 0); - - // Definition of $dir and $file - if ($object->specimen) { - $dir = empty($conf->facture->multidir_output[$conf->entity]) ? $conf->facture->dir_output : $conf->facture->multidir_output[$conf->entity]; - $file = $dir."/SPECIMEN.pdf"; - } else { - $objectref = dol_sanitizeFileName($object->ref); - $dir = (empty($conf->facture->multidir_output[$conf->entity]) ? $conf->facture->dir_output : $conf->facture->multidir_output[$conf->entity])."/".$objectref; - $file = $dir."/".$objectref.".pdf"; - } - if (!file_exists($dir)) { - if (dol_mkdir($dir) < 0) { - $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir); - return 0; - } - } - - if (file_exists($dir)) { - // Add pdfgeneration hook - if (!is_object($hookmanager)) { - include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; - $hookmanager = new HookManager($this->db); - } - $hookmanager->initHooks(array('pdfgeneration')); - $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs); - global $action; - $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks - - // Set nblines with the new facture lines content after hook - $nblines = count($object->lines); - $nbpayments = count($object->getListOfPayments()); - - // Create pdf instance - $pdf = pdf_getInstance($this->format); - $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance - $pdf->SetAutoPageBreak(1, 0); - - $heightforinfotot = 50 + (4 * $nbpayments); // Height reserved to output the info and total part and payment part - if ($heightforinfotot > 220) { - $heightforinfotot = 220; - } - $heightforfreetext = (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT) ? $conf->global->MAIN_PDF_FREETEXT_HEIGHT : 5); // Height reserved to output the free text on last page - $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) - if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS)) { - $heightforfooter += 6; - } - - if (class_exists('TCPDF')) { - $pdf->setPrintHeader(false); - $pdf->setPrintFooter(false); - } - $pdf->SetFont(pdf_getPDFFont($outputlangs)); - - // Set path to the background PDF File - if (!empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) { - $logodir = $conf->mycompany->dir_output; - if (!empty($conf->mycompany->multidir_output[$object->entity])) { - $logodir = $conf->mycompany->multidir_output[$object->entity]; - } - $pagecount = $pdf->setSourceFile($logodir.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND); - $tplidx = $pdf->importPage(1); - } - - $pdf->Open(); - $pagenb = 0; - $pdf->SetDrawColor(128, 128, 128); - - $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref)); - $pdf->SetSubject($outputlangs->transnoentities("PdfInvoiceTitle")); - $pdf->SetCreator("Dolibarr ".DOL_VERSION); - $pdf->SetAuthor($mysoc->name.($user->id > 0 ? ' - '.$outputlangs->convToOutputCharset($user->getFullName($outputlangs)) : '')); - $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PdfInvoiceTitle")." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); - if (!empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) { - $pdf->SetCompression(false); - } - - // Set certificate - $cert = empty($user->conf->CERTIFICATE_CRT) ? '' : $user->conf->CERTIFICATE_CRT; - $certprivate = empty($user->conf->CERTIFICATE_CRT_PRIVATE) ? '' : $user->conf->CERTIFICATE_CRT_PRIVATE; - // If user has no certificate, we try to take the company one - if (!$cert) { - $cert = empty($conf->global->CERTIFICATE_CRT) ? '' : $conf->global->CERTIFICATE_CRT; - } - if (!$certprivate) { - $certprivate = empty($conf->global->CERTIFICATE_CRT_PRIVATE) ? '' : $conf->global->CERTIFICATE_CRT_PRIVATE; - } - // If a certificate is found - if ($cert) { - $info = array( - 'Name' => $this->emetteur->name, - 'Location' => getCountry($this->emetteur->country_code, 0), - 'Reason' => 'INVOICE', - 'ContactInfo' => $this->emetteur->email - ); - $pdf->setSignature($cert, $certprivate, $this->emetteur->name, '', 2, $info); - } - - $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right - - // Set $this->atleastonediscount if you have at least one discount - for ($i = 0; $i < $nblines; $i++) { - if ($object->lines[$i]->remise_percent) { - $this->atleastonediscount++; - } - } - if (empty($this->atleastonediscount)) { // retrieve space not used by discount - $delta = ($this->posxprogress - $this->posxdiscount); - $this->posxpicture += $delta; - $this->posxtva += $delta; - $this->posxup += $delta; - $this->posxqty += $delta; - $this->posxunit += $delta; - $this->posxdiscount += $delta; - // post of fields after are not modified, stay at same position - } - - $progress_width = 0; - // Situation invoice handling - if ($object->situation_cycle_ref && empty($conf->global->MAIN_PDF_HIDE_SITUATION)) { - $this->situationinvoice = true; - $progress_width = 10; - $this->posxpicture -= $progress_width; - $this->posxtva -= $progress_width; - $this->posxup -= $progress_width; - $this->posxqty -= $progress_width; - $this->posxunit -= $progress_width; - $this->posxdiscount -= $progress_width; - $this->posxprogress -= $progress_width; - } - - // New page - $pdf->AddPage(); - if (!empty($tplidx)) { - $pdf->useTemplate($tplidx); - } - $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); - - // $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; - $qrcodestring = ''; - if (! empty($conf->global->INVOICE_ADD_ZATCA_QR_CODE)) { - $qrcodestring = $object->buildZATCAQRString(); - } elseif (! empty($conf->global->INVOICE_ADD_SWISS_QR_CODE)) { - $qrcodestring = $object->buildSwitzerlandQRString(); - } - if ($qrcodestring) { - $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_newpage += 0; - - // Incoterm - $height_incoterms = 0; - if (!empty($conf->incoterm->enabled)) { - $desc_incoterms = $object->getIncotermsForPDF(); - if ($desc_incoterms) { - $tab_top -= 2; - - $pdf->SetFont('', '', $default_font_size - 1); - $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1); - $nexY = $pdf->GetY(); - $height_incoterms = $nexY - $tab_top; - - // Rect takes a length in 3rd parameter - $pdf->SetDrawColor(192, 192, 192); - $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_incoterms + 1); - - $tab_top = $nexY + 6; - } - } - - // Display notes - $notetoshow = empty($object->note_public) ? '' : $object->note_public; - if (!empty($conf->global->MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE)) { - // Get first sale rep - if (is_object($object->thirdparty)) { - $salereparray = $object->thirdparty->getSalesRepresentatives($user); - $salerepobj = new User($this->db); - $salerepobj->fetch($salereparray[0]['id']); - if (!empty($salerepobj->signature)) { - $notetoshow = dol_concatdesc($notetoshow, $salerepobj->signature); - } - } - } - // Extrafields in note - $extranote = $this->getExtrafieldsInHtml($object, $outputlangs); - if (!empty($extranote)) { - $notetoshow = dol_concatdesc($notetoshow, $extranote); - } - if ($notetoshow) { - $tab_top -= 2; - - $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object); - complete_substitutions_array($substitutionarray, $outputlangs, $object); - - $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs); - $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow); - - $pdf->SetFont('', '', $default_font_size - 1); - $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($notetoshow), 0, 1); - $nexY = $pdf->GetY(); - $height_note = $nexY - $tab_top; - - // Rect takes a length in 3rd parameter - $pdf->SetDrawColor(192, 192, 192); - $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 1); - - $tab_top = $nexY + 6; - } - - $iniY = $tab_top + 7; - $curY = $tab_top + 7; - $nexY = $tab_top + 7; - - // Loop on each lines - for ($i = 0; $i < $nblines; $i++) { - $curY = $nexY; - $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage - $pdf->SetTextColor(0, 0, 0); - - // Define size of image if we need it - $imglinesize = array(); - if (!empty($realpatharray[$i])) { - $imglinesize = pdf_getSizeForImage($realpatharray[$i]); - } - - $pdf->setTopMargin($tab_top_newpage); - $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it. - $pageposbefore = $pdf->getPage(); - - $showpricebeforepagebreak = 1; - $posYAfterImage = 0; - $posYAfterDescription = 0; - - // We start with Photo of product line - if (isset($imglinesize['width']) && isset($imglinesize['height']) && ($curY + $imglinesize['height']) > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // If photo too high, we moved completely on new page - $pdf->AddPage('', '', true); - if (!empty($tplidx)) { - $pdf->useTemplate($tplidx); - } - if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { - $this->_pagehead($pdf, $object, 0, $outputlangs); - } - $pdf->setPage($pageposbefore + 1); - - $curY = $tab_top_newpage; - - // Allows data in the first page if description is long enough to break in multiples pages - if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) { - $showpricebeforepagebreak = 1; - } else { - $showpricebeforepagebreak = 0; - } - } - - if (isset($imglinesize['width']) && isset($imglinesize['height'])) { - $curX = $this->posxpicture - 1; - $pdf->Image($realpatharray[$i], $curX + (($this->posxtva - $this->posxpicture - $imglinesize['width']) / 2), $curY, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi - // $pdf->Image does not increase value return by getY, so we save it manually - $posYAfterImage = $curY + $imglinesize['height']; - } - - // Description of product line - $curX = $this->posxdesc - 1; - - $pdf->startTransaction(); - pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxpicture - $curX - $progress_width, 3, $curX, $curY, $hideref, $hidedesc); - $pageposafter = $pdf->getPage(); - if ($pageposafter > $pageposbefore) { // There is a pagebreak - $pdf->rollbackTransaction(true); - $pageposafter = $pageposbefore; - //print $pageposafter.'-'.$pageposbefore;exit; - $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it. - pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxpicture - $curX - $progress_width, 3, $curX, $curY, $hideref, $hidedesc); - $pageposafter = $pdf->getPage(); - $posyafter = $pdf->GetY(); - //var_dump($posyafter); var_dump(($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))); exit; - if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text - if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page - $pdf->AddPage('', '', true); - if (!empty($tplidx)) { - $pdf->useTemplate($tplidx); - } - if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { - $this->_pagehead($pdf, $object, 0, $outputlangs); - } - $pdf->setPage($pageposafter + 1); - } - } else { - // We found a page break - - // Allows data in the first page if description is long enough to break in multiples pages - if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) { - $showpricebeforepagebreak = 1; - } else { - $showpricebeforepagebreak = 0; - } - } - } else // No pagebreak - { - $pdf->commitTransaction(); - } - $posYAfterDescription = $pdf->GetY(); - - $nexY = $pdf->GetY(); - $pageposafter = $pdf->getPage(); - $pdf->setPage($pageposbefore); - $pdf->setTopMargin($this->marge_haute); - $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. - - // We suppose that a too long description or photo were moved completely on next page - if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) { - $pdf->setPage($pageposafter); - $curY = $tab_top_newpage; - } - - $pdf->SetFont('', '', $default_font_size - 1); // We reposition the default font - - // VAT Rate - if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) && empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) { - $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails); - $pdf->SetXY($this->posxtva - 5, $curY); - $pdf->MultiCell($this->posxup - $this->posxtva + 4, 3, $vat_rate, 0, 'R'); - } - - // Unit price before discount - $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails); - $pdf->SetXY($this->posxup, $curY); - $pdf->MultiCell($this->posxqty - $this->posxup - 0.8, 3, $up_excl_tax, 0, 'R', 0); - - // Quantity - $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails); - $pdf->SetXY($this->posxqty, $curY); - $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R'); // Enough for 6 chars - - // Unit - if (!empty($conf->global->PRODUCT_USE_UNITS)) { - $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails, $hookmanager); - $pdf->SetXY($this->posxunit, $curY); - $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 4, $unit, 0, 'L'); - } - - // Discount on line - if ($object->lines[$i]->remise_percent) { - $pdf->SetXY($this->posxdiscount - 2, $curY); - $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails); - $pdf->MultiCell($this->posxprogress - $this->posxdiscount + 2, 3, $remise_percent, 0, 'R'); - } - - // Situation progress - if ($this->situationinvoice) { - $progress = pdf_getlineprogress($object, $i, $outputlangs, $hidedetails); - $pdf->SetXY($this->posxprogress, $curY); - $pdf->MultiCell($this->postotalht - $this->posxprogress + 1, 3, $progress, 0, 'R'); - } - - // Total HT line - $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails); - $pdf->SetXY($this->postotalht, $curY); - $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalht, 3, $total_excl_tax, 0, 'R', 0); - - - $sign = 1; - if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) { - $sign = -1; - } - // Collection of totals by value of VAT in $this->tva["taux"]=total_tva - $prev_progress = $object->lines[$i]->get_prev_progress($object->id); - if ($prev_progress > 0 && !empty($object->lines[$i]->situation_percent)) { // Compute progress from previous situation - if (!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) { - $tvaligne = $sign * $object->lines[$i]->multicurrency_total_tva * ($object->lines[$i]->situation_percent - $prev_progress) / $object->lines[$i]->situation_percent; - } else { - $tvaligne = $sign * $object->lines[$i]->total_tva * ($object->lines[$i]->situation_percent - $prev_progress) / $object->lines[$i]->situation_percent; - } - } else { - if (!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) { - $tvaligne = $sign * $object->lines[$i]->multicurrency_total_tva; - } else { - $tvaligne = $sign * $object->lines[$i]->total_tva; - } - } - - $localtax1ligne = $object->lines[$i]->total_localtax1; - $localtax2ligne = $object->lines[$i]->total_localtax2; - $localtax1_rate = $object->lines[$i]->localtax1_tx; - $localtax2_rate = $object->lines[$i]->localtax2_tx; - $localtax1_type = $object->lines[$i]->localtax1_type; - $localtax2_type = $object->lines[$i]->localtax2_type; - - if ($object->remise_percent) { - $tvaligne -= ($tvaligne * $object->remise_percent) / 100; - } - if ($object->remise_percent) { - $localtax1ligne -= ($localtax1ligne * $object->remise_percent) / 100; - } - if ($object->remise_percent) { - $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; - } - - $vatrate = (string) $object->lines[$i]->tva_tx; - - // Retrieve type from database for backward compatibility with old records - if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') // if tax type not defined - && (!empty($localtax1_rate) || !empty($localtax2_rate))) { // and there is local tax - $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $object->thirdparty, $mysoc); - $localtax1_type = isset($localtaxtmp_array[0]) ? $localtaxtmp_array[0] : ''; - $localtax2_type = isset($localtaxtmp_array[2]) ? $localtaxtmp_array[2] : ''; - } - - // retrieve global local tax - if ($localtax1_type && $localtax1ligne != 0) { - $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne; - } - if ($localtax2_type && $localtax2ligne != 0) { - $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne; - } - - if (($object->lines[$i]->info_bits & 0x01) == 0x01) { - $vatrate .= '*'; - } - - // Fill $this->tva and $this->tva_array - if (!isset($this->tva[$vatrate])) { - $this->tva[$vatrate] = 0; - } - $this->tva[$vatrate] += $tvaligne; // ->tva is abandonned, 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; - } - $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; - } - - // Add line - if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblines - 1)) { - $pdf->setPage($pageposafter); - $pdf->SetLineStyle(array('dash'=>'1,1', 'color'=>array(80, 80, 80))); - //$pdf->SetDrawColor(190,190,200); - $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1); - $pdf->SetLineStyle(array('dash'=>0)); - } - - $nexY += 2; // Add space between lines - - // Detect if some page were added automatically and output _tableau for past pages - while ($pagenb < $pageposafter) { - $pdf->setPage($pagenb); - if ($pagenb == 1) { - $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code); - } else { - $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code); - } - $this->_pagefoot($pdf, $object, $outputlangs, 1); - $pagenb++; - $pdf->setPage($pagenb); - $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. - if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { - $this->_pagehead($pdf, $object, 0, $outputlangs); - } - if (!empty($tplidx)) { - $pdf->useTemplate($tplidx); - } - } - if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) { - if ($pagenb == 1) { - $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code); - } else { - $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code); - } - $this->_pagefoot($pdf, $object, $outputlangs, 1); - // New page - $pdf->AddPage(); - if (!empty($tplidx)) { - $pdf->useTemplate($tplidx); - } - $pagenb++; - if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { - $this->_pagehead($pdf, $object, 0, $outputlangs); - } - } - } - - // Show square - if ($pagenb == 1) { - $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0, $object->multicurrency_code); - $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; - } else { - $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code); - $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; - } - dol_syslog("bottomlasttab=".$bottomlasttab." this->page_hauteur=".$this->page_hauteur." heightforinfotot=".$heightforinfotot." heightforfreetext=".$heightforfreetext." heightforfooter=".$heightforfooter); - - // Display info area - $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs, $outputlangsbis); - - // Display total area - $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs, $outputlangsbis); - - // Display Payments area - if (($deja_regle || $amount_credit_notes_included || $amount_deposits_included) && empty($conf->global->INVOICE_NO_PAYMENT_DETAILS)) { - $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs, $heightforfooter); - } - - // Pagefoot - $this->_pagefoot($pdf, $object, $outputlangs); - if (method_exists($pdf, 'AliasNbPages')) { - $pdf->AliasNbPages(); - } - - // Add page for the Swiss QR-invoice + /** + * @var DoliDb Database handler + */ + public $db; + + /** + * @var string model name + */ + public $name; + + /** + * @var string model description (short text) + */ + public $description; + + /** + * @var int Save the name of generated file as the main doc when generating a doc with this template + */ + public $update_main_doc_field; + + /** + * @var string document type + */ + public $type; + + /** + * @var array Minimum version of PHP required by module. + * e.g.: PHP ≥ 5.6 = array(5, 6) + */ + public $phpmin = array(5, 6); + + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; + + /** + * @var int page_largeur + */ + public $page_largeur; + + /** + * @var int page_hauteur + */ + public $page_hauteur; + + /** + * @var array format + */ + public $format; + + /** + * @var int marge_gauche + */ + public $marge_gauche; + + /** + * @var int marge_droite + */ + public $marge_droite; + + /** + * @var int marge_haute + */ + public $marge_haute; + + /** + * @var int marge_basse + */ + public $marge_basse; + + /** + * Issuer + * @var Societe Object that emits + */ + public $emetteur; + + /** + * @var bool Situation invoice type + */ + public $situationinvoice; + + /** + * @var float X position for the situation progress column + */ + public $posxprogress; + + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + global $conf, $langs, $mysoc; + + // Translations + $langs->loadLangs(array("main", "bills")); + + $this->db = $db; + $this->name = "SwissQR"; + $this->description = 'Swiss QR invoice'; + $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template + + // Dimension page + $this->type = 'pdf'; + $formatarray = pdf_getFormat(); + $this->page_largeur = $formatarray['width']; + $this->page_hauteur = $formatarray['height']; + $this->format = array($this->page_largeur, $this->page_hauteur); + $this->marge_gauche = isset($conf->global->MAIN_PDF_MARGIN_LEFT) ? $conf->global->MAIN_PDF_MARGIN_LEFT : 10; + $this->marge_droite = isset($conf->global->MAIN_PDF_MARGIN_RIGHT) ? $conf->global->MAIN_PDF_MARGIN_RIGHT : 10; + $this->marge_haute = isset($conf->global->MAIN_PDF_MARGIN_TOP) ? $conf->global->MAIN_PDF_MARGIN_TOP : 10; + $this->marge_basse = isset($conf->global->MAIN_PDF_MARGIN_BOTTOM) ? $conf->global->MAIN_PDF_MARGIN_BOTTOM : 10; + + $this->option_logo = 1; // Display logo + $this->option_tva = 1; // Manage the vat option FACTURE_TVAOPTION + $this->option_modereg = 1; // Display payment mode + $this->option_condreg = 1; // Display payment terms + $this->option_multilang = 1; // Available in several languages + $this->option_escompte = 1; // Displays if there has been a discount + $this->option_credit_note = 1; // Support credit notes + $this->option_freetext = 1; // Support add of a personalised text + $this->option_draft_watermark = 1; // Support add of a watermark on drafts + $this->watermark = ''; + + // Get source company + $this->emetteur = $mysoc; + if (empty($this->emetteur->country_code)) { + $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined + } + + // Define position of columns + $this->posxdesc = $this->marge_gauche + 1; + if (!empty($conf->global->PRODUCT_USE_UNITS)) { + $this->posxtva = 101; + $this->posxup = 118; + $this->posxqty = 135; + $this->posxunit = 151; + } else { + $this->posxtva = 110; + $this->posxup = 126; + $this->posxqty = 145; + $this->posxunit = 162; + } + $this->posxprogress = 151; // Only displayed for situation invoices + $this->posxdiscount = 162; + $this->posxprogress = 174; + $this->postotalht = 174; + if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) || !empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) { + $this->posxtva = $this->posxup; + } + $this->posxpicture = $this->posxtva - (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH) ? 20 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH); // width of images + if ($this->page_largeur < 210) { // To work with US executive format + $this->posxpicture -= 20; + $this->posxtva -= 20; + $this->posxup -= 20; + $this->posxqty -= 20; + $this->posxunit -= 20; + $this->posxdiscount -= 20; + $this->posxprogress -= 20; + $this->postotalht -= 20; + } + + $this->tva = array(); + $this->tva_array = array(); + $this->localtax1 = array(); + $this->localtax2 = array(); + $this->atleastoneratenotnull = 0; + $this->atleastonediscount = 0; + $this->situationinvoice = false; + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Function to build pdf onto disk + * + * @param Facture $object Object to generate + * @param Translate $outputlangs Lang output object + * @param string $srctemplatepath Full path of source filename for generator using a template file + * @param int $hidedetails Do not show line details + * @param int $hidedesc Do not show desc + * @param int $hideref Do not show ref + * @return int 1=OK, 0=KO + */ + public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0) + { + // phpcs:enable + global $user, $langs, $conf, $mysoc, $hookmanager, $nblines; + + dol_syslog("write_file outputlangs->defaultlang=".(is_object($outputlangs) ? $outputlangs->defaultlang : 'null')); + + if (!is_object($outputlangs)) { + $outputlangs = $langs; + } + // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO + if (!empty($conf->global->MAIN_USE_FPDF)) { + $outputlangs->charset_output = 'ISO-8859-1'; + } + + // Load translation files required by the page + $outputlangs->loadLangs(array("main", "bills", "products", "dict", "companies")); + + // Show Draft Watermark + if ($object->statut == $object::STATUS_DRAFT && (!empty($conf->global->FACTURE_DRAFT_WATERMARK))) { + $this->watermark = $conf->global->FACTURE_DRAFT_WATERMARK; + } + + global $outputlangsbis; + $outputlangsbis = null; + if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && $outputlangs->defaultlang != $conf->global->PDF_USE_ALSO_LANGUAGE_CODE) { + $outputlangsbis = new Translate('', $conf); + $outputlangsbis->setDefaultLang($conf->global->PDF_USE_ALSO_LANGUAGE_CODE); + $outputlangsbis->loadLangs(array("main", "bills", "products", "dict", "companies")); + } + + $nblines = count($object->lines); + + // Loop on each lines to detect if there is at least one image to show + $realpatharray = array(); + if (!empty($conf->global->MAIN_GENERATE_INVOICES_WITH_PICTURE)) { + for ($i = 0; $i < $nblines; $i++) { + if (empty($object->lines[$i]->fk_product)) { + continue; + } + + $objphoto = new Product($this->db); + $objphoto->fetch($object->lines[$i]->fk_product); + + $pdir = get_exdir($object->lines[$i]->fk_product, 2, 0, 0, $objphoto, 'product').$object->lines[$i]->fk_product."/photos/"; + $dir = $conf->product->dir_output.'/'.$pdir; + + $realpath = ''; + foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) { + $filename = $obj['photo']; + //if ($obj['photo_vignette']) $filename='thumbs/'.$obj['photo_vignette']; + $realpath = $dir.$filename; + break; + } + + if ($realpath) { + $realpatharray[$i] = $realpath; + } + } + } + if (count($realpatharray) == 0) { + $this->posxpicture = $this->posxtva; + } + + if ($conf->facture->dir_output) { + $object->fetch_thirdparty(); + + $deja_regle = $object->getSommePaiement((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? 1 : 0); + $amount_credit_notes_included = $object->getSumCreditNotesUsed((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? 1 : 0); + $amount_deposits_included = $object->getSumDepositsUsed((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? 1 : 0); + + // Definition of $dir and $file + if ($object->specimen) { + $dir = empty($conf->facture->multidir_output[$conf->entity]) ? $conf->facture->dir_output : $conf->facture->multidir_output[$conf->entity]; + $file = $dir."/SPECIMEN.pdf"; + } else { + $objectref = dol_sanitizeFileName($object->ref); + $dir = (empty($conf->facture->multidir_output[$conf->entity]) ? $conf->facture->dir_output : $conf->facture->multidir_output[$conf->entity])."/".$objectref; + $file = $dir."/".$objectref.".pdf"; + } + if (!file_exists($dir)) { + if (dol_mkdir($dir) < 0) { + $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir); + return 0; + } + } + + if (file_exists($dir)) { + // Add pdfgeneration hook + if (!is_object($hookmanager)) { + include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; + $hookmanager = new HookManager($this->db); + } + $hookmanager->initHooks(array('pdfgeneration')); + $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs); + global $action; + $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + + // Set nblines with the new facture lines content after hook + $nblines = count($object->lines); + $nbpayments = count($object->getListOfPayments()); + + // Create pdf instance + $pdf = pdf_getInstance($this->format); + $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance + $pdf->SetAutoPageBreak(1, 0); + + $heightforinfotot = 50 + (4 * $nbpayments); // Height reserved to output the info and total part and payment part + if ($heightforinfotot > 220) { + $heightforinfotot = 220; + } + $heightforfreetext = (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT) ? $conf->global->MAIN_PDF_FREETEXT_HEIGHT : 5); // Height reserved to output the free text on last page + $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) + if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS)) { + $heightforfooter += 6; + } + + if (class_exists('TCPDF')) { + $pdf->setPrintHeader(false); + $pdf->setPrintFooter(false); + } + $pdf->SetFont(pdf_getPDFFont($outputlangs)); + + // Set path to the background PDF File + if (!empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) { + $logodir = $conf->mycompany->dir_output; + if (!empty($conf->mycompany->multidir_output[$object->entity])) { + $logodir = $conf->mycompany->multidir_output[$object->entity]; + } + $pagecount = $pdf->setSourceFile($logodir.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND); + $tplidx = $pdf->importPage(1); + } + + $pdf->Open(); + $pagenb = 0; + $pdf->SetDrawColor(128, 128, 128); + + $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref)); + $pdf->SetSubject($outputlangs->transnoentities("PdfInvoiceTitle")); + $pdf->SetCreator("Dolibarr ".DOL_VERSION); + $pdf->SetAuthor($mysoc->name.($user->id > 0 ? ' - '.$outputlangs->convToOutputCharset($user->getFullName($outputlangs)) : '')); + $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PdfInvoiceTitle")." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); + if (!empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) { + $pdf->SetCompression(false); + } + + // Set certificate + $cert = empty($user->conf->CERTIFICATE_CRT) ? '' : $user->conf->CERTIFICATE_CRT; + $certprivate = empty($user->conf->CERTIFICATE_CRT_PRIVATE) ? '' : $user->conf->CERTIFICATE_CRT_PRIVATE; + // If user has no certificate, we try to take the company one + if (!$cert) { + $cert = empty($conf->global->CERTIFICATE_CRT) ? '' : $conf->global->CERTIFICATE_CRT; + } + if (!$certprivate) { + $certprivate = empty($conf->global->CERTIFICATE_CRT_PRIVATE) ? '' : $conf->global->CERTIFICATE_CRT_PRIVATE; + } + // If a certificate is found + if ($cert) { + $info = array( + 'Name' => $this->emetteur->name, + 'Location' => getCountry($this->emetteur->country_code, 0), + 'Reason' => 'INVOICE', + 'ContactInfo' => $this->emetteur->email + ); + $pdf->setSignature($cert, $certprivate, $this->emetteur->name, '', 2, $info); + } + + $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right + + // Set $this->atleastonediscount if you have at least one discount + for ($i = 0; $i < $nblines; $i++) { + if ($object->lines[$i]->remise_percent) { + $this->atleastonediscount++; + } + } + if (empty($this->atleastonediscount)) { // retrieve space not used by discount + $delta = ($this->posxprogress - $this->posxdiscount); + $this->posxpicture += $delta; + $this->posxtva += $delta; + $this->posxup += $delta; + $this->posxqty += $delta; + $this->posxunit += $delta; + $this->posxdiscount += $delta; + // post of fields after are not modified, stay at same position + } + + $progress_width = 0; + // Situation invoice handling + if ($object->situation_cycle_ref && empty($conf->global->MAIN_PDF_HIDE_SITUATION)) { + $this->situationinvoice = true; + $progress_width = 10; + $this->posxpicture -= $progress_width; + $this->posxtva -= $progress_width; + $this->posxup -= $progress_width; + $this->posxqty -= $progress_width; + $this->posxunit -= $progress_width; + $this->posxdiscount -= $progress_width; + $this->posxprogress -= $progress_width; + } + + // New page + $pdf->AddPage(); + if (!empty($tplidx)) { + $pdf->useTemplate($tplidx); + } + $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); + + // $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; + $qrcodestring = ''; + if (! empty($conf->global->INVOICE_ADD_ZATCA_QR_CODE)) { + $qrcodestring = $object->buildZATCAQRString(); + } elseif (! empty($conf->global->INVOICE_ADD_SWISS_QR_CODE)) { + $qrcodestring = $object->buildSwitzerlandQRString(); + } + if ($qrcodestring) { + $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_newpage += 0; + + // Incoterm + $height_incoterms = 0; + if (!empty($conf->incoterm->enabled)) { + $desc_incoterms = $object->getIncotermsForPDF(); + if ($desc_incoterms) { + $tab_top -= 2; + + $pdf->SetFont('', '', $default_font_size - 1); + $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1); + $nexY = $pdf->GetY(); + $height_incoterms = $nexY - $tab_top; + + // Rect takes a length in 3rd parameter + $pdf->SetDrawColor(192, 192, 192); + $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_incoterms + 1); + + $tab_top = $nexY + 6; + } + } + + // Display notes + $notetoshow = empty($object->note_public) ? '' : $object->note_public; + if (!empty($conf->global->MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE)) { + // Get first sale rep + if (is_object($object->thirdparty)) { + $salereparray = $object->thirdparty->getSalesRepresentatives($user); + $salerepobj = new User($this->db); + $salerepobj->fetch($salereparray[0]['id']); + if (!empty($salerepobj->signature)) { + $notetoshow = dol_concatdesc($notetoshow, $salerepobj->signature); + } + } + } + // Extrafields in note + $extranote = $this->getExtrafieldsInHtml($object, $outputlangs); + if (!empty($extranote)) { + $notetoshow = dol_concatdesc($notetoshow, $extranote); + } + if ($notetoshow) { + $tab_top -= 2; + + $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object); + complete_substitutions_array($substitutionarray, $outputlangs, $object); + + $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs); + $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow); + + $pdf->SetFont('', '', $default_font_size - 1); + $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($notetoshow), 0, 1); + $nexY = $pdf->GetY(); + $height_note = $nexY - $tab_top; + + // Rect takes a length in 3rd parameter + $pdf->SetDrawColor(192, 192, 192); + $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 1); + + $tab_top = $nexY + 6; + } + + $iniY = $tab_top + 7; + $curY = $tab_top + 7; + $nexY = $tab_top + 7; + + // Loop on each lines + for ($i = 0; $i < $nblines; $i++) { + $curY = $nexY; + $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage + $pdf->SetTextColor(0, 0, 0); + + // Define size of image if we need it + $imglinesize = array(); + if (!empty($realpatharray[$i])) { + $imglinesize = pdf_getSizeForImage($realpatharray[$i]); + } + + $pdf->setTopMargin($tab_top_newpage); + $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it. + $pageposbefore = $pdf->getPage(); + + $showpricebeforepagebreak = 1; + $posYAfterImage = 0; + $posYAfterDescription = 0; + + // We start with Photo of product line + if (isset($imglinesize['width']) && isset($imglinesize['height']) && ($curY + $imglinesize['height']) > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // If photo too high, we moved completely on new page + $pdf->AddPage('', '', true); + if (!empty($tplidx)) { + $pdf->useTemplate($tplidx); + } + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { + $this->_pagehead($pdf, $object, 0, $outputlangs); + } + $pdf->setPage($pageposbefore + 1); + + $curY = $tab_top_newpage; + + // Allows data in the first page if description is long enough to break in multiples pages + if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) { + $showpricebeforepagebreak = 1; + } else { + $showpricebeforepagebreak = 0; + } + } + + if (isset($imglinesize['width']) && isset($imglinesize['height'])) { + $curX = $this->posxpicture - 1; + $pdf->Image($realpatharray[$i], $curX + (($this->posxtva - $this->posxpicture - $imglinesize['width']) / 2), $curY, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi + // $pdf->Image does not increase value return by getY, so we save it manually + $posYAfterImage = $curY + $imglinesize['height']; + } + + // Description of product line + $curX = $this->posxdesc - 1; + + $pdf->startTransaction(); + pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxpicture - $curX - $progress_width, 3, $curX, $curY, $hideref, $hidedesc); + $pageposafter = $pdf->getPage(); + if ($pageposafter > $pageposbefore) { // There is a pagebreak + $pdf->rollbackTransaction(true); + $pageposafter = $pageposbefore; + //print $pageposafter.'-'.$pageposbefore;exit; + $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it. + pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxpicture - $curX - $progress_width, 3, $curX, $curY, $hideref, $hidedesc); + $pageposafter = $pdf->getPage(); + $posyafter = $pdf->GetY(); + //var_dump($posyafter); var_dump(($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))); exit; + if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text + if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page + $pdf->AddPage('', '', true); + if (!empty($tplidx)) { + $pdf->useTemplate($tplidx); + } + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { + $this->_pagehead($pdf, $object, 0, $outputlangs); + } + $pdf->setPage($pageposafter + 1); + } + } else { + // We found a page break + + // Allows data in the first page if description is long enough to break in multiples pages + if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) { + $showpricebeforepagebreak = 1; + } else { + $showpricebeforepagebreak = 0; + } + } + } else // No pagebreak + { + $pdf->commitTransaction(); + } + $posYAfterDescription = $pdf->GetY(); + + $nexY = $pdf->GetY(); + $pageposafter = $pdf->getPage(); + $pdf->setPage($pageposbefore); + $pdf->setTopMargin($this->marge_haute); + $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. + + // We suppose that a too long description or photo were moved completely on next page + if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) { + $pdf->setPage($pageposafter); + $curY = $tab_top_newpage; + } + + $pdf->SetFont('', '', $default_font_size - 1); // We reposition the default font + + // VAT Rate + if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) && empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) { + $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails); + $pdf->SetXY($this->posxtva - 5, $curY); + $pdf->MultiCell($this->posxup - $this->posxtva + 4, 3, $vat_rate, 0, 'R'); + } + + // Unit price before discount + $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails); + $pdf->SetXY($this->posxup, $curY); + $pdf->MultiCell($this->posxqty - $this->posxup - 0.8, 3, $up_excl_tax, 0, 'R', 0); + + // Quantity + $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails); + $pdf->SetXY($this->posxqty, $curY); + $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R'); // Enough for 6 chars + + // Unit + if (!empty($conf->global->PRODUCT_USE_UNITS)) { + $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails, $hookmanager); + $pdf->SetXY($this->posxunit, $curY); + $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 4, $unit, 0, 'L'); + } + + // Discount on line + if ($object->lines[$i]->remise_percent) { + $pdf->SetXY($this->posxdiscount - 2, $curY); + $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails); + $pdf->MultiCell($this->posxprogress - $this->posxdiscount + 2, 3, $remise_percent, 0, 'R'); + } + + // Situation progress + if ($this->situationinvoice) { + $progress = pdf_getlineprogress($object, $i, $outputlangs, $hidedetails); + $pdf->SetXY($this->posxprogress, $curY); + $pdf->MultiCell($this->postotalht - $this->posxprogress + 1, 3, $progress, 0, 'R'); + } + + // Total HT line + $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails); + $pdf->SetXY($this->postotalht, $curY); + $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalht, 3, $total_excl_tax, 0, 'R', 0); + + + $sign = 1; + if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) { + $sign = -1; + } + // Collection of totals by value of VAT in $this->tva["taux"]=total_tva + $prev_progress = $object->lines[$i]->get_prev_progress($object->id); + if ($prev_progress > 0 && !empty($object->lines[$i]->situation_percent)) { // Compute progress from previous situation + if (!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) { + $tvaligne = $sign * $object->lines[$i]->multicurrency_total_tva * ($object->lines[$i]->situation_percent - $prev_progress) / $object->lines[$i]->situation_percent; + } else { + $tvaligne = $sign * $object->lines[$i]->total_tva * ($object->lines[$i]->situation_percent - $prev_progress) / $object->lines[$i]->situation_percent; + } + } else { + if (!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) { + $tvaligne = $sign * $object->lines[$i]->multicurrency_total_tva; + } else { + $tvaligne = $sign * $object->lines[$i]->total_tva; + } + } + + $localtax1ligne = $object->lines[$i]->total_localtax1; + $localtax2ligne = $object->lines[$i]->total_localtax2; + $localtax1_rate = $object->lines[$i]->localtax1_tx; + $localtax2_rate = $object->lines[$i]->localtax2_tx; + $localtax1_type = $object->lines[$i]->localtax1_type; + $localtax2_type = $object->lines[$i]->localtax2_type; + + if ($object->remise_percent) { + $tvaligne -= ($tvaligne * $object->remise_percent) / 100; + } + if ($object->remise_percent) { + $localtax1ligne -= ($localtax1ligne * $object->remise_percent) / 100; + } + if ($object->remise_percent) { + $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; + } + + $vatrate = (string) $object->lines[$i]->tva_tx; + + // Retrieve type from database for backward compatibility with old records + if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') // if tax type not defined + && (!empty($localtax1_rate) || !empty($localtax2_rate))) { // and there is local tax + $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $object->thirdparty, $mysoc); + $localtax1_type = isset($localtaxtmp_array[0]) ? $localtaxtmp_array[0] : ''; + $localtax2_type = isset($localtaxtmp_array[2]) ? $localtaxtmp_array[2] : ''; + } + + // retrieve global local tax + if ($localtax1_type && $localtax1ligne != 0) { + $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne; + } + if ($localtax2_type && $localtax2ligne != 0) { + $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne; + } + + if (($object->lines[$i]->info_bits & 0x01) == 0x01) { + $vatrate .= '*'; + } + + // Fill $this->tva and $this->tva_array + if (!isset($this->tva[$vatrate])) { + $this->tva[$vatrate] = 0; + } + $this->tva[$vatrate] += $tvaligne; // ->tva is abandonned, 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; + } + $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; + } + + // Add line + if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblines - 1)) { + $pdf->setPage($pageposafter); + $pdf->SetLineStyle(array('dash'=>'1,1', 'color'=>array(80, 80, 80))); + //$pdf->SetDrawColor(190,190,200); + $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1); + $pdf->SetLineStyle(array('dash'=>0)); + } + + $nexY += 2; // Add space between lines + + // Detect if some page were added automatically and output _tableau for past pages + while ($pagenb < $pageposafter) { + $pdf->setPage($pagenb); + if ($pagenb == 1) { + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code); + } else { + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code); + } + $this->_pagefoot($pdf, $object, $outputlangs, 1); + $pagenb++; + $pdf->setPage($pagenb); + $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { + $this->_pagehead($pdf, $object, 0, $outputlangs); + } + if (!empty($tplidx)) { + $pdf->useTemplate($tplidx); + } + } + if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) { + if ($pagenb == 1) { + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code); + } else { + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code); + } + $this->_pagefoot($pdf, $object, $outputlangs, 1); + // New page + $pdf->AddPage(); + if (!empty($tplidx)) { + $pdf->useTemplate($tplidx); + } + $pagenb++; + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { + $this->_pagehead($pdf, $object, 0, $outputlangs); + } + } + } + + // Show square + if ($pagenb == 1) { + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0, $object->multicurrency_code); + $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; + } else { + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code); + $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; + } + dol_syslog("bottomlasttab=".$bottomlasttab." this->page_hauteur=".$this->page_hauteur." heightforinfotot=".$heightforinfotot." heightforfreetext=".$heightforfreetext." heightforfooter=".$heightforfooter); + + // Display info area + $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs, $outputlangsbis); + + // Display total area + $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs, $outputlangsbis); + + // Display Payments area + if (($deja_regle || $amount_credit_notes_included || $amount_deposits_included) && empty($conf->global->INVOICE_NO_PAYMENT_DETAILS)) { + $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs, $heightforfooter); + } + + // Pagefoot + $this->_pagefoot($pdf, $object, $outputlangs); + if (method_exists($pdf, 'AliasNbPages')) { + $pdf->AliasNbPages(); + } + + // Add page for the Swiss QR-invoice $pdf->AddPage(); $this->_pagehead($pdf, $object, 0, $outputlangs); - $this->qrinvoice($pdf, $object, $outputlangs); + $this->qrinvoice($pdf, $object, $outputlangs, $conf); - $pdf->Close(); + $pdf->Close(); - $pdf->Output($file, 'F'); + $pdf->Output($file, 'F'); - // Add pdfgeneration hook - $hookmanager->initHooks(array('pdfgeneration')); - $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs); - global $action; - $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks - if ($reshook < 0) { - $this->error = $hookmanager->error; - $this->errors = $hookmanager->errors; - } + // Add pdfgeneration hook + $hookmanager->initHooks(array('pdfgeneration')); + $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs); + global $action; + $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook < 0) { + $this->error = $hookmanager->error; + $this->errors = $hookmanager->errors; + } - if (!empty($conf->global->MAIN_UMASK)) { - @chmod($file, octdec($conf->global->MAIN_UMASK)); - } + if (!empty($conf->global->MAIN_UMASK)) { + @chmod($file, octdec($conf->global->MAIN_UMASK)); + } - $this->result = array('fullpath'=>$file); + $this->result = array('fullpath'=>$file); - return 1; // No error - } else { - $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir); - return 0; - } - } else { - $this->error = $langs->transnoentities("ErrorConstantNotDefined", "FAC_OUTPUTDIR"); - return 0; - } - } + return 1; // No error + } else { + $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir); + return 0; + } + } else { + $this->error = $langs->transnoentities("ErrorConstantNotDefined", "FAC_OUTPUTDIR"); + return 0; + } + } - /** + /** * Swiss QR invoice * * This function add the QR-invoice block add the end of the last page of the PDF invoice. * * @param object TFTP object * @param object the Dolibarr invoice object - * @param object the Dolibarr langs object + * @param object the Dolibarr langs object + * @param object the Dolibarr configuration */ - protected function qrinvoice($pdf, $object, $langs) + protected function qrinvoice($pdf, $object, $langs, $conf) { // Create a new instance of QrBill, containing default headers with fixed values $qrBill = QrBill\QrBill::create(); @@ -918,6 +919,44 @@ class pdf_swissqr extends ModelePDFFactures QrBill\DataGroup\Element\CreditorInformation::create($object->iban // This is a special QR-IBAN. Classic IBANs will not be valid here. )); + $creditorInformation = QrBill\DataGroup\Element\CreditorInformation::create($object->iban); + + if ($creditorInformation->containsQrIban()) { + + $ref = $object->ref; + + if (str_contains($ref, 'FA')) + { + // Remove FA and - from the invoice reference + $ref = str_replace('FA', '', $ref); + $ref = str_replace('-', '', $ref); + } else { + $ref = 0; + } + + // Add payment reference for QR-IBAN + // This is what you will need to identify incoming payments. + $referenceNumber = QrBill\Reference\QrPaymentReferenceGenerator::generate( + $conf->global->SI_SWISSQR_REF, // You receive this number from your bank (BESR-ID). Unless your bank is PostFinance, in that case use NULL. + $ref // A number to match the payment with your internal data, e.g. an invoice number + ); + + $qrBill->setPaymentReference( + QrBill\DataGroup\Element\PaymentReference::create( + QrBill\DataGroup\Element\PaymentReference::TYPE_QR, + $referenceNumber + ) + ); + } else { + // Add payment reference CLASSIC-IBAN + // This is what you will need to identify incoming payments. + $qrBill->setPaymentReference( + QrBill\DataGroup\Element\PaymentReference::create( + QrBill\DataGroup\Element\PaymentReference::TYPE_NON + ) + ); + } + // Add debtor information // Who has to pay the invoice? This part is optional. $qrBill->setUltimateDebtor( @@ -936,13 +975,6 @@ class pdf_swissqr extends ModelePDFFactures $object->total_ttc )); - // Add payment reference - $qrBill->setPaymentReference( - QrBill\DataGroup\Element\PaymentReference::create( - QrBill\DataGroup\Element\PaymentReference::TYPE_NON - ) - ); - // Optionally, add some human-readable information about what the bill is for. $qrBill->setAdditionalInformation( QrBill\DataGroup\Element\AdditionalInformation::create( @@ -961,1196 +993,1195 @@ class pdf_swissqr extends ModelePDFFactures exit; } - // Define the translation to use - if ($langs->shortlang == 'de' || $langs->shortlang == 'fr' || $langs->shortlang == 'it' || $langs->shortlang == 'en') - { - $output = new QrBill\PaymentPart\Output\TcPdfOutput\TcPdfOutput($qrBill, $langs->shortlang, $pdf); - } else - { - $output = new QrBill\PaymentPart\Output\TcPdfOutput\TcPdfOutput($qrBill, 'en', $pdf); - } + // Define the translation to use + if ($langs->shortlang == 'de' || $langs->shortlang == 'fr' || $langs->shortlang == 'it' || $langs->shortlang == 'en') + { + $output = new QrBill\PaymentPart\Output\TcPdfOutput\TcPdfOutput($qrBill, $langs->shortlang, $pdf); + } else + { + $output = new QrBill\PaymentPart\Output\TcPdfOutput\TcPdfOutput($qrBill, 'en', $pdf); + } $output->setPrintable(false)->getPaymentPart(); } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore + /** + * Show payments table + * + * @param TCPDF $pdf Object PDF + * @param Facture $object Object invoice + * @param int $posy Position y in PDF + * @param Translate $outputlangs Object langs for output + * @param int $heightforfooter Height for footer + * @return int <0 if KO, >0 if OK + */ + protected function _tableau_versements(&$pdf, $object, $posy, $outputlangs, $heightforfooter = 0) + { + // phpcs:enable + global $conf; - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore - /** - * Show payments table - * - * @param TCPDF $pdf Object PDF - * @param Facture $object Object invoice - * @param int $posy Position y in PDF - * @param Translate $outputlangs Object langs for output - * @param int $heightforfooter Height for footer - * @return int <0 if KO, >0 if OK - */ - protected function _tableau_versements(&$pdf, $object, $posy, $outputlangs, $heightforfooter = 0) - { - // phpcs:enable - global $conf; + $sign = 1; + if ($object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) { + $sign = -1; + } - $sign = 1; - if ($object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) { - $sign = -1; - } + $current_page = $pdf->getPage(); + $tab3_posx = 120; + $tab3_top = $posy + 8; + $tab3_width = 80; + $tab3_height = 4; + if ($this->page_largeur < 210) { // To work with US executive format + $tab3_posx -= 15; + } - $current_page = $pdf->getPage(); - $tab3_posx = 120; - $tab3_top = $posy + 8; - $tab3_width = 80; - $tab3_height = 4; - if ($this->page_largeur < 210) { // To work with US executive format - $tab3_posx -= 15; - } + $default_font_size = pdf_getPDFFontSize($outputlangs); - $default_font_size = pdf_getPDFFontSize($outputlangs); + $this->_tableau_versements_header($pdf, $object, $outputlangs, $default_font_size, $tab3_posx, $tab3_top, $tab3_width, $tab3_height); - $this->_tableau_versements_header($pdf, $object, $outputlangs, $default_font_size, $tab3_posx, $tab3_top, $tab3_width, $tab3_height); + $y = 0; - $y = 0; - - $pdf->SetFont('', '', $default_font_size - 4); + $pdf->SetFont('', '', $default_font_size - 4); - // Loop on each discount available (deposits and credit notes and excess of payment included) - $sql = "SELECT re.rowid, re.amount_ht, re.multicurrency_amount_ht, re.amount_tva, re.multicurrency_amount_tva, re.amount_ttc, re.multicurrency_amount_ttc,"; - $sql .= " re.description, re.fk_facture_source,"; - $sql .= " f.type, f.datef"; - $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re, ".MAIN_DB_PREFIX."facture as f"; - $sql .= " WHERE re.fk_facture_source = f.rowid AND re.fk_facture = ".((int) $object->id); - $resql = $this->db->query($sql); - if ($resql) { - $num = $this->db->num_rows($resql); - $i = 0; - $invoice = new Facture($this->db); - while ($i < $num) { - $y += 3; - if ($tab3_top + $y >= ($this->page_hauteur - $heightforfooter)) { - $y = 0; - $current_page++; - $pdf->AddPage('', '', true); - if (!empty($tplidx)) { - $pdf->useTemplate($tplidx); - } - if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { - $this->_pagehead($pdf, $object, 0, $outputlangs); - } - $pdf->setPage($current_page); - $this->_tableau_versements_header($pdf, $object, $outputlangs, $default_font_size, $tab3_posx, $tab3_top + $y - 3, $tab3_width, $tab3_height); - } + // Loop on each discount available (deposits and credit notes and excess of payment included) + $sql = "SELECT re.rowid, re.amount_ht, re.multicurrency_amount_ht, re.amount_tva, re.multicurrency_amount_tva, re.amount_ttc, re.multicurrency_amount_ttc,"; + $sql .= " re.description, re.fk_facture_source,"; + $sql .= " f.type, f.datef"; + $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re, ".MAIN_DB_PREFIX."facture as f"; + $sql .= " WHERE re.fk_facture_source = f.rowid AND re.fk_facture = ".((int) $object->id); + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + $invoice = new Facture($this->db); + while ($i < $num) { + $y += 3; + if ($tab3_top + $y >= ($this->page_hauteur - $heightforfooter)) { + $y = 0; + $current_page++; + $pdf->AddPage('', '', true); + if (!empty($tplidx)) { + $pdf->useTemplate($tplidx); + } + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { + $this->_pagehead($pdf, $object, 0, $outputlangs); + } + $pdf->setPage($current_page); + $this->_tableau_versements_header($pdf, $object, $outputlangs, $default_font_size, $tab3_posx, $tab3_top + $y - 3, $tab3_width, $tab3_height); + } - $obj = $this->db->fetch_object($resql); + $obj = $this->db->fetch_object($resql); - if ($obj->type == 2) { - $text = $outputlangs->transnoentities("CreditNote"); - } elseif ($obj->type == 3) { - $text = $outputlangs->transnoentities("Deposit"); - } elseif ($obj->type == 0) { - $text = $outputlangs->transnoentities("ExcessReceived"); - } else { - $text = $outputlangs->transnoentities("UnknownType"); - } + if ($obj->type == 2) { + $text = $outputlangs->transnoentities("CreditNote"); + } elseif ($obj->type == 3) { + $text = $outputlangs->transnoentities("Deposit"); + } elseif ($obj->type == 0) { + $text = $outputlangs->transnoentities("ExcessReceived"); + } else { + $text = $outputlangs->transnoentities("UnknownType"); + } - $invoice->fetch($obj->fk_facture_source); + $invoice->fetch($obj->fk_facture_source); - $pdf->SetXY($tab3_posx, $tab3_top + $y); - $pdf->MultiCell(20, 3, dol_print_date($this->db->jdate($obj->datef), 'day', false, $outputlangs, true), 0, 'L', 0); - $pdf->SetXY($tab3_posx + 21, $tab3_top + $y); - $pdf->MultiCell(20, 3, price((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? $obj->multicurrency_amount_ttc : $obj->amount_ttc, 0, $outputlangs), 0, 'L', 0); - $pdf->SetXY($tab3_posx + 40, $tab3_top + $y); - $pdf->MultiCell(20, 3, $text, 0, 'L', 0); - $pdf->SetXY($tab3_posx + 58, $tab3_top + $y); - $pdf->MultiCell(20, 3, $invoice->ref, 0, 'L', 0); + $pdf->SetXY($tab3_posx, $tab3_top + $y); + $pdf->MultiCell(20, 3, dol_print_date($this->db->jdate($obj->datef), 'day', false, $outputlangs, true), 0, 'L', 0); + $pdf->SetXY($tab3_posx + 21, $tab3_top + $y); + $pdf->MultiCell(20, 3, price((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? $obj->multicurrency_amount_ttc : $obj->amount_ttc, 0, $outputlangs), 0, 'L', 0); + $pdf->SetXY($tab3_posx + 40, $tab3_top + $y); + $pdf->MultiCell(20, 3, $text, 0, 'L', 0); + $pdf->SetXY($tab3_posx + 58, $tab3_top + $y); + $pdf->MultiCell(20, 3, $invoice->ref, 0, 'L', 0); - $pdf->line($tab3_posx, $tab3_top + $y + 3, $tab3_posx + $tab3_width, $tab3_top + $y + 3); + $pdf->line($tab3_posx, $tab3_top + $y + 3, $tab3_posx + $tab3_width, $tab3_top + $y + 3); - $i++; - } - } else { - $this->error = $this->db->lasterror(); - return -1; - } + $i++; + } + } else { + $this->error = $this->db->lasterror(); + return -1; + } - // Loop on each payment - // TODO Call getListOfPaymentsgetListOfPayments instead of hard coded sql - $sql = "SELECT p.datep as date, p.fk_paiement, p.num_paiement as num, pf.amount as amount, pf.multicurrency_amount,"; - $sql .= " cp.code"; - $sql .= " FROM ".MAIN_DB_PREFIX."paiement_facture as pf, ".MAIN_DB_PREFIX."paiement as p"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as cp ON p.fk_paiement = cp.id"; - $sql .= " WHERE pf.fk_paiement = p.rowid AND pf.fk_facture = ".((int) $object->id); - //$sql.= " WHERE pf.fk_paiement = p.rowid AND pf.fk_facture = 1"; - $sql .= " ORDER BY p.datep"; + // Loop on each payment + // TODO Call getListOfPaymentsgetListOfPayments instead of hard coded sql + $sql = "SELECT p.datep as date, p.fk_paiement, p.num_paiement as num, pf.amount as amount, pf.multicurrency_amount,"; + $sql .= " cp.code"; + $sql .= " FROM ".MAIN_DB_PREFIX."paiement_facture as pf, ".MAIN_DB_PREFIX."paiement as p"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as cp ON p.fk_paiement = cp.id"; + $sql .= " WHERE pf.fk_paiement = p.rowid AND pf.fk_facture = ".((int) $object->id); + //$sql.= " WHERE pf.fk_paiement = p.rowid AND pf.fk_facture = 1"; + $sql .= " ORDER BY p.datep"; - $resql = $this->db->query($sql); - if ($resql) { - $num = $this->db->num_rows($resql); - $i = 0; - while ($i < $num) { - $y += 3; - if ($tab3_top + $y >= ($this->page_hauteur - $heightforfooter)) { - $y = 0; - $current_page++; - $pdf->AddPage('', '', true); - if (!empty($tplidx)) { - $pdf->useTemplate($tplidx); - } - if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { - $this->_pagehead($pdf, $object, 0, $outputlangs); - } - $pdf->setPage($current_page); - $this->_tableau_versements_header($pdf, $object, $outputlangs, $default_font_size, $tab3_posx, $tab3_top + $y - 3, $tab3_width, $tab3_height); - } + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < $num) { + $y += 3; + if ($tab3_top + $y >= ($this->page_hauteur - $heightforfooter)) { + $y = 0; + $current_page++; + $pdf->AddPage('', '', true); + if (!empty($tplidx)) { + $pdf->useTemplate($tplidx); + } + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { + $this->_pagehead($pdf, $object, 0, $outputlangs); + } + $pdf->setPage($current_page); + $this->_tableau_versements_header($pdf, $object, $outputlangs, $default_font_size, $tab3_posx, $tab3_top + $y - 3, $tab3_width, $tab3_height); + } - $row = $this->db->fetch_object($resql); + $row = $this->db->fetch_object($resql); - $pdf->SetXY($tab3_posx, $tab3_top + $y); - $pdf->MultiCell(20, 3, dol_print_date($this->db->jdate($row->date), 'day', false, $outputlangs, true), 0, 'L', 0); - $pdf->SetXY($tab3_posx + 21, $tab3_top + $y); - $pdf->MultiCell(20, 3, price($sign * ((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? $row->multicurrency_amount : $row->amount), 0, $outputlangs), 0, 'L', 0); - $pdf->SetXY($tab3_posx + 40, $tab3_top + $y); - $oper = $outputlangs->transnoentitiesnoconv("PaymentTypeShort".$row->code); + $pdf->SetXY($tab3_posx, $tab3_top + $y); + $pdf->MultiCell(20, 3, dol_print_date($this->db->jdate($row->date), 'day', false, $outputlangs, true), 0, 'L', 0); + $pdf->SetXY($tab3_posx + 21, $tab3_top + $y); + $pdf->MultiCell(20, 3, price($sign * ((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? $row->multicurrency_amount : $row->amount), 0, $outputlangs), 0, 'L', 0); + $pdf->SetXY($tab3_posx + 40, $tab3_top + $y); + $oper = $outputlangs->transnoentitiesnoconv("PaymentTypeShort".$row->code); - $pdf->MultiCell(20, 3, $oper, 0, 'L', 0); - $pdf->SetXY($tab3_posx + 58, $tab3_top + $y); - $pdf->MultiCell(30, 3, $row->num, 0, 'L', 0); + $pdf->MultiCell(20, 3, $oper, 0, 'L', 0); + $pdf->SetXY($tab3_posx + 58, $tab3_top + $y); + $pdf->MultiCell(30, 3, $row->num, 0, 'L', 0); - $pdf->line($tab3_posx, $tab3_top + $y + 3, $tab3_posx + $tab3_width, $tab3_top + $y + 3); + $pdf->line($tab3_posx, $tab3_top + $y + 3, $tab3_posx + $tab3_width, $tab3_top + $y + 3); - $i++; - } + $i++; + } - return $tab3_top + $y + 3; - } else { - $this->error = $this->db->lasterror(); - return -1; - } - } + return $tab3_top + $y + 3; + } else { + $this->error = $this->db->lasterror(); + return -1; + } + } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore - /** - * Function _tableau_versements_header - * - * @param TCPDF $pdf Object PDF - * @param Facture $object Object invoice - * @param Translate $outputlangs Object langs for output - * @param int $default_font_size Font size - * @param int $tab3_posx pos x - * @param int $tab3_top pos y - * @param int $tab3_width width - * @param int $tab3_height height - * @return void - */ - protected function _tableau_versements_header($pdf, $object, $outputlangs, $default_font_size, $tab3_posx, $tab3_top, $tab3_width, $tab3_height) - { - // phpcs:enable - $title = $outputlangs->transnoentities("PaymentsAlreadyDone"); - if ($object->type == 2) { - $title = $outputlangs->transnoentities("PaymentsBackAlreadyDone"); - } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore + /** + * Function _tableau_versements_header + * + * @param TCPDF $pdf Object PDF + * @param Facture $object Object invoice + * @param Translate $outputlangs Object langs for output + * @param int $default_font_size Font size + * @param int $tab3_posx pos x + * @param int $tab3_top pos y + * @param int $tab3_width width + * @param int $tab3_height height + * @return void + */ + protected function _tableau_versements_header($pdf, $object, $outputlangs, $default_font_size, $tab3_posx, $tab3_top, $tab3_width, $tab3_height) + { + // phpcs:enable + $title = $outputlangs->transnoentities("PaymentsAlreadyDone"); + if ($object->type == 2) { + $title = $outputlangs->transnoentities("PaymentsBackAlreadyDone"); + } - $pdf->SetFont('', '', $default_font_size - 3); - $pdf->SetXY($tab3_posx, $tab3_top - 4); - $pdf->MultiCell(60, 3, $title, 0, 'L', 0); + $pdf->SetFont('', '', $default_font_size - 3); + $pdf->SetXY($tab3_posx, $tab3_top - 4); + $pdf->MultiCell(60, 3, $title, 0, 'L', 0); - $pdf->line($tab3_posx, $tab3_top, $tab3_posx + $tab3_width, $tab3_top); + $pdf->line($tab3_posx, $tab3_top, $tab3_posx + $tab3_width, $tab3_top); - $pdf->SetFont('', '', $default_font_size - 4); - $pdf->SetXY($tab3_posx, $tab3_top); - $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Payment"), 0, 'L', 0); - $pdf->SetXY($tab3_posx + 21, $tab3_top); - $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Amount"), 0, 'L', 0); - $pdf->SetXY($tab3_posx + 40, $tab3_top); - $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Type"), 0, 'L', 0); - $pdf->SetXY($tab3_posx + 58, $tab3_top); - $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Num"), 0, 'L', 0); + $pdf->SetFont('', '', $default_font_size - 4); + $pdf->SetXY($tab3_posx, $tab3_top); + $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Payment"), 0, 'L', 0); + $pdf->SetXY($tab3_posx + 21, $tab3_top); + $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Amount"), 0, 'L', 0); + $pdf->SetXY($tab3_posx + 40, $tab3_top); + $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Type"), 0, 'L', 0); + $pdf->SetXY($tab3_posx + 58, $tab3_top); + $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Num"), 0, 'L', 0); - $pdf->line($tab3_posx, $tab3_top - 1 + $tab3_height, $tab3_posx + $tab3_width, $tab3_top - 1 + $tab3_height); - } + $pdf->line($tab3_posx, $tab3_top - 1 + $tab3_height, $tab3_posx + $tab3_width, $tab3_top - 1 + $tab3_height); + } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore - /** - * Show miscellaneous information (payment mode, payment term, ...) - * - * @param TCPDF $pdf Object PDF - * @param Facture $object Object to show - * @param int $posy Y - * @param Translate $outputlangs Langs object - * @param Translate $outputlangsbis Object lang for output bis - * @return int Pos y - */ - protected function _tableau_info(&$pdf, $object, $posy, $outputlangs, $outputlangsbis) - { - // phpcs:enable - global $conf, $mysoc; + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore + /** + * Show miscellaneous information (payment mode, payment term, ...) + * + * @param TCPDF $pdf Object PDF + * @param Facture $object Object to show + * @param int $posy Y + * @param Translate $outputlangs Langs object + * @param Translate $outputlangsbis Object lang for output bis + * @return int Pos y + */ + protected function _tableau_info(&$pdf, $object, $posy, $outputlangs, $outputlangsbis) + { + // phpcs:enable + global $conf, $mysoc; - $default_font_size = pdf_getPDFFontSize($outputlangs); + $default_font_size = pdf_getPDFFontSize($outputlangs); - $pdf->SetFont('', '', $default_font_size - 1); + $pdf->SetFont('', '', $default_font_size - 1); - // 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); - $pdf->SetXY($this->marge_gauche, $posy); - if ($mysoc->forme_juridique_code == 92) { - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoiceAsso"), 0, 'L', 0); - } else { - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', 0); - } + // 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); + $pdf->SetXY($this->marge_gauche, $posy); + if ($mysoc->forme_juridique_code == 92) { + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoiceAsso"), 0, 'L', 0); + } else { + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', 0); + } - $posy = $pdf->GetY() + 4; - } + $posy = $pdf->GetY() + 4; + } - $posxval = 52; + $posxval = 52; - // Show payments conditions - if ($object->type != 2 && ($object->cond_reglement_code || $object->cond_reglement)) { - $pdf->SetFont('', 'B', $default_font_size - 2); - $pdf->SetXY($this->marge_gauche, $posy); - $titre = $outputlangs->transnoentities("PaymentConditions").':'; - $pdf->MultiCell(43, 4, $titre, 0, 'L'); + // Show payments conditions + if ($object->type != 2 && ($object->cond_reglement_code || $object->cond_reglement)) { + $pdf->SetFont('', 'B', $default_font_size - 2); + $pdf->SetXY($this->marge_gauche, $posy); + $titre = $outputlangs->transnoentities("PaymentConditions").':'; + $pdf->MultiCell(43, 4, $titre, 0, 'L'); - $pdf->SetFont('', '', $default_font_size - 2); - $pdf->SetXY($posxval, $posy); - $lib_condition_paiement = $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) != ('PaymentCondition'.$object->cond_reglement_code) ? $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) : $outputlangs->convToOutputCharset($object->cond_reglement_doc ? $object->cond_reglement_doc : $object->cond_reglement_label); - $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement); - $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L'); + $pdf->SetFont('', '', $default_font_size - 2); + $pdf->SetXY($posxval, $posy); + $lib_condition_paiement = $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) != ('PaymentCondition'.$object->cond_reglement_code) ? $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) : $outputlangs->convToOutputCharset($object->cond_reglement_doc ? $object->cond_reglement_doc : $object->cond_reglement_label); + $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement); + $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L'); - $posy = $pdf->GetY() + 3; // We need spaces for 2 lines payment conditions - } + $posy = $pdf->GetY() + 3; // We need spaces for 2 lines payment conditions + } - if ($object->type != 2) { - // Check a payment mode is defined - if (empty($object->mode_reglement_code) - && empty($conf->global->FACTURE_CHQ_NUMBER) - && empty($conf->global->FACTURE_RIB_NUMBER)) { - $this->error = $outputlangs->transnoentities("ErrorNoPaiementModeConfigured"); - } elseif (($object->mode_reglement_code == 'CHQ' && empty($conf->global->FACTURE_CHQ_NUMBER) && empty($object->fk_account) && empty($object->fk_bank)) - || ($object->mode_reglement_code == 'VIR' && empty($conf->global->FACTURE_RIB_NUMBER) && empty($object->fk_account) && empty($object->fk_bank))) { - // Avoid having any valid PDF with setup that is not complete - $outputlangs->load("errors"); + if ($object->type != 2) { + // Check a payment mode is defined + if (empty($object->mode_reglement_code) + && empty($conf->global->FACTURE_CHQ_NUMBER) + && empty($conf->global->FACTURE_RIB_NUMBER)) { + $this->error = $outputlangs->transnoentities("ErrorNoPaiementModeConfigured"); + } elseif (($object->mode_reglement_code == 'CHQ' && empty($conf->global->FACTURE_CHQ_NUMBER) && empty($object->fk_account) && empty($object->fk_bank)) + || ($object->mode_reglement_code == 'VIR' && empty($conf->global->FACTURE_RIB_NUMBER) && empty($object->fk_account) && empty($object->fk_bank))) { + // Avoid having any valid PDF with setup that is not complete + $outputlangs->load("errors"); - $pdf->SetXY($this->marge_gauche, $posy); - $pdf->SetTextColor(200, 0, 0); - $pdf->SetFont('', 'B', $default_font_size - 2); - $this->error = $outputlangs->transnoentities("ErrorPaymentModeDefinedToWithoutSetup", $object->mode_reglement_code); - $pdf->MultiCell(80, 3, $this->error, 0, 'L', 0); - $pdf->SetTextColor(0, 0, 0); + $pdf->SetXY($this->marge_gauche, $posy); + $pdf->SetTextColor(200, 0, 0); + $pdf->SetFont('', 'B', $default_font_size - 2); + $this->error = $outputlangs->transnoentities("ErrorPaymentModeDefinedToWithoutSetup", $object->mode_reglement_code); + $pdf->MultiCell(80, 3, $this->error, 0, 'L', 0); + $pdf->SetTextColor(0, 0, 0); - $posy = $pdf->GetY() + 1; - } + $posy = $pdf->GetY() + 1; + } - // Show payment mode - if (!empty($object->mode_reglement_code) - && $object->mode_reglement_code != 'CHQ' - && $object->mode_reglement_code != 'VIR') { - $pdf->SetFont('', 'B', $default_font_size - 2); - $pdf->SetXY($this->marge_gauche, $posy); - $titre = $outputlangs->transnoentities("PaymentMode").':'; - $pdf->MultiCell(80, 5, $titre, 0, 'L'); + // Show payment mode + if (!empty($object->mode_reglement_code) + && $object->mode_reglement_code != 'CHQ' + && $object->mode_reglement_code != 'VIR') { + $pdf->SetFont('', 'B', $default_font_size - 2); + $pdf->SetXY($this->marge_gauche, $posy); + $titre = $outputlangs->transnoentities("PaymentMode").':'; + $pdf->MultiCell(80, 5, $titre, 0, 'L'); - $pdf->SetFont('', '', $default_font_size - 2); - $pdf->SetXY($posxval, $posy); - $lib_mode_reg = $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) != ('PaymentType'.$object->mode_reglement_code) ? $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) : $outputlangs->convToOutputCharset($object->mode_reglement); - $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L'); + $pdf->SetFont('', '', $default_font_size - 2); + $pdf->SetXY($posxval, $posy); + $lib_mode_reg = $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) != ('PaymentType'.$object->mode_reglement_code) ? $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) : $outputlangs->convToOutputCharset($object->mode_reglement); + $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L'); - $posy = $pdf->GetY(); - } + $posy = $pdf->GetY(); + } - // Show online payment link - if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CB' || $object->mode_reglement_code == 'VAD') { - $useonlinepayment = 0; - if (!empty($conf->global->PDF_SHOW_LINK_TO_ONLINE_PAYMENT)) { - if (!empty($conf->paypal->enabled)) { - $useonlinepayment++; - } - if (!empty($conf->stripe->enabled)) { - $useonlinepayment++; - } - if (!empty($conf->paybox->enabled)) { - $useonlinepayment++; - } - } + // Show online payment link + if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CB' || $object->mode_reglement_code == 'VAD') { + $useonlinepayment = 0; + if (!empty($conf->global->PDF_SHOW_LINK_TO_ONLINE_PAYMENT)) { + if (!empty($conf->paypal->enabled)) { + $useonlinepayment++; + } + if (!empty($conf->stripe->enabled)) { + $useonlinepayment++; + } + if (!empty($conf->paybox->enabled)) { + $useonlinepayment++; + } + } - if ($object->statut != Facture::STATUS_DRAFT && $useonlinepayment) { - require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; - global $langs; + if ($object->statut != Facture::STATUS_DRAFT && $useonlinepayment) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; + global $langs; - $langs->loadLangs(array('payment', 'paybox', 'stripe')); - $servicename = $langs->transnoentities('Online'); - $paiement_url = getOnlinePaymentUrl('', 'invoice', $object->ref, '', '', ''); - $linktopay = $langs->trans("ToOfferALinkForOnlinePayment", $servicename).' '.$outputlangs->transnoentities("ClickHere").''; + $langs->loadLangs(array('payment', 'paybox', 'stripe')); + $servicename = $langs->transnoentities('Online'); + $paiement_url = getOnlinePaymentUrl('', 'invoice', $object->ref, '', '', ''); + $linktopay = $langs->trans("ToOfferALinkForOnlinePayment", $servicename).' '.$outputlangs->transnoentities("ClickHere").''; - $pdf->SetXY($this->marge_gauche, $posy); - $pdf->writeHTMLCell(80, 5, '', '', dol_htmlentitiesbr($linktopay), 0, 1); + $pdf->SetXY($this->marge_gauche, $posy); + $pdf->writeHTMLCell(80, 5, '', '', dol_htmlentitiesbr($linktopay), 0, 1); - $posy = $pdf->GetY() + 1; - } - } + $posy = $pdf->GetY() + 1; + } + } - // Show payment mode CHQ - if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') { - // If payment mode unregulated or payment mode forced to CHQ - if (!empty($conf->global->FACTURE_CHQ_NUMBER)) { - $diffsizetitle = (empty($conf->global->PDF_DIFFSIZE_TITLE) ? 3 : $conf->global->PDF_DIFFSIZE_TITLE); + // Show payment mode CHQ + if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') { + // If payment mode unregulated or payment mode forced to CHQ + if (!empty($conf->global->FACTURE_CHQ_NUMBER)) { + $diffsizetitle = (empty($conf->global->PDF_DIFFSIZE_TITLE) ? 3 : $conf->global->PDF_DIFFSIZE_TITLE); - if ($conf->global->FACTURE_CHQ_NUMBER > 0) { - $account = new Account($this->db); - $account->fetch($conf->global->FACTURE_CHQ_NUMBER); + if ($conf->global->FACTURE_CHQ_NUMBER > 0) { + $account = new Account($this->db); + $account->fetch($conf->global->FACTURE_CHQ_NUMBER); - $pdf->SetXY($this->marge_gauche, $posy); - $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $account->proprio), 0, 'L', 0); - $posy = $pdf->GetY() + 1; + $pdf->SetXY($this->marge_gauche, $posy); + $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $account->proprio), 0, 'L', 0); + $posy = $pdf->GetY() + 1; - if (empty($conf->global->MAIN_PDF_HIDE_CHQ_ADDRESS)) { - $pdf->SetXY($this->marge_gauche, $posy); - $pdf->SetFont('', '', $default_font_size - $diffsizetitle); - $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($account->owner_address), 0, 'L', 0); - $posy = $pdf->GetY() + 2; - } - } - if ($conf->global->FACTURE_CHQ_NUMBER == -1) { - $pdf->SetXY($this->marge_gauche, $posy); - $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $this->emetteur->name), 0, 'L', 0); - $posy = $pdf->GetY() + 1; + if (empty($conf->global->MAIN_PDF_HIDE_CHQ_ADDRESS)) { + $pdf->SetXY($this->marge_gauche, $posy); + $pdf->SetFont('', '', $default_font_size - $diffsizetitle); + $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($account->owner_address), 0, 'L', 0); + $posy = $pdf->GetY() + 2; + } + } + if ($conf->global->FACTURE_CHQ_NUMBER == -1) { + $pdf->SetXY($this->marge_gauche, $posy); + $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $this->emetteur->name), 0, 'L', 0); + $posy = $pdf->GetY() + 1; - if (empty($conf->global->MAIN_PDF_HIDE_CHQ_ADDRESS)) { - $pdf->SetXY($this->marge_gauche, $posy); - $pdf->SetFont('', '', $default_font_size - $diffsizetitle); - $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($this->emetteur->getFullAddress()), 0, 'L', 0); - $posy = $pdf->GetY() + 2; - } - } - } - } + if (empty($conf->global->MAIN_PDF_HIDE_CHQ_ADDRESS)) { + $pdf->SetXY($this->marge_gauche, $posy); + $pdf->SetFont('', '', $default_font_size - $diffsizetitle); + $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($this->emetteur->getFullAddress()), 0, 'L', 0); + $posy = $pdf->GetY() + 2; + } + } + } + } - // If payment mode not forced or forced to VIR, show payment with BAN - if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR') { - if ($object->fk_account > 0 || $object->fk_bank > 0 || !empty($conf->global->FACTURE_RIB_NUMBER)) { - $bankid = ($object->fk_account <= 0 ? $conf->global->FACTURE_RIB_NUMBER : $object->fk_account); - if ($object->fk_bank > 0) { - $bankid = $object->fk_bank; // For backward compatibility when object->fk_account is forced with object->fk_bank - } - $account = new Account($this->db); - $account->fetch($bankid); + // If payment mode not forced or forced to VIR, show payment with BAN + if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR') { + if ($object->fk_account > 0 || $object->fk_bank > 0 || !empty($conf->global->FACTURE_RIB_NUMBER)) { + $bankid = ($object->fk_account <= 0 ? $conf->global->FACTURE_RIB_NUMBER : $object->fk_account); + if ($object->fk_bank > 0) { + $bankid = $object->fk_bank; // For backward compatibility when object->fk_account is forced with object->fk_bank + } + $account = new Account($this->db); + $account->fetch($bankid); - // Copy the IBAN outside the tableau_info function + // Copy the IBAN outside the tableau_info function $object->iban = $account->iban; - $curx = $this->marge_gauche; - $cury = $posy; - - $posy = pdf_bank($pdf, $outputlangs, $curx, $cury, $account, 0, $default_font_size); - - $posy += 2; - } - } - } - - return $posy; - } - - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore - /** - * Show total to pay - * - * @param TCPDF $pdf Object PDF - * @param Facture $object Object invoice - * @param int $deja_regle Amount already paid (in the currency of invoice) - * @param int $posy Position depart - * @param Translate $outputlangs Objet langs - * @param Translate $outputlangsbis Object lang for output bis - * @return int Position pour suite - */ - protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis) - { - // phpcs:enable - global $conf, $mysoc, $hookmanager; - - $sign = 1; - if ($object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) { - $sign = -1; - } - - $default_font_size = pdf_getPDFFontSize($outputlangs); - - $outputlangsbis = null; - if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && $outputlangs->defaultlang != $conf->global->PDF_USE_ALSO_LANGUAGE_CODE) { - $outputlangsbis = new Translate('', $conf); - $outputlangsbis->setDefaultLang($conf->global->PDF_USE_ALSO_LANGUAGE_CODE); - $outputlangsbis->loadLangs(array("main", "dict", "companies", "bills", "products", "propal")); - $default_font_size--; - } - - $tab2_top = $posy; - $tab2_hl = 4; - $pdf->SetFont('', '', $default_font_size - 1); - - // Total table - $col1x = 120; - $col2x = 170; - if ($this->page_largeur < 210) { // To work with US executive format - $col1x -= 15; - $col2x -= 10; - } - $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x); - - $useborder = 0; - $index = 0; - - // Total HT - $pdf->SetFillColor(255, 255, 255); - $pdf->SetXY($col1x, $tab2_top + 0); - $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities(empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) ? "TotalHT" : "Total").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities(empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) ? "TotalHT" : "Total") : ''), 0, 'L', 1); - - $total_ht = ((!empty($conf->multicurrency->enabled) && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht); - $pdf->SetXY($col2x, $tab2_top + 0); - $pdf->MultiCell($largcol2, $tab2_hl, price($sign * ($total_ht + (!empty($object->remise) ? $object->remise : 0)), 0, $outputlangs), 0, 'R', 1); - - // Show VAT by rates and total - $pdf->SetFillColor(248, 248, 248); - - $total_ttc = (!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc; - - $this->atleastoneratenotnull = 0; - if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) { - $tvaisnull = ((!empty($this->tva) && count($this->tva) == 1 && isset($this->tva['0.000']) && is_float($this->tva['0.000'])) ? true : false); - if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL) && $tvaisnull) { - // Nothing to do - } else { - // FIXME amount of vat not supported with multicurrency - - //Local tax 1 before VAT - //if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') - //{ - foreach ($this->localtax1 as $localtax_type => $localtax_rate) { - if (in_array((string) $localtax_type, array('1', '3', '5'))) { - continue; - } - - foreach ($localtax_rate 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("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : ''); - $totalvat .= ' '; - $totalvat .= vatrate(abs($tvakey), 1).$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($tvaval, 0, $outputlangs), 0, 'R', 1); - } - } - } - //} - //Local tax 2 before VAT - //if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') - //{ - foreach ($this->localtax2 as $localtax_type => $localtax_rate) { - if (in_array((string) $localtax_type, array('1', '3', '5'))) { - continue; - } - - foreach ($localtax_rate 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("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : ''); - $totalvat .= ' '; - $totalvat .= vatrate(abs($tvakey), 1).$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($tvaval, 0, $outputlangs), 0, 'R', 1); - } - } - } - - //} - - // 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); - - $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; - } 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); - } - } - - //Local tax 1 after VAT - //if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') - //{ - foreach ($this->localtax1 as $localtax_type => $localtax_rate) { - if (in_array((string) $localtax_type, array('2', '4', '6'))) { - continue; - } - - foreach ($localtax_rate 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("TotalLT1", $mysoc->country_code).' '; - $totalvat .= vatrate(abs($tvakey), 1).$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($tvaval, 0, $outputlangs), 0, 'R', 1); - } - } - } - //} - //Local tax 2 after VAT - //if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') - //{ - foreach ($this->localtax2 as $localtax_type => $localtax_rate) { - if (in_array((string) $localtax_type, array('2', '4', '6'))) { - continue; - } - - foreach ($localtax_rate as $tvakey => $tvaval) { - //$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("TotalLT2", $mysoc->country_code).' '; - - $totalvat .= vatrate(abs($tvakey), 1).$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($tvaval, 0, $outputlangs), 0, 'R', 1); - } - } - //} - - // Revenue stamp - if (price2num($object->revenuestamp) != 0) { - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RevenueStamp"), $useborder, 'L', 1); - - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $object->revenuestamp), $useborder, 'R', 1); - } - - // Total TTC - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->SetTextColor(0, 0, 60); - $pdf->SetFillColor(224, 224, 224); - $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC"), $useborder, 'L', 1); - - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $total_ttc, 0, $outputlangs), $useborder, 'R', 1); - - // Retained warranty - if ($object->displayRetainedWarranty()) { - $pdf->SetTextColor(40, 40, 40); - $pdf->SetFillColor(255, 255, 255); - - $retainedWarranty = $object->getRetainedWarrantyAmount(); - $billedWithRetainedWarranty = $object->total_ttc - $retainedWarranty; - - // Billed - retained warranty - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("ToPayOn", dol_print_date($object->date_lim_reglement, 'day')), $useborder, 'L', 1); - - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($billedWithRetainedWarranty), $useborder, 'R', 1); - - // retained warranty - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - - $retainedWarrantyToPayOn = $outputlangs->transnoentities("RetainedWarranty").' ('.$object->retained_warranty.'%)'; - $retainedWarrantyToPayOn .= !empty($object->retained_warranty_date_limit) ? ' '.$outputlangs->transnoentities("toPayOn", dol_print_date($object->retained_warranty_date_limit, 'day')) : ''; - - $pdf->MultiCell($col2x - $col1x, $tab2_hl, $retainedWarrantyToPayOn, $useborder, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($retainedWarranty), $useborder, 'R', 1); - } - } - } - - $pdf->SetTextColor(0, 0, 0); - $creditnoteamount = $object->getSumCreditNotesUsed((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? 1 : 0); // Warning, this also include excess received - $depositsamount = $object->getSumDepositsUsed((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? 1 : 0); - //print "x".$creditnoteamount."-".$depositsamount;exit; - $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT'); - if (!empty($object->paye)) { - $resteapayer = 0; - } - - if (($deja_regle > 0 || $creditnoteamount > 0 || $depositsamount > 0) && empty($conf->global->INVOICE_NO_PAYMENT_DETAILS)) { - // Already paid + Deposits - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("Paid"), 0, 'L', 0); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle + $depositsamount, 0, $outputlangs), 0, 'R', 0); - - // Credit note - if ($creditnoteamount) { - $labeltouse = ($outputlangs->transnoentities("CreditNotesOrExcessReceived") != "CreditNotesOrExcessReceived") ? $outputlangs->transnoentities("CreditNotesOrExcessReceived") : $outputlangs->transnoentities("CreditNotes"); - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x - $col1x, $tab2_hl, $labeltouse, 0, 'L', 0); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($creditnoteamount, 0, $outputlangs), 0, 'R', 0); - } - - // Escompte - if ($object->close_code == Facture::CLOSECODE_DISCOUNTVAT) { - $index++; - $pdf->SetFillColor(255, 255, 255); - - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("EscompteOfferedShort"), $useborder, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 0, $outputlangs), $useborder, 'R', 1); - - $resteapayer = 0; - } - - $index++; - $pdf->SetTextColor(0, 0, 60); - $pdf->SetFillColor(224, 224, 224); - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay"), $useborder, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer, 0, $outputlangs), $useborder, 'R', 1); - - $pdf->SetFont('', '', $default_font_size - 1); - $pdf->SetTextColor(0, 0, 0); - } - - $index++; - return ($tab2_top + ($tab2_hl * $index)); - } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore - /** - * Show table for lines - * - * @param TCPDF $pdf Object PDF - * @param string $tab_top Top position of table - * @param string $tab_height Height of table (rectangle) - * @param int $nexY Y (not used) - * @param Translate $outputlangs Langs object - * @param int $hidetop 1=Hide top bar of array and title, 0=Hide nothing, -1=Hide only title - * @param int $hidebottom Hide bottom bar of array - * @param string $currency Currency code - * @return void - */ - protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '') - { - global $conf; - - // Force to disable hidetop and hidebottom - $hidebottom = 0; - if ($hidetop) { - $hidetop = -1; - } - - $currency = !empty($currency) ? $currency : $conf->currency; - $default_font_size = pdf_getPDFFontSize($outputlangs); - - // Amount in (at tab_top - 1) - $pdf->SetTextColor(0, 0, 0); - $pdf->SetFont('', '', $default_font_size - 2); - - if (empty($hidetop)) { - $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency)); - $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4); - $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre); - - //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230'; - if (!empty($conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)) { - $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, 5, 'F', null, explode(',', $conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)); - } - } - - $pdf->SetDrawColor(128, 128, 128); - $pdf->SetFont('', '', $default_font_size - 1); - - // Output Rect - $this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect takes a length in 3rd parameter and 4th parameter - - if (empty($hidetop)) { - $pdf->line($this->marge_gauche, $tab_top + 5, $this->page_largeur - $this->marge_droite, $tab_top + 5); // line takes a position y in 2nd parameter and 4th parameter - - $pdf->SetXY($this->posxdesc - 1, $tab_top + 1); - $pdf->MultiCell(108, 2, $outputlangs->transnoentities("Designation"), '', 'L'); - } - - if (!empty($conf->global->MAIN_GENERATE_INVOICES_WITH_PICTURE)) { - $pdf->line($this->posxpicture - 1, $tab_top, $this->posxpicture - 1, $tab_top + $tab_height); - if (empty($hidetop)) { - //$pdf->SetXY($this->posxpicture-1, $tab_top+1); - //$pdf->MultiCell($this->posxtva-$this->posxpicture-1,2, $outputlangs->transnoentities("Photo"),'','C'); - } - } - - if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) && empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) { - $pdf->line($this->posxtva - 1, $tab_top, $this->posxtva - 1, $tab_top + $tab_height); - if (empty($hidetop)) { - $pdf->SetXY($this->posxtva - 3, $tab_top + 1); - $pdf->MultiCell($this->posxup - $this->posxtva + 3, 2, $outputlangs->transnoentities("VAT"), '', 'C'); - } - } - - $pdf->line($this->posxup - 1, $tab_top, $this->posxup - 1, $tab_top + $tab_height); - if (empty($hidetop)) { - $pdf->SetXY($this->posxup - 1, $tab_top + 1); - $pdf->MultiCell($this->posxqty - $this->posxup - 1, 2, $outputlangs->transnoentities("PriceUHT"), '', 'C'); - } - - $pdf->line($this->posxqty - 1, $tab_top, $this->posxqty - 1, $tab_top + $tab_height); - if (empty($hidetop)) { - $pdf->SetXY($this->posxqty - 1, $tab_top + 1); - $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C'); - } - - if (!empty($conf->global->PRODUCT_USE_UNITS)) { - $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height); - if (empty($hidetop)) { - $pdf->SetXY($this->posxunit - 1, $tab_top + 1); - $pdf->MultiCell($this->posxdiscount - $this->posxunit - 1, 2, $outputlangs->transnoentities("Unit"), '', 'C'); - } - } - - if ($this->atleastonediscount) { - $pdf->line($this->posxdiscount - 1, $tab_top, $this->posxdiscount - 1, $tab_top + $tab_height); - if (empty($hidetop)) { - $pdf->SetXY($this->posxdiscount - 1, $tab_top + 1); - $pdf->MultiCell($this->posxprogress - $this->posxdiscount + 1, 2, $outputlangs->transnoentities("ReductionShort"), '', 'C'); - } - } - - if ($this->situationinvoice) { - $pdf->line($this->posxprogress - 1, $tab_top, $this->posxprogress - 1, $tab_top + $tab_height); - if (empty($hidetop)) { - $pdf->SetXY($this->posxprogress, $tab_top + 1); - $pdf->MultiCell($this->postotalht - $this->posxprogress, 2, $outputlangs->transnoentities("ProgressShort"), '', 'C'); - } - } - - $pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height); - if (empty($hidetop)) { - $pdf->SetXY($this->postotalht - 1, $tab_top + 1); - $pdf->MultiCell(30, 2, $outputlangs->transnoentities("TotalHT"), '', 'C'); - } - } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore - /** - * Show top header of page. - * - * @param TCPDF $pdf Object PDF - * @param Facture $object Object to show - * @param int $showaddress 0=no, 1=yes - * @param Translate $outputlangs Object lang for output - * @param Translate $outputlangsbis Object lang for output bis - * @return int top shift of linked object lines - */ - protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null) - { - global $conf, $langs; - - $ltrdirection = 'L'; - if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R'; - - // Load traductions files required by page - $outputlangs->loadLangs(array("main", "bills", "propal", "companies")); - - $default_font_size = pdf_getPDFFontSize($outputlangs); - - pdf_pagehead($pdf, $outputlangs, $this->page_hauteur); - - $pdf->SetTextColor(0, 0, 60); - $pdf->SetFont('', 'B', $default_font_size + 3); - - $w = 110; - - $posy = $this->marge_haute; - $posx = $this->page_largeur - $this->marge_droite - $w; - - $pdf->SetXY($this->marge_gauche, $posy); - - // Logo - if (empty($conf->global->PDF_DISABLE_MYCOMPANY_LOGO)) { - if ($this->emetteur->logo) { - $logodir = $conf->mycompany->dir_output; - if (!empty($conf->mycompany->multidir_output[$object->entity])) { - $logodir = $conf->mycompany->multidir_output[$object->entity]; - } - if (empty($conf->global->MAIN_PDF_USE_LARGE_LOGO)) { - $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small; - } else { - $logo = $logodir.'/logos/'.$this->emetteur->logo; - } - if (is_readable($logo)) { - $height = pdf_getHeightForLogo($logo); - $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto) - } else { - $pdf->SetTextColor(200, 0, 0); - $pdf->SetFont('', 'B', $default_font_size - 2); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L'); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L'); - } - } else { - $text = $this->emetteur->name; - $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection); - } - } - - $pdf->SetFont('', 'B', $default_font_size + 3); - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - $title = $outputlangs->transnoentities("PdfInvoiceTitle"); - if ($object->type == 1) { - $title = $outputlangs->transnoentities("InvoiceReplacement"); - } - if ($object->type == 2) { - $title = $outputlangs->transnoentities("InvoiceAvoir"); - } - if ($object->type == 3) { - $title = $outputlangs->transnoentities("InvoiceDeposit"); - } - if ($object->type == 4) { - $title = $outputlangs->transnoentities("InvoiceProForma"); - } - if ($this->situationinvoice) { - $title = $outputlangs->transnoentities("PDFInvoiceSituation"); - } - if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) { - $title .= ' - '; - if ($object->type == 0) { - if ($this->situationinvoice) { - $title .= $outputlangsbis->transnoentities("PDFInvoiceSituation"); - } - $title .= $outputlangsbis->transnoentities("PdfInvoiceTitle"); - } elseif ($object->type == 1) { - $title .= $outputlangsbis->transnoentities("InvoiceReplacement"); - } elseif ($object->type == 2) { - $title .= $outputlangsbis->transnoentities("InvoiceAvoir"); - } elseif ($object->type == 3) { - $title .= $outputlangsbis->transnoentities("InvoiceDeposit"); - } elseif ($object->type == 4) { - $title .= $outputlangsbis->transnoentities("InvoiceProForma"); - } - } - $title .= ' '.$outputlangs->convToOutputCharset($object->ref); - if ($object->statut == $object::STATUS_DRAFT) { - $pdf->SetTextColor(128, 0, 0); - $title .= ' - '.$outputlangs->transnoentities("NotValidated"); - } - - $pdf->MultiCell($w, 3, $title, '', 'R'); - - $pdf->SetFont('', 'B', $default_font_size); - - /* - $posy += 5; - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - $textref = $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref); - if ($object->statut == $object::STATUS_DRAFT) { - $pdf->SetTextColor(128, 0, 0); - $textref .= ' - '.$outputlangs->transnoentities("NotValidated"); - } - $pdf->MultiCell($w, 4, $textref, '', 'R');*/ - - $posy += 3; - $pdf->SetFont('', '', $default_font_size - 2); - - if ($object->ref_client) { - $posy += 4; - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".$outputlangs->convToOutputCharset($object->ref_client), '', 'R'); - } - - if (!empty($conf->global->PDF_SHOW_PROJECT_TITLE)) { - $object->fetch_projet(); - if (!empty($object->project->ref)) { - $posy += 3; - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->title) ? '' : $object->project->title), '', 'R'); - } - } - - if (!empty($conf->global->PDF_SHOW_PROJECT)) { - $object->fetch_projet(); - if (!empty($object->project->ref)) { - $outputlangs->load("projects"); - $posy += 3; - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefProject")." : ".(empty($object->project->ref) ? '' : $object->project->ref), '', 'R'); - } - } - - $objectidnext = $object->getIdReplacingInvoice('validated'); - if ($object->type == 0 && $objectidnext) { - $objectreplacing = new Facture($this->db); - $objectreplacing->fetch($objectidnext); - - $posy += 3; - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ReplacementByInvoice").' : '.$outputlangs->convToOutputCharset($objectreplacing->ref), '', 'R'); - } - if ($object->type == 1) { - $objectreplaced = new Facture($this->db); - $objectreplaced->fetch($object->fk_facture_source); - - $posy += 4; - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ReplacementInvoice").' : '.$outputlangs->convToOutputCharset($objectreplaced->ref), '', 'R'); - } - if ($object->type == 2 && !empty($object->fk_facture_source)) { - $objectreplaced = new Facture($this->db); - $objectreplaced->fetch($object->fk_facture_source); - - $posy += 3; - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CorrectionInvoice").' : '.$outputlangs->convToOutputCharset($objectreplaced->ref), '', 'R'); - } - - $posy += 4; - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - $title = $outputlangs->transnoentities("DateInvoice"); - if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) { - $title .= ' - '.$outputlangsbis->transnoentities("DateInvoice"); - } - $pdf->MultiCell($w, 3, $title." : ".dol_print_date($object->date, "day", false, $outputlangs, true), '', 'R'); - - if (!empty($conf->global->INVOICE_POINTOFTAX_DATE)) { - $posy += 4; - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("DatePointOfTax")." : ".dol_print_date($object->date_pointoftax, "day", false, $outputlangs), '', 'R'); - } - - if ($object->type != 2) { - $posy += 3; - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - $title = $outputlangs->transnoentities("DateDue"); - if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) { - $title .= ' - '.$outputlangsbis->transnoentities("DateDue"); - } - $pdf->MultiCell($w, 3, $title." : ".dol_print_date($object->date_lim_reglement, "day", false, $outputlangs, true), '', 'R'); - } - - if (empty($conf->global->MAIN_PDF_HIDE_CUSTOMER_CODE) && $object->thirdparty->code_client) { - $posy += 3; - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_client), '', 'R'); - } - - // Get contact - if (!empty($conf->global->DOC_SHOW_FIRST_SALES_REP)) { - $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL'); - if (count($arrayidcontact) > 0) { - $usertmp = new User($this->db); - $usertmp->fetch($arrayidcontact[0]); - $posy += 4; - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); - } - } - - $posy += 1; - - $top_shift = 0; - // Show list of linked objects - $current_y = $pdf->getY(); - $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size); - if ($current_y < $pdf->getY()) { - $top_shift = $pdf->getY() - $current_y; - } - - if ($showaddress) { - // Sender properties - $carac_emetteur = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object); - - // Show sender - $posy = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42; - $posy += $top_shift; - $posx = $this->marge_gauche; - if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) { - $posx = $this->page_largeur - $this->marge_droite - 80; - } - - $hautcadre = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 38 : 40; - $widthrecbox = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 82; - - - // Show sender frame - if (empty($conf->global->MAIN_PDF_NO_SENDER_FRAME)) { - $pdf->SetTextColor(0, 0, 0); - $pdf->SetFont('', '', $default_font_size - 2); - $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection); - $pdf->SetXY($posx, $posy); - $pdf->SetFillColor(230, 230, 230); - $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1); - $pdf->SetTextColor(0, 0, 60); - } - - // Show sender name - if (empty($conf->global->MAIN_PDF_HIDE_SENDER_NAME)) { - $pdf->SetXY($posx + 2, $posy + 3); - $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection); - $posy = $pdf->getY(); - } - - // Show sender information - $pdf->SetXY($posx + 2, $posy); - $pdf->SetFont('', '', $default_font_size - 1); - $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, $ltrdirection); - - - // If BILLING contact defined on invoice, we use it - $usecontact = false; - $arrayidcontact = $object->getIdContact('external', 'BILLING'); - if (count($arrayidcontact) > 0) { - $usecontact = true; - $result = $object->fetch_contact($arrayidcontact[0]); - } - - // Recipient name - if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || !empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT)))) { - $thirdparty = $object->contact; - } else { - $thirdparty = $object->thirdparty; - } - - $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs); - - $mode = 'target'; - $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), $usecontact, $mode, $object); - - // Show recipient - $widthrecbox = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 100; - if ($this->page_largeur < 210) { - $widthrecbox = 84; // To work with US executive format - } - $posy = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42; - $posy += $top_shift; - $posx = $this->page_largeur - $this->marge_droite - $widthrecbox; - if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) { - $posx = $this->marge_gauche; - } - - // Show recipient frame - if (empty($conf->global->MAIN_PDF_NO_RECIPENT_FRAME)) { - $pdf->SetTextColor(0, 0, 0); - $pdf->SetFont('', '', $default_font_size - 2); - $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox - 2, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection); - $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); - } - - // Show recipient name - $pdf->SetXY($posx + 2, $posy + 3); - $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_name, 0, $ltrdirection); - - $posy = $pdf->getY(); - - // Show recipient information - $pdf->SetFont('', '', $default_font_size - 1); - $pdf->SetXY($posx + 2, $posy); - $pdf->MultiCell($widthrecbox - 2, 4, $carac_client, 0, $ltrdirection); - } - - $pdf->SetTextColor(0, 0, 0); - return $top_shift; - } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore - /** - * Show footer of page. Need this->emetteur object - * - * @param TCPDF $pdf PDF - * @param Facture $object Object to show - * @param Translate $outputlangs Object lang for output - * @param int $hidefreetext 1=Hide free text - * @return int Return height of bottom margin including footer text - */ - protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0) - { - global $conf; - $showdetails = empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS) ? 0 : $conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS; - return pdf_pagefoot($pdf, $outputlangs, 'INVOICE_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext, $this->page_largeur, $this->watermark); - } + $curx = $this->marge_gauche; + $cury = $posy; + + $posy = pdf_bank($pdf, $outputlangs, $curx, $cury, $account, 0, $default_font_size); + + $posy += 2; + } + } + } + + return $posy; + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore + /** + * Show total to pay + * + * @param TCPDF $pdf Object PDF + * @param Facture $object Object invoice + * @param int $deja_regle Amount already paid (in the currency of invoice) + * @param int $posy Position depart + * @param Translate $outputlangs Objet langs + * @param Translate $outputlangsbis Object lang for output bis + * @return int Position pour suite + */ + protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis) + { + // phpcs:enable + global $conf, $mysoc, $hookmanager; + + $sign = 1; + if ($object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) { + $sign = -1; + } + + $default_font_size = pdf_getPDFFontSize($outputlangs); + + $outputlangsbis = null; + if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && $outputlangs->defaultlang != $conf->global->PDF_USE_ALSO_LANGUAGE_CODE) { + $outputlangsbis = new Translate('', $conf); + $outputlangsbis->setDefaultLang($conf->global->PDF_USE_ALSO_LANGUAGE_CODE); + $outputlangsbis->loadLangs(array("main", "dict", "companies", "bills", "products", "propal")); + $default_font_size--; + } + + $tab2_top = $posy; + $tab2_hl = 4; + $pdf->SetFont('', '', $default_font_size - 1); + + // Total table + $col1x = 120; + $col2x = 170; + if ($this->page_largeur < 210) { // To work with US executive format + $col1x -= 15; + $col2x -= 10; + } + $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x); + + $useborder = 0; + $index = 0; + + // Total HT + $pdf->SetFillColor(255, 255, 255); + $pdf->SetXY($col1x, $tab2_top + 0); + $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities(empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) ? "TotalHT" : "Total").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities(empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) ? "TotalHT" : "Total") : ''), 0, 'L', 1); + + $total_ht = ((!empty($conf->multicurrency->enabled) && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht); + $pdf->SetXY($col2x, $tab2_top + 0); + $pdf->MultiCell($largcol2, $tab2_hl, price($sign * ($total_ht + (!empty($object->remise) ? $object->remise : 0)), 0, $outputlangs), 0, 'R', 1); + + // Show VAT by rates and total + $pdf->SetFillColor(248, 248, 248); + + $total_ttc = (!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc; + + $this->atleastoneratenotnull = 0; + if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) { + $tvaisnull = ((!empty($this->tva) && count($this->tva) == 1 && isset($this->tva['0.000']) && is_float($this->tva['0.000'])) ? true : false); + if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL) && $tvaisnull) { + // Nothing to do + } else { + // FIXME amount of vat not supported with multicurrency + + //Local tax 1 before VAT + //if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') + //{ + foreach ($this->localtax1 as $localtax_type => $localtax_rate) { + if (in_array((string) $localtax_type, array('1', '3', '5'))) { + continue; + } + + foreach ($localtax_rate 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("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : ''); + $totalvat .= ' '; + $totalvat .= vatrate(abs($tvakey), 1).$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($tvaval, 0, $outputlangs), 0, 'R', 1); + } + } + } + //} + //Local tax 2 before VAT + //if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') + //{ + foreach ($this->localtax2 as $localtax_type => $localtax_rate) { + if (in_array((string) $localtax_type, array('1', '3', '5'))) { + continue; + } + + foreach ($localtax_rate 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("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : ''); + $totalvat .= ' '; + $totalvat .= vatrate(abs($tvakey), 1).$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($tvaval, 0, $outputlangs), 0, 'R', 1); + } + } + } + + //} + + // 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); + + $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; + } 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); + } + } + + //Local tax 1 after VAT + //if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') + //{ + foreach ($this->localtax1 as $localtax_type => $localtax_rate) { + if (in_array((string) $localtax_type, array('2', '4', '6'))) { + continue; + } + + foreach ($localtax_rate 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("TotalLT1", $mysoc->country_code).' '; + $totalvat .= vatrate(abs($tvakey), 1).$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($tvaval, 0, $outputlangs), 0, 'R', 1); + } + } + } + //} + //Local tax 2 after VAT + //if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') + //{ + foreach ($this->localtax2 as $localtax_type => $localtax_rate) { + if (in_array((string) $localtax_type, array('2', '4', '6'))) { + continue; + } + + foreach ($localtax_rate as $tvakey => $tvaval) { + //$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("TotalLT2", $mysoc->country_code).' '; + + $totalvat .= vatrate(abs($tvakey), 1).$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($tvaval, 0, $outputlangs), 0, 'R', 1); + } + } + //} + + // Revenue stamp + if (price2num($object->revenuestamp) != 0) { + $index++; + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RevenueStamp"), $useborder, 'L', 1); + + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $object->revenuestamp), $useborder, 'R', 1); + } + + // Total TTC + $index++; + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->SetTextColor(0, 0, 60); + $pdf->SetFillColor(224, 224, 224); + $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC"), $useborder, 'L', 1); + + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $total_ttc, 0, $outputlangs), $useborder, 'R', 1); + + // Retained warranty + if ($object->displayRetainedWarranty()) { + $pdf->SetTextColor(40, 40, 40); + $pdf->SetFillColor(255, 255, 255); + + $retainedWarranty = $object->getRetainedWarrantyAmount(); + $billedWithRetainedWarranty = $object->total_ttc - $retainedWarranty; + + // Billed - retained warranty + $index++; + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("ToPayOn", dol_print_date($object->date_lim_reglement, 'day')), $useborder, 'L', 1); + + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($billedWithRetainedWarranty), $useborder, 'R', 1); + + // retained warranty + $index++; + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + + $retainedWarrantyToPayOn = $outputlangs->transnoentities("RetainedWarranty").' ('.$object->retained_warranty.'%)'; + $retainedWarrantyToPayOn .= !empty($object->retained_warranty_date_limit) ? ' '.$outputlangs->transnoentities("toPayOn", dol_print_date($object->retained_warranty_date_limit, 'day')) : ''; + + $pdf->MultiCell($col2x - $col1x, $tab2_hl, $retainedWarrantyToPayOn, $useborder, 'L', 1); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($retainedWarranty), $useborder, 'R', 1); + } + } + } + + $pdf->SetTextColor(0, 0, 0); + $creditnoteamount = $object->getSumCreditNotesUsed((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? 1 : 0); // Warning, this also include excess received + $depositsamount = $object->getSumDepositsUsed((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? 1 : 0); + //print "x".$creditnoteamount."-".$depositsamount;exit; + $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT'); + if (!empty($object->paye)) { + $resteapayer = 0; + } + + if (($deja_regle > 0 || $creditnoteamount > 0 || $depositsamount > 0) && empty($conf->global->INVOICE_NO_PAYMENT_DETAILS)) { + // Already paid + Deposits + $index++; + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("Paid"), 0, 'L', 0); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle + $depositsamount, 0, $outputlangs), 0, 'R', 0); + + // Credit note + if ($creditnoteamount) { + $labeltouse = ($outputlangs->transnoentities("CreditNotesOrExcessReceived") != "CreditNotesOrExcessReceived") ? $outputlangs->transnoentities("CreditNotesOrExcessReceived") : $outputlangs->transnoentities("CreditNotes"); + $index++; + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($col2x - $col1x, $tab2_hl, $labeltouse, 0, 'L', 0); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($creditnoteamount, 0, $outputlangs), 0, 'R', 0); + } + + // Escompte + if ($object->close_code == Facture::CLOSECODE_DISCOUNTVAT) { + $index++; + $pdf->SetFillColor(255, 255, 255); + + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("EscompteOfferedShort"), $useborder, 'L', 1); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 0, $outputlangs), $useborder, 'R', 1); + + $resteapayer = 0; + } + + $index++; + $pdf->SetTextColor(0, 0, 60); + $pdf->SetFillColor(224, 224, 224); + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay"), $useborder, 'L', 1); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer, 0, $outputlangs), $useborder, 'R', 1); + + $pdf->SetFont('', '', $default_font_size - 1); + $pdf->SetTextColor(0, 0, 0); + } + + $index++; + return ($tab2_top + ($tab2_hl * $index)); + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore + /** + * Show table for lines + * + * @param TCPDF $pdf Object PDF + * @param string $tab_top Top position of table + * @param string $tab_height Height of table (rectangle) + * @param int $nexY Y (not used) + * @param Translate $outputlangs Langs object + * @param int $hidetop 1=Hide top bar of array and title, 0=Hide nothing, -1=Hide only title + * @param int $hidebottom Hide bottom bar of array + * @param string $currency Currency code + * @return void + */ + protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '') + { + global $conf; + + // Force to disable hidetop and hidebottom + $hidebottom = 0; + if ($hidetop) { + $hidetop = -1; + } + + $currency = !empty($currency) ? $currency : $conf->currency; + $default_font_size = pdf_getPDFFontSize($outputlangs); + + // Amount in (at tab_top - 1) + $pdf->SetTextColor(0, 0, 0); + $pdf->SetFont('', '', $default_font_size - 2); + + if (empty($hidetop)) { + $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency)); + $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4); + $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre); + + //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230'; + if (!empty($conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)) { + $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, 5, 'F', null, explode(',', $conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)); + } + } + + $pdf->SetDrawColor(128, 128, 128); + $pdf->SetFont('', '', $default_font_size - 1); + + // Output Rect + $this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect takes a length in 3rd parameter and 4th parameter + + if (empty($hidetop)) { + $pdf->line($this->marge_gauche, $tab_top + 5, $this->page_largeur - $this->marge_droite, $tab_top + 5); // line takes a position y in 2nd parameter and 4th parameter + + $pdf->SetXY($this->posxdesc - 1, $tab_top + 1); + $pdf->MultiCell(108, 2, $outputlangs->transnoentities("Designation"), '', 'L'); + } + + if (!empty($conf->global->MAIN_GENERATE_INVOICES_WITH_PICTURE)) { + $pdf->line($this->posxpicture - 1, $tab_top, $this->posxpicture - 1, $tab_top + $tab_height); + if (empty($hidetop)) { + //$pdf->SetXY($this->posxpicture-1, $tab_top+1); + //$pdf->MultiCell($this->posxtva-$this->posxpicture-1,2, $outputlangs->transnoentities("Photo"),'','C'); + } + } + + if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) && empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) { + $pdf->line($this->posxtva - 1, $tab_top, $this->posxtva - 1, $tab_top + $tab_height); + if (empty($hidetop)) { + $pdf->SetXY($this->posxtva - 3, $tab_top + 1); + $pdf->MultiCell($this->posxup - $this->posxtva + 3, 2, $outputlangs->transnoentities("VAT"), '', 'C'); + } + } + + $pdf->line($this->posxup - 1, $tab_top, $this->posxup - 1, $tab_top + $tab_height); + if (empty($hidetop)) { + $pdf->SetXY($this->posxup - 1, $tab_top + 1); + $pdf->MultiCell($this->posxqty - $this->posxup - 1, 2, $outputlangs->transnoentities("PriceUHT"), '', 'C'); + } + + $pdf->line($this->posxqty - 1, $tab_top, $this->posxqty - 1, $tab_top + $tab_height); + if (empty($hidetop)) { + $pdf->SetXY($this->posxqty - 1, $tab_top + 1); + $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C'); + } + + if (!empty($conf->global->PRODUCT_USE_UNITS)) { + $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height); + if (empty($hidetop)) { + $pdf->SetXY($this->posxunit - 1, $tab_top + 1); + $pdf->MultiCell($this->posxdiscount - $this->posxunit - 1, 2, $outputlangs->transnoentities("Unit"), '', 'C'); + } + } + + if ($this->atleastonediscount) { + $pdf->line($this->posxdiscount - 1, $tab_top, $this->posxdiscount - 1, $tab_top + $tab_height); + if (empty($hidetop)) { + $pdf->SetXY($this->posxdiscount - 1, $tab_top + 1); + $pdf->MultiCell($this->posxprogress - $this->posxdiscount + 1, 2, $outputlangs->transnoentities("ReductionShort"), '', 'C'); + } + } + + if ($this->situationinvoice) { + $pdf->line($this->posxprogress - 1, $tab_top, $this->posxprogress - 1, $tab_top + $tab_height); + if (empty($hidetop)) { + $pdf->SetXY($this->posxprogress, $tab_top + 1); + $pdf->MultiCell($this->postotalht - $this->posxprogress, 2, $outputlangs->transnoentities("ProgressShort"), '', 'C'); + } + } + + $pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height); + if (empty($hidetop)) { + $pdf->SetXY($this->postotalht - 1, $tab_top + 1); + $pdf->MultiCell(30, 2, $outputlangs->transnoentities("TotalHT"), '', 'C'); + } + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore + /** + * Show top header of page. + * + * @param TCPDF $pdf Object PDF + * @param Facture $object Object to show + * @param int $showaddress 0=no, 1=yes + * @param Translate $outputlangs Object lang for output + * @param Translate $outputlangsbis Object lang for output bis + * @return int top shift of linked object lines + */ + protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null) + { + global $conf, $langs; + + $ltrdirection = 'L'; + if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R'; + + // Load traductions files required by page + $outputlangs->loadLangs(array("main", "bills", "propal", "companies")); + + $default_font_size = pdf_getPDFFontSize($outputlangs); + + pdf_pagehead($pdf, $outputlangs, $this->page_hauteur); + + $pdf->SetTextColor(0, 0, 60); + $pdf->SetFont('', 'B', $default_font_size + 3); + + $w = 110; + + $posy = $this->marge_haute; + $posx = $this->page_largeur - $this->marge_droite - $w; + + $pdf->SetXY($this->marge_gauche, $posy); + + // Logo + if (empty($conf->global->PDF_DISABLE_MYCOMPANY_LOGO)) { + if ($this->emetteur->logo) { + $logodir = $conf->mycompany->dir_output; + if (!empty($conf->mycompany->multidir_output[$object->entity])) { + $logodir = $conf->mycompany->multidir_output[$object->entity]; + } + if (empty($conf->global->MAIN_PDF_USE_LARGE_LOGO)) { + $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small; + } else { + $logo = $logodir.'/logos/'.$this->emetteur->logo; + } + if (is_readable($logo)) { + $height = pdf_getHeightForLogo($logo); + $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto) + } else { + $pdf->SetTextColor(200, 0, 0); + $pdf->SetFont('', 'B', $default_font_size - 2); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L'); + } + } else { + $text = $this->emetteur->name; + $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection); + } + } + + $pdf->SetFont('', 'B', $default_font_size + 3); + $pdf->SetXY($posx, $posy); + $pdf->SetTextColor(0, 0, 60); + $title = $outputlangs->transnoentities("PdfInvoiceTitle"); + if ($object->type == 1) { + $title = $outputlangs->transnoentities("InvoiceReplacement"); + } + if ($object->type == 2) { + $title = $outputlangs->transnoentities("InvoiceAvoir"); + } + if ($object->type == 3) { + $title = $outputlangs->transnoentities("InvoiceDeposit"); + } + if ($object->type == 4) { + $title = $outputlangs->transnoentities("InvoiceProForma"); + } + if ($this->situationinvoice) { + $title = $outputlangs->transnoentities("PDFInvoiceSituation"); + } + if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) { + $title .= ' - '; + if ($object->type == 0) { + if ($this->situationinvoice) { + $title .= $outputlangsbis->transnoentities("PDFInvoiceSituation"); + } + $title .= $outputlangsbis->transnoentities("PdfInvoiceTitle"); + } elseif ($object->type == 1) { + $title .= $outputlangsbis->transnoentities("InvoiceReplacement"); + } elseif ($object->type == 2) { + $title .= $outputlangsbis->transnoentities("InvoiceAvoir"); + } elseif ($object->type == 3) { + $title .= $outputlangsbis->transnoentities("InvoiceDeposit"); + } elseif ($object->type == 4) { + $title .= $outputlangsbis->transnoentities("InvoiceProForma"); + } + } + $title .= ' '.$outputlangs->convToOutputCharset($object->ref); + if ($object->statut == $object::STATUS_DRAFT) { + $pdf->SetTextColor(128, 0, 0); + $title .= ' - '.$outputlangs->transnoentities("NotValidated"); + } + + $pdf->MultiCell($w, 3, $title, '', 'R'); + + $pdf->SetFont('', 'B', $default_font_size); + + /* + $posy += 5; + $pdf->SetXY($posx, $posy); + $pdf->SetTextColor(0, 0, 60); + $textref = $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref); + if ($object->statut == $object::STATUS_DRAFT) { + $pdf->SetTextColor(128, 0, 0); + $textref .= ' - '.$outputlangs->transnoentities("NotValidated"); + } + $pdf->MultiCell($w, 4, $textref, '', 'R');*/ + + $posy += 3; + $pdf->SetFont('', '', $default_font_size - 2); + + if ($object->ref_client) { + $posy += 4; + $pdf->SetXY($posx, $posy); + $pdf->SetTextColor(0, 0, 60); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".$outputlangs->convToOutputCharset($object->ref_client), '', 'R'); + } + + if (!empty($conf->global->PDF_SHOW_PROJECT_TITLE)) { + $object->fetch_projet(); + if (!empty($object->project->ref)) { + $posy += 3; + $pdf->SetXY($posx, $posy); + $pdf->SetTextColor(0, 0, 60); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->title) ? '' : $object->project->title), '', 'R'); + } + } + + if (!empty($conf->global->PDF_SHOW_PROJECT)) { + $object->fetch_projet(); + if (!empty($object->project->ref)) { + $outputlangs->load("projects"); + $posy += 3; + $pdf->SetXY($posx, $posy); + $pdf->SetTextColor(0, 0, 60); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefProject")." : ".(empty($object->project->ref) ? '' : $object->project->ref), '', 'R'); + } + } + + $objectidnext = $object->getIdReplacingInvoice('validated'); + if ($object->type == 0 && $objectidnext) { + $objectreplacing = new Facture($this->db); + $objectreplacing->fetch($objectidnext); + + $posy += 3; + $pdf->SetXY($posx, $posy); + $pdf->SetTextColor(0, 0, 60); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ReplacementByInvoice").' : '.$outputlangs->convToOutputCharset($objectreplacing->ref), '', 'R'); + } + if ($object->type == 1) { + $objectreplaced = new Facture($this->db); + $objectreplaced->fetch($object->fk_facture_source); + + $posy += 4; + $pdf->SetXY($posx, $posy); + $pdf->SetTextColor(0, 0, 60); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ReplacementInvoice").' : '.$outputlangs->convToOutputCharset($objectreplaced->ref), '', 'R'); + } + if ($object->type == 2 && !empty($object->fk_facture_source)) { + $objectreplaced = new Facture($this->db); + $objectreplaced->fetch($object->fk_facture_source); + + $posy += 3; + $pdf->SetXY($posx, $posy); + $pdf->SetTextColor(0, 0, 60); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CorrectionInvoice").' : '.$outputlangs->convToOutputCharset($objectreplaced->ref), '', 'R'); + } + + $posy += 4; + $pdf->SetXY($posx, $posy); + $pdf->SetTextColor(0, 0, 60); + $title = $outputlangs->transnoentities("DateInvoice"); + if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) { + $title .= ' - '.$outputlangsbis->transnoentities("DateInvoice"); + } + $pdf->MultiCell($w, 3, $title." : ".dol_print_date($object->date, "day", false, $outputlangs, true), '', 'R'); + + if (!empty($conf->global->INVOICE_POINTOFTAX_DATE)) { + $posy += 4; + $pdf->SetXY($posx, $posy); + $pdf->SetTextColor(0, 0, 60); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("DatePointOfTax")." : ".dol_print_date($object->date_pointoftax, "day", false, $outputlangs), '', 'R'); + } + + if ($object->type != 2) { + $posy += 3; + $pdf->SetXY($posx, $posy); + $pdf->SetTextColor(0, 0, 60); + $title = $outputlangs->transnoentities("DateDue"); + if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) { + $title .= ' - '.$outputlangsbis->transnoentities("DateDue"); + } + $pdf->MultiCell($w, 3, $title." : ".dol_print_date($object->date_lim_reglement, "day", false, $outputlangs, true), '', 'R'); + } + + if (empty($conf->global->MAIN_PDF_HIDE_CUSTOMER_CODE) && $object->thirdparty->code_client) { + $posy += 3; + $pdf->SetXY($posx, $posy); + $pdf->SetTextColor(0, 0, 60); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_client), '', 'R'); + } + + // Get contact + if (!empty($conf->global->DOC_SHOW_FIRST_SALES_REP)) { + $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL'); + if (count($arrayidcontact) > 0) { + $usertmp = new User($this->db); + $usertmp->fetch($arrayidcontact[0]); + $posy += 4; + $pdf->SetXY($posx, $posy); + $pdf->SetTextColor(0, 0, 60); + $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + } + } + + $posy += 1; + + $top_shift = 0; + // Show list of linked objects + $current_y = $pdf->getY(); + $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size); + if ($current_y < $pdf->getY()) { + $top_shift = $pdf->getY() - $current_y; + } + + if ($showaddress) { + // Sender properties + $carac_emetteur = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object); + + // Show sender + $posy = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42; + $posy += $top_shift; + $posx = $this->marge_gauche; + if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) { + $posx = $this->page_largeur - $this->marge_droite - 80; + } + + $hautcadre = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 38 : 40; + $widthrecbox = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 82; + + + // Show sender frame + if (empty($conf->global->MAIN_PDF_NO_SENDER_FRAME)) { + $pdf->SetTextColor(0, 0, 0); + $pdf->SetFont('', '', $default_font_size - 2); + $pdf->SetXY($posx, $posy - 5); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection); + $pdf->SetXY($posx, $posy); + $pdf->SetFillColor(230, 230, 230); + $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1); + $pdf->SetTextColor(0, 0, 60); + } + + // Show sender name + if (empty($conf->global->MAIN_PDF_HIDE_SENDER_NAME)) { + $pdf->SetXY($posx + 2, $posy + 3); + $pdf->SetFont('', 'B', $default_font_size); + $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection); + $posy = $pdf->getY(); + } + + // Show sender information + $pdf->SetXY($posx + 2, $posy); + $pdf->SetFont('', '', $default_font_size - 1); + $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, $ltrdirection); + + + // If BILLING contact defined on invoice, we use it + $usecontact = false; + $arrayidcontact = $object->getIdContact('external', 'BILLING'); + if (count($arrayidcontact) > 0) { + $usecontact = true; + $result = $object->fetch_contact($arrayidcontact[0]); + } + + // Recipient name + if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || !empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT)))) { + $thirdparty = $object->contact; + } else { + $thirdparty = $object->thirdparty; + } + + $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs); + + $mode = 'target'; + $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), $usecontact, $mode, $object); + + // Show recipient + $widthrecbox = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 100; + if ($this->page_largeur < 210) { + $widthrecbox = 84; // To work with US executive format + } + $posy = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42; + $posy += $top_shift; + $posx = $this->page_largeur - $this->marge_droite - $widthrecbox; + if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) { + $posx = $this->marge_gauche; + } + + // Show recipient frame + if (empty($conf->global->MAIN_PDF_NO_RECIPENT_FRAME)) { + $pdf->SetTextColor(0, 0, 0); + $pdf->SetFont('', '', $default_font_size - 2); + $pdf->SetXY($posx + 2, $posy - 5); + $pdf->MultiCell($widthrecbox - 2, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection); + $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); + } + + // Show recipient name + $pdf->SetXY($posx + 2, $posy + 3); + $pdf->SetFont('', 'B', $default_font_size); + $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_name, 0, $ltrdirection); + + $posy = $pdf->getY(); + + // Show recipient information + $pdf->SetFont('', '', $default_font_size - 1); + $pdf->SetXY($posx + 2, $posy); + $pdf->MultiCell($widthrecbox - 2, 4, $carac_client, 0, $ltrdirection); + } + + $pdf->SetTextColor(0, 0, 0); + return $top_shift; + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore + /** + * Show footer of page. Need this->emetteur object + * + * @param TCPDF $pdf PDF + * @param Facture $object Object to show + * @param Translate $outputlangs Object lang for output + * @param int $hidefreetext 1=Hide free text + * @return int Return height of bottom margin including footer text + */ + protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0) + { + global $conf; + $showdetails = empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS) ? 0 : $conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS; + return pdf_pagefoot($pdf, $outputlangs, 'INVOICE_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext, $this->page_largeur, $this->watermark); + } } From adeb447227c91f09a54b905561269980a60801cf Mon Sep 17 00:00:00 2001 From: Benoit Vianin Date: Sat, 4 Mar 2023 18:09:53 +0100 Subject: [PATCH 2/7] Update dependencies and Readme --- README.md | 20 ++- .../doc/vendor/composer/installed.json | 105 ++++++++-------- .../facture/doc/vendor/composer/installed.php | 46 +++---- .../dasprid/enum/.github/workflows/tests.yml | 47 +++++++ .../facture/doc/vendor/dasprid/enum/README.md | 30 ++--- .../doc/vendor/dasprid/enum/composer.json | 5 +- .../doc/vendor/dasprid/enum/src/EnumMap.php | 42 ++++--- .../DateFormat/HourTransformer.php | 4 +- .../DateFormat/QuarterTransformer.php | 10 +- .../intl/DateFormatter/IntlDateFormatter.php | 14 +-- .../facture/doc/vendor/symfony/intl/LICENSE | 2 +- .../doc/vendor/symfony/intl/Locale/Locale.php | 28 ++--- .../intl/NumberFormatter/NumberFormatter.php | 14 +-- .../vendor/symfony/intl/ResourceBundle.php | 14 +-- .../vendor/symfony/options-resolver/LICENSE | 2 +- .../vendor/symfony/property-access/LICENSE | 2 +- .../Extractor/PhpDocExtractor.php | 4 +- .../Extractor/PhpStanExtractor.php | 9 ++ .../doc/vendor/symfony/property-info/LICENSE | 2 +- .../property-info/Util/PhpDocTypeHelper.php | 2 +- .../symfony/string/AbstractUnicodeString.php | 4 +- .../facture/doc/vendor/symfony/string/LICENSE | 2 +- .../Constraints/AtLeastOneOfValidator.php | 6 +- .../validator/Constraints/EmailValidator.php | 3 +- .../validator/Constraints/IbanValidator.php | 116 +++++++++++------- .../doc/vendor/symfony/validator/LICENSE | 2 +- .../Test/ConstraintValidatorTestCase.php | 26 ++-- .../vendor/symfony/validator/composer.json | 2 +- 28 files changed, 344 insertions(+), 219 deletions(-) create mode 100644 htdocs/core/modules/facture/doc/vendor/dasprid/enum/.github/workflows/tests.yml diff --git a/README.md b/README.md index f073158..8b8012d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Swiss QR Invoice for Dolibarr This repository is a set of files to add Swiss QR invoice to Dolibarr ERP/CRM. +The model supports QR-IBAN or classic IBAN. ## Requirement @@ -9,7 +10,8 @@ This set of files is actually tested on Dolibarr 16.0.1 with PHP 7.4.29 ## Installation 1. Copy each files with the same name in the same directory of the Dolibarr installation. -2. Activated invoice templates in the Setup -> Modules/Apllications -> Invoices +2. Activated invoice templates in the Setup -> Modules/Apllications -> Invoices. +3. In case of QR-IBAN add the variable SI_SWISSQR_REF in Configuration->Other Setup. You receive this number from your bank (BESR-ID). ## Baed on @@ -18,7 +20,8 @@ This set of files is actually tested on Dolibarr 16.0.1 with PHP 7.4.29 # QR facture suisse pour Dolibarr -Ce dépôt est un ensemble de fichiers pour ajouter la facture QR suisse à l'ERP/CRM Dolibarr +Ce dépôt est un ensemble de fichiers pour ajouter la facture QR suisse à l'ERP/CRM Dolibarr. +Le modèle supporte le QR-IBAN ou l'IBAN classic. ## Prérequis @@ -27,11 +30,13 @@ Ces fichiers sont actuellement testés avec Dolibarr 16.0.1 et PHP 7.4.29 ## Installation 1. Copier l'ensemble des fichiers dans les mêmes répertoires de votre installation Dolibarr. -2. Activer le modèle de facture dans Configuration->Modules/Applications -> Factures +2. Activer le modèle de facture dans Configuration->Modules/Applications -> Factures. +3. Dans le cas du QR-IBAN ajouter la variable SI_SWISSQR_REF dans Configuration->Divers. Vous recevez ce numéro de votre banque (BESR-ID). # Swiss QR Invoice für Dolibarr Dieses Repository enthält eine Reihe von Dateien, um die Schweizer QR-Rechnung zu Dolibarr ERP/CRM hinzuzufügen. +Die Vorlage unterstützt QR-IBAN oder IBAN classic. ## Anforderung @@ -40,17 +45,20 @@ Dieser Satz von Dateien ist auf Dolibarr 16.0.1 mit PHP 7.4.29 getestet. ## Installation 1. Kopieren Sie alle Dateien mit dem gleichen Namen in das gleiche Verzeichnis der Dolibarr-Installation. -2. Aktivieren Sie die Rechnungsvorlagen im Setup -> Module/Applikationen -> Rechnungen +2. Aktivieren Sie die Rechnungsvorlagen im Setup -> Module/Applikationen -> Rechnungen. +3. Im Fall von QR-IBAN fügen Sie die Variable SI_SWISSQR_REF in Konfiguration->Diverses hinzu. Sie erhalten diese Nummer von Ihrer Bank (BESR-ID). # Fattura QR svizzera per Dolibarr Questo repository è un insieme di file per aggiungere la fattura Swiss QR all'ERP/CRM Dolibarr. +Il modello supporta QR-IBAN o IBAN classico. ## Requisiti -Questo set di file è stato testato su Dolibarr 16.0.1 con PHP 7.4.29. +Questo set di file è stato testato su Dolibarr 16.0.1 con PHP 7.4.29 ## Installazione 1. Copiare i file con lo stesso nome nella stessa directory dell'installazione di Dolibarr. -2. Attivare i modelli di fattura in Impostazione -> Moduli/Allegati -> Fatture. \ No newline at end of file +2. Attivare i modelli di fattura in Impostazione -> Moduli/Allegati -> Fatture. +3. In caso di QR-IBAN, aggiungere la variabile SI_SWISSQR_REF in Configurazione->Varie. Questo numero viene fornito dalla banca (BESR-ID). \ No newline at end of file diff --git a/htdocs/core/modules/facture/doc/vendor/composer/installed.json b/htdocs/core/modules/facture/doc/vendor/composer/installed.json index 6aef6f1..abe9930 100644 --- a/htdocs/core/modules/facture/doc/vendor/composer/installed.json +++ b/htdocs/core/modules/facture/doc/vendor/composer/installed.json @@ -59,24 +59,27 @@ }, { "name": "dasprid/enum", - "version": "1.0.3", - "version_normalized": "1.0.3.0", + "version": "1.0.4", + "version_normalized": "1.0.4.0", "source": { "type": "git", "url": "https://github.com/DASPRiD/Enum.git", - "reference": "5abf82f213618696dda8e3bf6f64dd042d8542b2" + "reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/5abf82f213618696dda8e3bf6f64dd042d8542b2", - "reference": "5abf82f213618696dda8e3bf6f64dd042d8542b2", + "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8e6b6ea76eabbf19ea2bf5b67b98e1860474012f", + "reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f", "shasum": "" }, + "require": { + "php": ">=7.1 <9.0" + }, "require-dev": { "phpunit/phpunit": "^7 | ^8 | ^9", - "squizlabs/php_codesniffer": "^3.4" + "squizlabs/php_codesniffer": "*" }, - "time": "2020-10-02T16:03:48+00:00", + "time": "2023-03-01T18:44:03+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -103,7 +106,7 @@ ], "support": { "issues": "https://github.com/DASPRiD/Enum/issues", - "source": "https://github.com/DASPRiD/Enum/tree/1.0.3" + "source": "https://github.com/DASPRiD/Enum/tree/1.0.4" }, "install-path": "../dasprid/enum" }, @@ -500,17 +503,17 @@ }, { "name": "symfony/intl", - "version": "v5.4.15", - "version_normalized": "5.4.15.0", + "version": "v5.4.21", + "version_normalized": "5.4.21.0", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "2cb39da7f6e7b7344d7d5317dbee8db9d12cc714" + "reference": "32c2d958b88f5c7f0b080774d7d15d4c87769bc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/2cb39da7f6e7b7344d7d5317dbee8db9d12cc714", - "reference": "2cb39da7f6e7b7344d7d5317dbee8db9d12cc714", + "url": "https://api.github.com/repos/symfony/intl/zipball/32c2d958b88f5c7f0b080774d7d15d4c87769bc8", + "reference": "32c2d958b88f5c7f0b080774d7d15d4c87769bc8", "shasum": "" }, "require": { @@ -521,7 +524,7 @@ "require-dev": { "symfony/filesystem": "^4.4|^5.0|^6.0" }, - "time": "2022-10-19T14:28:49+00:00", + "time": "2023-02-17T21:35:35+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -571,7 +574,7 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v5.4.15" + "source": "https://github.com/symfony/intl/tree/v5.4.21" }, "funding": [ { @@ -591,17 +594,17 @@ }, { "name": "symfony/options-resolver", - "version": "v5.4.11", - "version_normalized": "5.4.11.0", + "version": "v5.4.21", + "version_normalized": "5.4.21.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "54f14e36aa73cb8f7261d7686691fd4d75ea2690" + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/54f14e36aa73cb8f7261d7686691fd4d75ea2690", - "reference": "54f14e36aa73cb8f7261d7686691fd4d75ea2690", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", "shasum": "" }, "require": { @@ -610,7 +613,7 @@ "symfony/polyfill-php73": "~1.0", "symfony/polyfill-php80": "^1.16" }, - "time": "2022-07-20T13:00:38+00:00", + "time": "2023-02-14T08:03:56+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -643,7 +646,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.11" + "source": "https://github.com/symfony/options-resolver/tree/v5.4.21" }, "funding": [ { @@ -1345,17 +1348,17 @@ }, { "name": "symfony/property-access", - "version": "v5.4.15", - "version_normalized": "5.4.15.0", + "version": "v5.4.21", + "version_normalized": "5.4.21.0", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "0f3e8f40a1d3da90f674b3dd772e4777ccde4273" + "reference": "bbd4442bfbdf3992550772539ba743d6d834534f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/0f3e8f40a1d3da90f674b3dd772e4777ccde4273", - "reference": "0f3e8f40a1d3da90f674b3dd772e4777ccde4273", + "url": "https://api.github.com/repos/symfony/property-access/zipball/bbd4442bfbdf3992550772539ba743d6d834534f", + "reference": "bbd4442bfbdf3992550772539ba743d6d834534f", "shasum": "" }, "require": { @@ -1370,7 +1373,7 @@ "suggest": { "psr/cache-implementation": "To cache access methods." }, - "time": "2022-10-27T07:55:40+00:00", + "time": "2023-02-16T09:33:00+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1409,7 +1412,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v5.4.15" + "source": "https://github.com/symfony/property-access/tree/v5.4.21" }, "funding": [ { @@ -1429,17 +1432,17 @@ }, { "name": "symfony/property-info", - "version": "v5.4.17", - "version_normalized": "5.4.17.0", + "version": "v5.4.21", + "version_normalized": "5.4.21.0", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "12e1f7b3d73b1f3690aa524b92b5de9937507361" + "reference": "722737086d76b4edabfc2d50a48cebd4b8cd5546" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/12e1f7b3d73b1f3690aa524b92b5de9937507361", - "reference": "12e1f7b3d73b1f3690aa524b92b5de9937507361", + "url": "https://api.github.com/repos/symfony/property-info/zipball/722737086d76b4edabfc2d50a48cebd4b8cd5546", + "reference": "722737086d76b4edabfc2d50a48cebd4b8cd5546", "shasum": "" }, "require": { @@ -1467,7 +1470,7 @@ "symfony/doctrine-bridge": "To use Doctrine metadata", "symfony/serializer": "To use Serializer metadata" }, - "time": "2022-12-20T11:10:57+00:00", + "time": "2023-02-16T09:33:00+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1503,7 +1506,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v5.4.17" + "source": "https://github.com/symfony/property-info/tree/v5.4.21" }, "funding": [ { @@ -1523,17 +1526,17 @@ }, { "name": "symfony/string", - "version": "v5.4.17", - "version_normalized": "5.4.17.0", + "version": "v5.4.21", + "version_normalized": "5.4.21.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "55733a8664b8853b003e70251c58bc8cb2d82a6b" + "reference": "edac10d167b78b1d90f46a80320d632de0bd9f2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/55733a8664b8853b003e70251c58bc8cb2d82a6b", - "reference": "55733a8664b8853b003e70251c58bc8cb2d82a6b", + "url": "https://api.github.com/repos/symfony/string/zipball/edac10d167b78b1d90f46a80320d632de0bd9f2f", + "reference": "edac10d167b78b1d90f46a80320d632de0bd9f2f", "shasum": "" }, "require": { @@ -1553,7 +1556,7 @@ "symfony/translation-contracts": "^1.1|^2", "symfony/var-exporter": "^4.4|^5.0|^6.0" }, - "time": "2022-12-12T15:54:21+00:00", + "time": "2023-02-22T08:00:55+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1592,7 +1595,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.17" + "source": "https://github.com/symfony/string/tree/v5.4.21" }, "funding": [ { @@ -1693,17 +1696,17 @@ }, { "name": "symfony/validator", - "version": "v5.4.17", - "version_normalized": "5.4.17.0", + "version": "v5.4.21", + "version_normalized": "5.4.21.0", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "621b820204a238d754f7f60241fcbdb1687641ea" + "reference": "0ba987d705962a4f6571d31a8e1aed18ad2c9f55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/621b820204a238d754f7f60241fcbdb1687641ea", - "reference": "621b820204a238d754f7f60241fcbdb1687641ea", + "url": "https://api.github.com/repos/symfony/validator/zipball/0ba987d705962a4f6571d31a8e1aed18ad2c9f55", + "reference": "0ba987d705962a4f6571d31a8e1aed18ad2c9f55", "shasum": "" }, "require": { @@ -1732,7 +1735,7 @@ "require-dev": { "doctrine/annotations": "^1.13|^2", "doctrine/cache": "^1.11|^2.0", - "egulias/email-validator": "^2.1.10|^3", + "egulias/email-validator": "^2.1.10|^3|^4", "symfony/cache": "^4.4|^5.0|^6.0", "symfony/config": "^4.4|^5.0|^6.0", "symfony/console": "^4.4|^5.0|^6.0", @@ -1761,7 +1764,7 @@ "symfony/translation": "For translating validation errors.", "symfony/yaml": "" }, - "time": "2022-12-21T19:20:17+00:00", + "time": "2023-02-22T19:16:45+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1789,7 +1792,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v5.4.17" + "source": "https://github.com/symfony/validator/tree/v5.4.21" }, "funding": [ { diff --git a/htdocs/core/modules/facture/doc/vendor/composer/installed.php b/htdocs/core/modules/facture/doc/vendor/composer/installed.php index 88f4c29..554b127 100644 --- a/htdocs/core/modules/facture/doc/vendor/composer/installed.php +++ b/htdocs/core/modules/facture/doc/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => '__root__', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '4f030b05af2d8e0e4875c40d35686b88e7924979', + 'reference' => '0b5bf953d7af542abca30ebb41f2db12add3f214', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -13,7 +13,7 @@ '__root__' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '4f030b05af2d8e0e4875c40d35686b88e7924979', + 'reference' => '0b5bf953d7af542abca30ebb41f2db12add3f214', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -29,9 +29,9 @@ 'dev_requirement' => false, ), 'dasprid/enum' => array( - 'pretty_version' => '1.0.3', - 'version' => '1.0.3.0', - 'reference' => '5abf82f213618696dda8e3bf6f64dd042d8542b2', + 'pretty_version' => '1.0.4', + 'version' => '1.0.4.0', + 'reference' => '8e6b6ea76eabbf19ea2bf5b67b98e1860474012f', 'type' => 'library', 'install_path' => __DIR__ . '/../dasprid/enum', 'aliases' => array(), @@ -92,18 +92,18 @@ 'dev_requirement' => false, ), 'symfony/intl' => array( - 'pretty_version' => 'v5.4.15', - 'version' => '5.4.15.0', - 'reference' => '2cb39da7f6e7b7344d7d5317dbee8db9d12cc714', + 'pretty_version' => 'v5.4.21', + 'version' => '5.4.21.0', + 'reference' => '32c2d958b88f5c7f0b080774d7d15d4c87769bc8', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/intl', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/options-resolver' => array( - 'pretty_version' => 'v5.4.11', - 'version' => '5.4.11.0', - 'reference' => '54f14e36aa73cb8f7261d7686691fd4d75ea2690', + 'pretty_version' => 'v5.4.21', + 'version' => '5.4.21.0', + 'reference' => '4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/options-resolver', 'aliases' => array(), @@ -182,27 +182,27 @@ 'dev_requirement' => false, ), 'symfony/property-access' => array( - 'pretty_version' => 'v5.4.15', - 'version' => '5.4.15.0', - 'reference' => '0f3e8f40a1d3da90f674b3dd772e4777ccde4273', + 'pretty_version' => 'v5.4.21', + 'version' => '5.4.21.0', + 'reference' => 'bbd4442bfbdf3992550772539ba743d6d834534f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/property-access', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/property-info' => array( - 'pretty_version' => 'v5.4.17', - 'version' => '5.4.17.0', - 'reference' => '12e1f7b3d73b1f3690aa524b92b5de9937507361', + 'pretty_version' => 'v5.4.21', + 'version' => '5.4.21.0', + 'reference' => '722737086d76b4edabfc2d50a48cebd4b8cd5546', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/property-info', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/string' => array( - 'pretty_version' => 'v5.4.17', - 'version' => '5.4.17.0', - 'reference' => '55733a8664b8853b003e70251c58bc8cb2d82a6b', + 'pretty_version' => 'v5.4.21', + 'version' => '5.4.21.0', + 'reference' => 'edac10d167b78b1d90f46a80320d632de0bd9f2f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), @@ -218,9 +218,9 @@ 'dev_requirement' => false, ), 'symfony/validator' => array( - 'pretty_version' => 'v5.4.17', - 'version' => '5.4.17.0', - 'reference' => '621b820204a238d754f7f60241fcbdb1687641ea', + 'pretty_version' => 'v5.4.21', + 'version' => '5.4.21.0', + 'reference' => '0ba987d705962a4f6571d31a8e1aed18ad2c9f55', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/validator', 'aliases' => array(), diff --git a/htdocs/core/modules/facture/doc/vendor/dasprid/enum/.github/workflows/tests.yml b/htdocs/core/modules/facture/doc/vendor/dasprid/enum/.github/workflows/tests.yml new file mode 100644 index 0000000..94b2562 --- /dev/null +++ b/htdocs/core/modules/facture/doc/vendor/dasprid/enum/.github/workflows/tests.yml @@ -0,0 +1,47 @@ +name: Tests + +on: [push, pull_request] + +jobs: + php-tests: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: true + matrix: + php: [8.2, 8.1, 8.0, 7.4, 7.3, 7.2, 7.1] + dependency-version: [prefer-stable] + os: [ubuntu-latest, windows-latest] + + name: ${{ matrix.os }} - PHP${{ matrix.php }} - ${{ matrix.dependency-version }} + + steps: + - name: Set git to use LF + run: | + git config --global core.autocrlf false + git config --global core.eol lf + + - name: Checkout code + uses: actions/checkout@v3 + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: ~/.composer/cache/files + key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: none + + - name: Install dependencies + run: | + composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction + + - name: Execute tests + run: vendor/bin/phpunit + + - name: Code Sniffer + run: vendor/bin/phpcs + diff --git a/htdocs/core/modules/facture/doc/vendor/dasprid/enum/README.md b/htdocs/core/modules/facture/doc/vendor/dasprid/enum/README.md index 9e9ca12..da37045 100644 --- a/htdocs/core/modules/facture/doc/vendor/dasprid/enum/README.md +++ b/htdocs/core/modules/facture/doc/vendor/dasprid/enum/README.md @@ -1,6 +1,6 @@ # PHP 7.1 enums -[![Build Status](https://travis-ci.org/DASPRiD/Enum.svg?branch=master)](https://travis-ci.org/DASPRiD/Enum) +[![Build Status](https://github.com/DASPRiD/Enum/actions/workflows/tests.yml/badge.svg)](https://github.com/DASPRiD/Enum/actions?query=workflow%3Atests) [![Coverage Status](https://coveralls.io/repos/github/DASPRiD/Enum/badge.svg?branch=master)](https://coveralls.io/github/DASPRiD/Enum?branch=master) [![Latest Stable Version](https://poser.pugx.org/dasprid/enum/v/stable)](https://packagist.org/packages/dasprid/enum) [![Total Downloads](https://poser.pugx.org/dasprid/enum/downloads)](https://packagist.org/packages/dasprid/enum) @@ -41,7 +41,7 @@ final class WeekDay extends AbstractEnum protected const SATURDAY = null; protected const SUNDAY = null; } -``` +``` If you need to provide constants for either internal use or public use, you can mark them as either private or public, in which case they will be ignored by the enum, which only considers protected constants as valid values. As you can @@ -56,16 +56,16 @@ function tellItLikeItIs(WeekDay $weekDay) case WeekDay::MONDAY(): echo 'Mondays are bad.'; break; - + case WeekDay::FRIDAY(): echo 'Fridays are better.'; break; - + case WeekDay::SATURDAY(): case WeekDay::SUNDAY(): echo 'Weekends are best.'; break; - + default: echo 'Midweek days are so-so.'; } @@ -107,14 +107,14 @@ final class Planet extends AbstractEnum protected const SATURN = [5.688e+26, 6.0268e7]; protected const URANUS = [8.686e+25, 2.5559e7]; protected const NEPTUNE = [1.024e+26, 2.4746e7]; - + /** * Universal gravitational constant. * * @var float */ private const G = 6.67300E-11; - + /** * Mass in kilograms. * @@ -124,32 +124,32 @@ final class Planet extends AbstractEnum /** * Radius in meters. - * + * * @var float - */ + */ private $radius; - + protected function __construct(float $mass, float $radius) { $this->mass = $mass; $this->radius = $radius; } - + public function mass() : float { return $this->mass; } - + public function radius() : float { - return $this->radius; + return $this->radius; } - + public function surfaceGravity() : float { return self::G * $this->mass / ($this->radius * $this->radius); } - + public function surfaceWeight(float $otherMass) : float { return $otherMass * $this->surfaceGravity(); diff --git a/htdocs/core/modules/facture/doc/vendor/dasprid/enum/composer.json b/htdocs/core/modules/facture/doc/vendor/dasprid/enum/composer.json index b3d745a..133e279 100644 --- a/htdocs/core/modules/facture/doc/vendor/dasprid/enum/composer.json +++ b/htdocs/core/modules/facture/doc/vendor/dasprid/enum/composer.json @@ -14,9 +14,12 @@ "enum", "map" ], + "require": { + "php": ">=7.1 <9.0" + }, "require-dev": { "phpunit/phpunit": "^7 | ^8 | ^9", - "squizlabs/php_codesniffer": "^3.4" + "squizlabs/php_codesniffer": "*" }, "autoload": { "psr-4": { diff --git a/htdocs/core/modules/facture/doc/vendor/dasprid/enum/src/EnumMap.php b/htdocs/core/modules/facture/doc/vendor/dasprid/enum/src/EnumMap.php index 77c5f35..95b8856 100644 --- a/htdocs/core/modules/facture/doc/vendor/dasprid/enum/src/EnumMap.php +++ b/htdocs/core/modules/facture/doc/vendor/dasprid/enum/src/EnumMap.php @@ -88,6 +88,31 @@ final class EnumMap implements Serializable, IteratorAggregate $this->values = array_fill(0, count($this->keyUniverse), null); } + public function __serialize(): array + { + $values = []; + + foreach ($this->values as $ordinal => $value) { + if (null === $value) { + continue; + } + + $values[$ordinal] = $this->unmaskNull($value); + } + + return [ + 'keyType' => $this->keyType, + 'valueType' => $this->valueType, + 'allowNullValues' => $this->allowNullValues, + 'values' => $values, + ]; + } + + public function __unserialize(array $data): void + { + $this->unserialize(serialize($data)); + } + /** * Checks whether the map types match the supplied ones. * @@ -261,22 +286,7 @@ final class EnumMap implements Serializable, IteratorAggregate public function serialize() : string { - $values = []; - - foreach ($this->values as $ordinal => $value) { - if (null === $value) { - continue; - } - - $values[$ordinal] = $this->unmaskNull($value); - } - - return serialize([ - 'keyType' => $this->keyType, - 'valueType' => $this->valueType, - 'allowNullValues' => $this->allowNullValues, - 'values' => $values, - ]); + return serialize($this->__serialize()); } public function unserialize($serialized) : void diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/intl/DateFormatter/DateFormat/HourTransformer.php b/htdocs/core/modules/facture/doc/vendor/symfony/intl/DateFormatter/DateFormat/HourTransformer.php index 54dcbfe..a9734ac 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/intl/DateFormatter/DateFormat/HourTransformer.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/intl/DateFormatter/DateFormat/HourTransformer.php @@ -25,8 +25,8 @@ abstract class HourTransformer extends Transformer /** * Returns a normalized hour value suitable for the hour transformer type. * - * @param int $hour The hour value - * @param string $marker An optional AM/PM marker + * @param int $hour The hour value + * @param string|null $marker An optional AM/PM marker * * @return int The normalized hour value */ diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/intl/DateFormatter/DateFormat/QuarterTransformer.php b/htdocs/core/modules/facture/doc/vendor/symfony/intl/DateFormatter/DateFormat/QuarterTransformer.php index 71b95c8..83d8400 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/intl/DateFormatter/DateFormat/QuarterTransformer.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/intl/DateFormatter/DateFormat/QuarterTransformer.php @@ -35,10 +35,18 @@ class QuarterTransformer extends Transformer return $this->padLeft($quarter, $length); case 3: return 'Q'.$quarter; - default: + case 4: $map = [1 => '1st quarter', 2 => '2nd quarter', 3 => '3rd quarter', 4 => '4th quarter']; return $map[$quarter]; + default: + if (\defined('INTL_ICU_VERSION') && version_compare(\INTL_ICU_VERSION, '70.1', '<')) { + $map = [1 => '1st quarter', 2 => '2nd quarter', 3 => '3rd quarter', 4 => '4th quarter']; + + return $map[$quarter]; + } else { + return $quarter; + } } } diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/intl/DateFormatter/IntlDateFormatter.php b/htdocs/core/modules/facture/doc/vendor/symfony/intl/DateFormatter/IntlDateFormatter.php index 5b683c4..8625789 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/intl/DateFormatter/IntlDateFormatter.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/intl/DateFormatter/IntlDateFormatter.php @@ -124,7 +124,7 @@ abstract class IntlDateFormatter * @param int|null $datetype Type of date formatting, one of the format type constants * @param int|null $timetype Type of time formatting, one of the format type constants * @param \IntlTimeZone|\DateTimeZone|string|null $timezone Timezone identifier - * @param int $calendar Calendar to use for formatting or parsing. The only currently + * @param int|null $calendar Calendar to use for formatting or parsing. The only currently * supported value is IntlDateFormatter::GREGORIAN (or null using the default calendar, i.e. "GREGORIAN") * @param string|null $pattern Optional pattern to use when formatting * @@ -418,11 +418,11 @@ abstract class IntlDateFormatter /** * Parse string to a timestamp value. * - * @param string $value String to convert to a time value - * @param int $position Not supported. Position at which to start the parsing in $value (zero-based) - * If no error occurs before $value is consumed, $parse_pos will - * contain -1 otherwise it will contain the position at which parsing - * ended. If $parse_pos > strlen($value), the parse fails immediately. + * @param string $value String to convert to a time value + * @param int|null $position Not supported. Position at which to start the parsing in $value (zero-based) + * If no error occurs before $value is consumed, $parse_pos will + * contain -1 otherwise it will contain the position at which parsing + * ended. If $parse_pos > strlen($value), the parse fails immediately. * * @return int|false Parsed value as a timestamp * @@ -494,7 +494,7 @@ abstract class IntlDateFormatter /** * Set the formatter's pattern. * - * @param string $pattern A pattern string in conformance with the ICU IntlDateFormatter documentation + * @param string|null $pattern A pattern string in conformance with the ICU IntlDateFormatter documentation * * @return bool true on success or false on failure * diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/intl/LICENSE b/htdocs/core/modules/facture/doc/vendor/symfony/intl/LICENSE index 88bf75b..0138f8f 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/intl/LICENSE +++ b/htdocs/core/modules/facture/doc/vendor/symfony/intl/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2022 Fabien Potencier +Copyright (c) 2004-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/intl/Locale/Locale.php b/htdocs/core/modules/facture/doc/vendor/symfony/intl/Locale/Locale.php index 79d2f07..d806671 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/intl/Locale/Locale.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/intl/Locale/Locale.php @@ -152,8 +152,8 @@ abstract class Locale /** * Not supported. Returns the localized display name for the locale language. * - * @param string $locale The locale code to return the display language from - * @param string $inLocale Optional format locale code to use to display the language name + * @param string $locale The locale code to return the display language from + * @param string|null $inLocale Optional format locale code to use to display the language name * * @return string * @@ -169,8 +169,8 @@ abstract class Locale /** * Not supported. Returns the localized display name for the locale. * - * @param string $locale The locale code to return the display locale name from - * @param string $inLocale Optional format locale code to use to display the locale name + * @param string $locale The locale code to return the display locale name from + * @param string|null $inLocale Optional format locale code to use to display the locale name * * @return string * @@ -186,8 +186,8 @@ abstract class Locale /** * Not supported. Returns the localized display name for the locale region. * - * @param string $locale The locale code to return the display region from - * @param string $inLocale Optional format locale code to use to display the region name + * @param string $locale The locale code to return the display region from + * @param string|null $inLocale Optional format locale code to use to display the region name * * @return string * @@ -203,8 +203,8 @@ abstract class Locale /** * Not supported. Returns the localized display name for the locale script. * - * @param string $locale The locale code to return the display script from - * @param string $inLocale Optional format locale code to use to display the script name + * @param string $locale The locale code to return the display script from + * @param string|null $inLocale Optional format locale code to use to display the script name * * @return string * @@ -220,8 +220,8 @@ abstract class Locale /** * Not supported. Returns the localized display name for the locale variant. * - * @param string $locale The locale code to return the display variant from - * @param string $inLocale Optional format locale code to use to display the variant name + * @param string $locale The locale code to return the display variant from + * @param string|null $inLocale Optional format locale code to use to display the variant name * * @return string * @@ -301,10 +301,10 @@ abstract class Locale /** * Not supported. Returns the closest language tag for the locale. * - * @param array $langtag A list of the language tags to compare to locale - * @param string $locale The locale to use as the language range when matching - * @param bool $canonicalize If true, the arguments will be converted to canonical form before matching - * @param string $default The locale to use if no match is found + * @param array $langtag A list of the language tags to compare to locale + * @param string $locale The locale to use as the language range when matching + * @param bool $canonicalize If true, the arguments will be converted to canonical form before matching + * @param string|null $default The locale to use if no match is found * * @see https://php.net/locale.lookup * diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/intl/NumberFormatter/NumberFormatter.php b/htdocs/core/modules/facture/doc/vendor/symfony/intl/NumberFormatter/NumberFormatter.php index 2a369c2..b573f63 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/intl/NumberFormatter/NumberFormatter.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/intl/NumberFormatter/NumberFormatter.php @@ -244,10 +244,10 @@ abstract class NumberFormatter /** * @param string|null $locale The locale code. The only currently supported locale is "en" (or null using the default locale, i.e. "en") - * @param int $style Style of the formatting, one of the format style constants. + * @param int|null $style Style of the formatting, one of the format style constants. * The only supported styles are NumberFormatter::DECIMAL * and NumberFormatter::CURRENCY. - * @param string $pattern Not supported. A pattern string in case $style is NumberFormat::PATTERN_DECIMAL or + * @param string|null $pattern Not supported. A pattern string in case $style is NumberFormat::PATTERN_DECIMAL or * NumberFormat::PATTERN_RULEBASED. It must conform to the syntax * described in the ICU DecimalFormat or ICU RuleBasedNumberFormat documentation * @@ -281,10 +281,10 @@ abstract class NumberFormatter * Static constructor. * * @param string|null $locale The locale code. The only supported locale is "en" (or null using the default locale, i.e. "en") - * @param int $style Style of the formatting, one of the format style constants. + * @param int|null $style Style of the formatting, one of the format style constants. * The only currently supported styles are NumberFormatter::DECIMAL * and NumberFormatter::CURRENCY. - * @param string $pattern Not supported. A pattern string in case $style is NumberFormat::PATTERN_DECIMAL or + * @param string|null $pattern Not supported. A pattern string in case $style is NumberFormat::PATTERN_DECIMAL or * NumberFormat::PATTERN_RULEBASED. It must conform to the syntax * described in the ICU DecimalFormat or ICU RuleBasedNumberFormat documentation * @@ -485,9 +485,9 @@ abstract class NumberFormatter /** * Not supported. Parse a currency number. * - * @param string $value The value to parse - * @param string $currency Parameter to receive the currency name (reference) - * @param int $position Offset to begin the parsing on return this value will hold the offset at which the parsing ended + * @param string $value The value to parse + * @param string $currency Parameter to receive the currency name (reference) + * @param int|null $position Offset to begin the parsing on return this value will hold the offset at which the parsing ended * * @return float|false The parsed numeric value or false on error * diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/intl/ResourceBundle.php b/htdocs/core/modules/facture/doc/vendor/symfony/intl/ResourceBundle.php index 4f2ee32..c0ef5d1 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/intl/ResourceBundle.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/intl/ResourceBundle.php @@ -32,13 +32,13 @@ abstract class ResourceBundle * * @see BundleEntryReaderInterface::readEntry() * - * @param string[] $indices The indices to read from the bundle - * @param string $locale The locale to read - * @param bool $fallback Whether to merge the value with the value from - * the fallback locale (e.g. "en" for "en_GB"). - * Only applicable if the result is multivalued - * (i.e. array or \ArrayAccess) or cannot be found - * in the requested locale. + * @param string[] $indices The indices to read from the bundle + * @param string|null $locale The locale to read + * @param bool $fallback Whether to merge the value with the value from + * the fallback locale (e.g. "en" for "en_GB"). + * Only applicable if the result is multivalued + * (i.e. array or \ArrayAccess) or cannot be found + * in the requested locale. * * @return mixed returns an array or {@link \ArrayAccess} instance for * complex data and a scalar value for simple data diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/options-resolver/LICENSE b/htdocs/core/modules/facture/doc/vendor/symfony/options-resolver/LICENSE index 88bf75b..0138f8f 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/options-resolver/LICENSE +++ b/htdocs/core/modules/facture/doc/vendor/symfony/options-resolver/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2022 Fabien Potencier +Copyright (c) 2004-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/property-access/LICENSE b/htdocs/core/modules/facture/doc/vendor/symfony/property-access/LICENSE index 88bf75b..0138f8f 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/property-access/LICENSE +++ b/htdocs/core/modules/facture/doc/vendor/symfony/property-access/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2022 Fabien Potencier +Copyright (c) 2004-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/property-info/Extractor/PhpDocExtractor.php b/htdocs/core/modules/facture/doc/vendor/symfony/property-info/Extractor/PhpDocExtractor.php index 0f2fba5..2cecfcf 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/property-info/Extractor/PhpDocExtractor.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/property-info/Extractor/PhpDocExtractor.php @@ -60,7 +60,7 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property public function __construct(DocBlockFactoryInterface $docBlockFactory = null, array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null) { if (!class_exists(DocBlockFactory::class)) { - throw new \LogicException(sprintf('Unable to use the "%s" class as the "phpdocumentor/reflection-docblock" package is not installed.', __CLASS__)); + throw new \LogicException(sprintf('Unable to use the "%s" class as the "phpdocumentor/reflection-docblock" package is not installed. Try running composer require "phpdocumentor/reflection-docblock".', __CLASS__)); } $this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance(); @@ -200,7 +200,7 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property } } - if (!isset($types[0])) { + if (!isset($types[0]) || [] === $types[0]) { return null; } diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/property-info/Extractor/PhpStanExtractor.php b/htdocs/core/modules/facture/doc/vendor/symfony/property-info/Extractor/PhpStanExtractor.php index f833731..52a43d1 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/property-info/Extractor/PhpStanExtractor.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/property-info/Extractor/PhpStanExtractor.php @@ -11,6 +11,7 @@ namespace Symfony\Component\PropertyInfo\Extractor; +use phpDocumentor\Reflection\Types\ContextFactory; use PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode; @@ -59,6 +60,14 @@ final class PhpStanExtractor implements PropertyTypeExtractorInterface, Construc */ public function __construct(array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null) { + if (!class_exists(ContextFactory::class)) { + throw new \LogicException(sprintf('Unable to use the "%s" class as the "phpdocumentor/type-resolver" package is not installed. Try running composer require "phpdocumentor/type-resolver".', __CLASS__)); + } + + if (!class_exists(PhpDocParser::class)) { + throw new \LogicException(sprintf('Unable to use the "%s" class as the "phpstan/phpdoc-parser" package is not installed. Try running composer require "phpstan/phpdoc-parser".', __CLASS__)); + } + $this->phpStanTypeHelper = new PhpStanTypeHelper(); $this->mutatorPrefixes = $mutatorPrefixes ?? ReflectionExtractor::$defaultMutatorPrefixes; $this->accessorPrefixes = $accessorPrefixes ?? ReflectionExtractor::$defaultAccessorPrefixes; diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/property-info/LICENSE b/htdocs/core/modules/facture/doc/vendor/symfony/property-info/LICENSE index 4e90b1b..6e3afce 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/property-info/LICENSE +++ b/htdocs/core/modules/facture/doc/vendor/symfony/property-info/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2022 Fabien Potencier +Copyright (c) 2015-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/property-info/Util/PhpDocTypeHelper.php b/htdocs/core/modules/facture/doc/vendor/symfony/property-info/Util/PhpDocTypeHelper.php index c4a2edb..2c858c3 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/property-info/Util/PhpDocTypeHelper.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/property-info/Util/PhpDocTypeHelper.php @@ -173,7 +173,7 @@ final class PhpDocTypeHelper case 'boolean': return 'bool'; - // real is not part of the PHPDoc standard, so we ignore it + // real is not part of the PHPDoc standard, so we ignore it case 'double': return 'float'; diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/string/AbstractUnicodeString.php b/htdocs/core/modules/facture/doc/vendor/symfony/string/AbstractUnicodeString.php index 1bc6f88..80b8326 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/string/AbstractUnicodeString.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/string/AbstractUnicodeString.php @@ -37,8 +37,8 @@ abstract class AbstractUnicodeString extends AbstractString private const ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"; // the subset of folded case mappings that is not in lower case mappings - private const FOLD_FROM = ['İ', 'µ', 'ſ', "\xCD\x85", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "\xE1\xBE\xBE", 'ß', 'İ', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ']; - private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', 'i̇', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'եւ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'aʾ', 'ss', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὰι', 'αι', 'άι', 'ᾶ', 'ᾶι', 'αι', 'ὴι', 'ηι', 'ήι', 'ῆ', 'ῆι', 'ηι', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ὼι', 'ωι', 'ώι', 'ῶ', 'ῶι', 'ωι', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'մն', 'մե', 'մի', 'վն', 'մխ']; + private const FOLD_FROM = ['İ', 'µ', 'ſ', "\xCD\x85", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "\xE1\xBE\xBE", 'ß', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ']; + private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'եւ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'aʾ', 'ss', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὰι', 'αι', 'άι', 'ᾶ', 'ᾶι', 'αι', 'ὴι', 'ηι', 'ήι', 'ῆ', 'ῆι', 'ηι', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ὼι', 'ωι', 'ώι', 'ῶ', 'ῶι', 'ωι', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'մն', 'մե', 'մի', 'վն', 'մխ']; // the subset of upper case mappings that map one code point to many code points private const UPPER_FROM = ['ß', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'և', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ', 'ʼn', 'ΐ', 'ΰ', 'ǰ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾶ', 'ῆ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ῶ']; diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/string/LICENSE b/htdocs/core/modules/facture/doc/vendor/symfony/string/LICENSE index 9c907a4..f37c76b 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/string/LICENSE +++ b/htdocs/core/modules/facture/doc/vendor/symfony/string/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2022 Fabien Potencier +Copyright (c) 2019-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/validator/Constraints/AtLeastOneOfValidator.php b/htdocs/core/modules/facture/doc/vendor/symfony/validator/Constraints/AtLeastOneOfValidator.php index 888f583..692b117 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/validator/Constraints/AtLeastOneOfValidator.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/validator/Constraints/AtLeastOneOfValidator.php @@ -31,7 +31,11 @@ class AtLeastOneOfValidator extends ConstraintValidator $validator = $this->context->getValidator(); - $messages = [$constraint->message]; + // Build a first violation to have the base message of the constraint translated + $baseMessageContext = clone $this->context; + $baseMessageContext->buildViolation($constraint->message)->addViolation(); + $baseViolations = $baseMessageContext->getViolations(); + $messages = [(string) $baseViolations->get(\count($baseViolations) - 1)->getMessage()]; foreach ($constraint->constraints as $key => $item) { if (!\in_array($this->context->getGroup(), $item->groups, true)) { diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/validator/Constraints/EmailValidator.php b/htdocs/core/modules/facture/doc/vendor/symfony/validator/Constraints/EmailValidator.php index ee78024..11fc7be 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/validator/Constraints/EmailValidator.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/validator/Constraints/EmailValidator.php @@ -16,6 +16,7 @@ use Egulias\EmailValidator\Validation\EmailValidation; use Egulias\EmailValidator\Validation\NoRFCWarningsValidation; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; +use Symfony\Component\Validator\Exception\LogicException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -71,7 +72,7 @@ class EmailValidator extends ConstraintValidator if (null === $constraint->mode) { if (Email::VALIDATION_MODE_STRICT === $this->defaultMode && !class_exists(EguliasEmailValidator::class)) { - throw new LogicException(sprintf('The "egulias/email-validator" component is required to make the "%s" constraint default to strict mode.', EguliasEmailValidator::class)); + throw new LogicException(sprintf('The "egulias/email-validator" component is required to make the "%s" constraint default to strict mode.', Email::class)); } $constraint->mode = $this->defaultMode; diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/validator/Constraints/IbanValidator.php b/htdocs/core/modules/facture/doc/vendor/symfony/validator/Constraints/IbanValidator.php index 215eb16..173cb66 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/validator/Constraints/IbanValidator.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/validator/Constraints/IbanValidator.php @@ -20,8 +20,6 @@ use Symfony\Component\Validator\Exception\UnexpectedValueException; * @author Manuel Reinhard * @author Michael Schummel * @author Bernhard Schussek - * - * @see http://www.michael-schummel.de/2007/10/05/iban-prufung-mit-php/ */ class IbanValidator extends ConstraintValidator { @@ -34,107 +32,135 @@ class IbanValidator extends ConstraintValidator * a BBAN (Basic Bank Account Number) which has a fixed length per country and, * included within it, a bank identifier with a fixed position and a fixed length per country * - * @see https://www.swift.com/sites/default/files/resources/iban_registry.pdf + * @see Resources/bin/sync-iban-formats.php + * @see https://www.swift.com/swift-resource/11971/download?language=en + * @see https://en.wikipedia.org/wiki/International_Bank_Account_Number */ private const FORMATS = [ + // auto-generated 'AD' => 'AD\d{2}\d{4}\d{4}[\dA-Z]{12}', // Andorra - 'AE' => 'AE\d{2}\d{3}\d{16}', // United Arab Emirates + 'AE' => 'AE\d{2}\d{3}\d{16}', // United Arab Emirates (The) 'AL' => 'AL\d{2}\d{8}[\dA-Z]{16}', // Albania 'AO' => 'AO\d{2}\d{21}', // Angola 'AT' => 'AT\d{2}\d{5}\d{11}', // Austria - 'AX' => 'FI\d{2}\d{6}\d{7}\d{1}', // Aland Islands + 'AX' => 'FI\d{2}\d{3}\d{11}', // Finland 'AZ' => 'AZ\d{2}[A-Z]{4}[\dA-Z]{20}', // Azerbaijan 'BA' => 'BA\d{2}\d{3}\d{3}\d{8}\d{2}', // Bosnia and Herzegovina 'BE' => 'BE\d{2}\d{3}\d{7}\d{2}', // Belgium - 'BF' => 'BF\d{2}\d{23}', // Burkina Faso + 'BF' => 'BF\d{2}[\dA-Z]{2}\d{22}', // Burkina Faso 'BG' => 'BG\d{2}[A-Z]{4}\d{4}\d{2}[\dA-Z]{8}', // Bulgaria 'BH' => 'BH\d{2}[A-Z]{4}[\dA-Z]{14}', // Bahrain - 'BI' => 'BI\d{2}\d{12}', // Burundi - 'BJ' => 'BJ\d{2}[A-Z]{1}\d{23}', // Benin - 'BY' => 'BY\d{2}[\dA-Z]{4}\d{4}[\dA-Z]{16}', // Belarus - https://bank.codes/iban/structure/belarus/ - 'BL' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Saint Barthelemy - 'BR' => 'BR\d{2}\d{8}\d{5}\d{10}[A-Z][\dA-Z]', // Brazil - 'CG' => 'CG\d{2}\d{23}', // Congo + 'BI' => 'BI\d{2}\d{5}\d{5}\d{11}\d{2}', // Burundi + 'BJ' => 'BJ\d{2}[\dA-Z]{2}\d{22}', // Benin + 'BL' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France + 'BR' => 'BR\d{2}\d{8}\d{5}\d{10}[A-Z]{1}[\dA-Z]{1}', // Brazil + 'BY' => 'BY\d{2}[\dA-Z]{4}\d{4}[\dA-Z]{16}', // Republic of Belarus + 'CF' => 'CF\d{2}\d{23}', // Central African Republic + 'CG' => 'CG\d{2}\d{23}', // Congo, Republic of the 'CH' => 'CH\d{2}\d{5}[\dA-Z]{12}', // Switzerland - 'CI' => 'CI\d{2}[A-Z]{1}\d{23}', // Ivory Coast - 'CM' => 'CM\d{2}\d{23}', // Cameron - 'CR' => 'CR\d{2}0\d{3}\d{14}', // Costa Rica - 'CV' => 'CV\d{2}\d{21}', // Cape Verde + 'CI' => 'CI\d{2}[A-Z]{1}\d{23}', // Côte d'Ivoire + 'CM' => 'CM\d{2}\d{23}', // Cameroon + 'CR' => 'CR\d{2}\d{4}\d{14}', // Costa Rica + 'CV' => 'CV\d{2}\d{21}', // Cabo Verde 'CY' => 'CY\d{2}\d{3}\d{5}[\dA-Z]{16}', // Cyprus - 'CZ' => 'CZ\d{2}\d{20}', // Czech Republic + 'CZ' => 'CZ\d{2}\d{4}\d{6}\d{10}', // Czechia 'DE' => 'DE\d{2}\d{8}\d{10}', // Germany + 'DJ' => 'DJ\d{2}\d{5}\d{5}\d{11}\d{2}', // Djibouti + 'DK' => 'DK\d{2}\d{4}\d{9}\d{1}', // Denmark 'DO' => 'DO\d{2}[\dA-Z]{4}\d{20}', // Dominican Republic - 'DK' => 'DK\d{2}\d{4}\d{10}', // Denmark - 'DZ' => 'DZ\d{2}\d{20}', // Algeria + 'DZ' => 'DZ\d{2}\d{22}', // Algeria 'EE' => 'EE\d{2}\d{2}\d{2}\d{11}\d{1}', // Estonia - 'ES' => 'ES\d{2}\d{4}\d{4}\d{1}\d{1}\d{10}', // Spain (also includes Canary Islands, Ceuta and Melilla) - 'FI' => 'FI\d{2}\d{6}\d{7}\d{1}', // Finland + 'EG' => 'EG\d{2}\d{4}\d{4}\d{17}', // Egypt + 'ES' => 'ES\d{2}\d{4}\d{4}\d{1}\d{1}\d{10}', // Spain + 'FI' => 'FI\d{2}\d{3}\d{11}', // Finland 'FO' => 'FO\d{2}\d{4}\d{9}\d{1}', // Faroe Islands 'FR' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France - 'GF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // French Guyana - 'GB' => 'GB\d{2}[A-Z]{4}\d{6}\d{8}', // United Kingdom of Great Britain and Northern Ireland + 'GA' => 'GA\d{2}\d{23}', // Gabon + 'GB' => 'GB\d{2}[A-Z]{4}\d{6}\d{8}', // United Kingdom 'GE' => 'GE\d{2}[A-Z]{2}\d{16}', // Georgia + 'GF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France + 'GG' => 'GB\d{2}[A-Z]{4}\d{6}\d{8}', // United Kingdom 'GI' => 'GI\d{2}[A-Z]{4}[\dA-Z]{15}', // Gibraltar 'GL' => 'GL\d{2}\d{4}\d{9}\d{1}', // Greenland - 'GP' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Guadeloupe + 'GP' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France + 'GQ' => 'GQ\d{2}\d{23}', // Equatorial Guinea 'GR' => 'GR\d{2}\d{3}\d{4}[\dA-Z]{16}', // Greece 'GT' => 'GT\d{2}[\dA-Z]{4}[\dA-Z]{20}', // Guatemala + 'GW' => 'GW\d{2}[\dA-Z]{2}\d{19}', // Guinea-Bissau + 'HN' => 'HN\d{2}[A-Z]{4}\d{20}', // Honduras 'HR' => 'HR\d{2}\d{7}\d{10}', // Croatia 'HU' => 'HU\d{2}\d{3}\d{4}\d{1}\d{15}\d{1}', // Hungary 'IE' => 'IE\d{2}[A-Z]{4}\d{6}\d{8}', // Ireland 'IL' => 'IL\d{2}\d{3}\d{3}\d{13}', // Israel + 'IM' => 'GB\d{2}[A-Z]{4}\d{6}\d{8}', // United Kingdom + 'IQ' => 'IQ\d{2}[A-Z]{4}\d{3}\d{12}', // Iraq 'IR' => 'IR\d{2}\d{22}', // Iran 'IS' => 'IS\d{2}\d{4}\d{2}\d{6}\d{10}', // Iceland 'IT' => 'IT\d{2}[A-Z]{1}\d{5}\d{5}[\dA-Z]{12}', // Italy + 'JE' => 'GB\d{2}[A-Z]{4}\d{6}\d{8}', // United Kingdom 'JO' => 'JO\d{2}[A-Z]{4}\d{4}[\dA-Z]{18}', // Jordan - 'KW' => 'KW\d{2}[A-Z]{4}\d{22}', // KUWAIT + 'KM' => 'KM\d{2}\d{23}', // Comoros + 'KW' => 'KW\d{2}[A-Z]{4}[\dA-Z]{22}', // Kuwait 'KZ' => 'KZ\d{2}\d{3}[\dA-Z]{13}', // Kazakhstan - 'LB' => 'LB\d{2}\d{4}[\dA-Z]{20}', // LEBANON - 'LI' => 'LI\d{2}\d{5}[\dA-Z]{12}', // Liechtenstein (Principality of) + 'LB' => 'LB\d{2}\d{4}[\dA-Z]{20}', // Lebanon + 'LC' => 'LC\d{2}[A-Z]{4}[\dA-Z]{24}', // Saint Lucia + 'LI' => 'LI\d{2}\d{5}[\dA-Z]{12}', // Liechtenstein 'LT' => 'LT\d{2}\d{5}\d{11}', // Lithuania 'LU' => 'LU\d{2}\d{3}[\dA-Z]{13}', // Luxembourg 'LV' => 'LV\d{2}[A-Z]{4}[\dA-Z]{13}', // Latvia + 'LY' => 'LY\d{2}\d{3}\d{3}\d{15}', // Libya + 'MA' => 'MA\d{2}\d{24}', // Morocco 'MC' => 'MC\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Monaco 'MD' => 'MD\d{2}[\dA-Z]{2}[\dA-Z]{18}', // Moldova 'ME' => 'ME\d{2}\d{3}\d{13}\d{2}', // Montenegro - 'MF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Saint Martin (French part) + 'MF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France 'MG' => 'MG\d{2}\d{23}', // Madagascar - 'MK' => 'MK\d{2}\d{3}[\dA-Z]{10}\d{2}', // Macedonia, Former Yugoslav Republic of - 'ML' => 'ML\d{2}[A-Z]{1}\d{23}', // Mali - 'MQ' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Martinique + 'MK' => 'MK\d{2}\d{3}[\dA-Z]{10}\d{2}', // Macedonia + 'ML' => 'ML\d{2}[\dA-Z]{2}\d{22}', // Mali + 'MQ' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France 'MR' => 'MR\d{2}\d{5}\d{5}\d{11}\d{2}', // Mauritania 'MT' => 'MT\d{2}[A-Z]{4}\d{5}[\dA-Z]{18}', // Malta 'MU' => 'MU\d{2}[A-Z]{4}\d{2}\d{2}\d{12}\d{3}[A-Z]{3}', // Mauritius 'MZ' => 'MZ\d{2}\d{21}', // Mozambique - 'NC' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // New Caledonia - 'NL' => 'NL\d{2}[A-Z]{4}\d{10}', // The Netherlands + 'NC' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France + 'NE' => 'NE\d{2}[A-Z]{2}\d{22}', // Niger + 'NI' => 'NI\d{2}[A-Z]{4}\d{24}', // Nicaragua + 'NL' => 'NL\d{2}[A-Z]{4}\d{10}', // Netherlands (The) 'NO' => 'NO\d{2}\d{4}\d{6}\d{1}', // Norway - 'PF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // French Polynesia + 'PF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France 'PK' => 'PK\d{2}[A-Z]{4}[\dA-Z]{16}', // Pakistan 'PL' => 'PL\d{2}\d{8}\d{16}', // Poland - 'PM' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Saint Pierre et Miquelon + 'PM' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France 'PS' => 'PS\d{2}[A-Z]{4}[\dA-Z]{21}', // Palestine, State of - 'PT' => 'PT\d{2}\d{4}\d{4}\d{11}\d{2}', // Portugal (plus Azores and Madeira) + 'PT' => 'PT\d{2}\d{4}\d{4}\d{11}\d{2}', // Portugal 'QA' => 'QA\d{2}[A-Z]{4}[\dA-Z]{21}', // Qatar - 'RE' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Reunion + 'RE' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France 'RO' => 'RO\d{2}[A-Z]{4}[\dA-Z]{16}', // Romania 'RS' => 'RS\d{2}\d{3}\d{13}\d{2}', // Serbia + 'RU' => 'RU\d{2}\d{9}\d{5}[\dA-Z]{15}', // Russia 'SA' => 'SA\d{2}\d{2}[\dA-Z]{18}', // Saudi Arabia + 'SC' => 'SC\d{2}[A-Z]{4}\d{2}\d{2}\d{16}[A-Z]{3}', // Seychelles + 'SD' => 'SD\d{2}\d{2}\d{12}', // Sudan 'SE' => 'SE\d{2}\d{3}\d{16}\d{1}', // Sweden 'SI' => 'SI\d{2}\d{5}\d{8}\d{2}', // Slovenia - 'SK' => 'SK\d{2}\d{4}\d{6}\d{10}', // Slovak Republic + 'SK' => 'SK\d{2}\d{4}\d{6}\d{10}', // Slovakia 'SM' => 'SM\d{2}[A-Z]{1}\d{5}\d{5}[\dA-Z]{12}', // San Marino - 'SN' => 'SN\d{2}[A-Z]{1}\d{23}', // Senegal - 'TF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // French Southern Territories + 'SN' => 'SN\d{2}[A-Z]{2}\d{22}', // Senegal + 'SO' => 'SO\d{2}\d{4}\d{3}\d{12}', // Somalia + 'ST' => 'ST\d{2}\d{4}\d{4}\d{11}\d{2}', // Sao Tome and Principe + 'SV' => 'SV\d{2}[A-Z]{4}\d{20}', // El Salvador + 'TD' => 'TD\d{2}\d{23}', // Chad + 'TF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France + 'TG' => 'TG\d{2}[A-Z]{2}\d{22}', // Togo 'TL' => 'TL\d{2}\d{3}\d{14}\d{2}', // Timor-Leste 'TN' => 'TN\d{2}\d{2}\d{3}\d{13}\d{2}', // Tunisia - 'TR' => 'TR\d{2}\d{5}[\dA-Z]{1}[\dA-Z]{16}', // Turkey + 'TR' => 'TR\d{2}\d{5}\d{1}[\dA-Z]{16}', // Turkey 'UA' => 'UA\d{2}\d{6}[\dA-Z]{19}', // Ukraine 'VA' => 'VA\d{2}\d{3}\d{15}', // Vatican City State - 'VG' => 'VG\d{2}[A-Z]{4}\d{16}', // Virgin Islands, British - 'WF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Wallis and Futuna Islands - 'XK' => 'XK\d{2}\d{4}\d{10}\d{2}', // Republic of Kosovo - 'YT' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Mayotte + 'VG' => 'VG\d{2}[A-Z]{4}\d{16}', // Virgin Islands + 'WF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France + 'XK' => 'XK\d{2}\d{4}\d{10}\d{2}', // Kosovo + 'YT' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France ]; /** diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/validator/LICENSE b/htdocs/core/modules/facture/doc/vendor/symfony/validator/LICENSE index 88bf75b..0138f8f 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/validator/LICENSE +++ b/htdocs/core/modules/facture/doc/vendor/symfony/validator/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2022 Fabien Potencier +Copyright (c) 2004-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/validator/Test/ConstraintValidatorTestCase.php b/htdocs/core/modules/facture/doc/vendor/symfony/validator/Test/ConstraintValidatorTestCase.php index bee4639..073dd17 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/validator/Test/ConstraintValidatorTestCase.php +++ b/htdocs/core/modules/facture/doc/vendor/symfony/validator/Test/ConstraintValidatorTestCase.php @@ -130,16 +130,22 @@ abstract class ConstraintValidatorTestCase extends TestCase $context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath); $context->setConstraint($this->constraint); - $contextualValidator = $this->getMockBuilder(AssertingContextualValidator::class) - ->setConstructorArgs([$context]) - ->setMethods([ - 'atPath', - 'validate', - 'validateProperty', - 'validatePropertyValue', - 'getViolations', - ]) - ->getMock(); + $contextualValidatorMockBuilder = $this->getMockBuilder(AssertingContextualValidator::class) + ->setConstructorArgs([$context]); + $contextualValidatorMethods = [ + 'atPath', + 'validate', + 'validateProperty', + 'validatePropertyValue', + 'getViolations', + ]; + // PHPUnit 10 removed MockBuilder::setMethods() + if (method_exists($contextualValidatorMockBuilder, 'onlyMethods')) { + $contextualValidatorMockBuilder->onlyMethods($contextualValidatorMethods); + } else { + $contextualValidatorMockBuilder->setMethods($contextualValidatorMethods); + } + $contextualValidator = $contextualValidatorMockBuilder->getMock(); $contextualValidator->expects($this->any()) ->method('atPath') ->willReturnCallback(function ($path) use ($contextualValidator) { diff --git a/htdocs/core/modules/facture/doc/vendor/symfony/validator/composer.json b/htdocs/core/modules/facture/doc/vendor/symfony/validator/composer.json index 4799c7b..019a46f 100644 --- a/htdocs/core/modules/facture/doc/vendor/symfony/validator/composer.json +++ b/htdocs/core/modules/facture/doc/vendor/symfony/validator/composer.json @@ -43,7 +43,7 @@ "symfony/translation": "^4.4|^5.0|^6.0", "doctrine/annotations": "^1.13|^2", "doctrine/cache": "^1.11|^2.0", - "egulias/email-validator": "^2.1.10|^3" + "egulias/email-validator": "^2.1.10|^3|^4" }, "conflict": { "doctrine/annotations": "<1.13", From 8918230c1a1eb8dd1b4356ecd7bbe129622e04e1 Mon Sep 17 00:00:00 2001 From: Benoit Vianin Date: Sun, 12 Mar 2023 10:16:18 +0100 Subject: [PATCH 3/7] Add check if IBAN is set before adding the QR part --- htdocs/core/modules/facture/doc/pdf_swissqr.modules.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php b/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php index 8909773..185c249 100644 --- a/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php @@ -855,9 +855,12 @@ class pdf_swissqr extends ModelePDFFactures } // Add page for the Swiss QR-invoice - $pdf->AddPage(); - $this->_pagehead($pdf, $object, 0, $outputlangs); - $this->qrinvoice($pdf, $object, $outputlangs, $conf); + if (isset($object->iban)) + { + $pdf->AddPage(); + $this->_pagehead($pdf, $object, 0, $outputlangs); + $this->qrinvoice($pdf, $object, $outputlangs, $conf); + } $pdf->Close(); From 298de15213bc2b3d8df0258836f6e94209c75941 Mon Sep 17 00:00:00 2001 From: Benoit Vianin Date: Sun, 12 Mar 2023 10:51:48 +0100 Subject: [PATCH 4/7] Remove all non numeric character form invoice ref and set reference to 0 for PROV invoice --- htdocs/core/modules/facture/doc/pdf_swissqr.modules.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php b/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php index 185c249..fdee638 100644 --- a/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php @@ -928,15 +928,13 @@ class pdf_swissqr extends ModelePDFFactures $ref = $object->ref; - if (str_contains($ref, 'FA')) + if (str_contains($ref, 'PROV')) { - // Remove FA and - from the invoice reference - $ref = str_replace('FA', '', $ref); - $ref = str_replace('-', '', $ref); - } else { $ref = 0; } + $ref = preg_replace('/[^0-9]/', '', $ref); + // Add payment reference for QR-IBAN // This is what you will need to identify incoming payments. $referenceNumber = QrBill\Reference\QrPaymentReferenceGenerator::generate( From f23a1b40b0e8d2a8a91fce7905ec7be46f96d21e Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Sun, 12 Mar 2023 16:30:19 +0100 Subject: [PATCH 5/7] fix: force QR block to have black text In case of coloured watermark, this was not reset to black --- htdocs/core/modules/facture/doc/pdf_swissqr.modules.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php b/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php index fefb8df..759662f 100644 --- a/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php @@ -857,6 +857,7 @@ class pdf_swissqr extends ModelePDFFactures // Add page for the Swiss QR-invoice $pdf->AddPage(); $this->_pagehead($pdf, $object, 0, $outputlangs); + $pdf->SetTextColor(0, 0, 0); $this->qrinvoice($pdf, $object, $outputlangs); $pdf->Close(); From 2b253071005c66e28a813e198eddaf60023abda3 Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Sun, 12 Mar 2023 16:54:12 +0100 Subject: [PATCH 6/7] fix: do not allow Dolibarr's SwitzerlandQR --- htdocs/core/modules/facture/doc/pdf_swissqr.modules.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php b/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php index fefb8df..696945a 100644 --- a/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php @@ -460,7 +460,8 @@ class pdf_swissqr extends ModelePDFFactures if (! empty($conf->global->INVOICE_ADD_ZATCA_QR_CODE)) { $qrcodestring = $object->buildZATCAQRString(); } elseif (! empty($conf->global->INVOICE_ADD_SWISS_QR_CODE)) { - $qrcodestring = $object->buildSwitzerlandQRString(); + // Do not allow another QR code; this module is about having the legit one. + // $qrcodestring = $object->buildSwitzerlandQRString(); } if ($qrcodestring) { $qrcodecolor = array('25', '25', '25'); From 39b340f874b238487b1bdc54df13a8e9e51b42d1 Mon Sep 17 00:00:00 2001 From: Benoit Vianin Date: Sun, 11 Aug 2024 13:08:06 +0200 Subject: [PATCH 7/7] Fix balance for QR --- .../modules/facture/doc/pdf_swissqr.modules.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php b/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php index dfe29e0..04cf29f 100644 --- a/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_swissqr.modules.php @@ -9,7 +9,7 @@ * Copyright (C) 2015 Marcos García * Copyright (C) 2017-2018 Ferran Marcet * Copyright (C) 2018-2020 Frédéric France - * Copyright (C) 2022-2023 Sinabe Sàrl, Benoit Vianin + * Copyright (C) 2022-2024 Sinabe Sàrl, Benoit Vianin * * 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 @@ -861,7 +861,7 @@ class pdf_swissqr extends ModelePDFFactures $pdf->AddPage(); $this->_pagehead($pdf, $object, 0, $outputlangs); $pdf->SetTextColor(0, 0, 0); - $this->qrinvoice($pdf, $object, $outputlangs, $conf); + $this->qrinvoice($pdf, $object, $deja_regle, $outputlangs, $conf); } $pdf->Close(); @@ -905,7 +905,7 @@ class pdf_swissqr extends ModelePDFFactures * @param object the Dolibarr langs object * @param object the Dolibarr configuration */ - protected function qrinvoice($pdf, $object, $langs, $conf) + protected function qrinvoice($pdf, $object, $deja_regle, $langs, $conf) { // Create a new instance of QrBill, containing default headers with fixed values $qrBill = QrBill\QrBill::create(); @@ -970,12 +970,17 @@ class pdf_swissqr extends ModelePDFFactures 'CH' )); + // Calculate total with taxes + $creditnoteamount = $object->getSumCreditNotesUsed((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? 1 : 0); // Warning, this also include excess received + $depositsamount = $object->getSumDepositsUsed((!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? 1 : 0); + $balance = price2num($object->total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT'); + // Add payment amount information // What amount is to be paid? $qrBill->setPaymentAmountInformation( QrBill\DataGroup\Element\PaymentAmountInformation::create( 'CHF', - $object->total_ttc + $balance )); // Optionally, add some human-readable information about what the bill is for.