/**
  *  Function to build pdf onto disk
  *
  *  @param		Object		$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
  */
 function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
 {
     global $user, $langs, $conf, $mysoc, $db, $hookmanager;
     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';
     }
     $outputlangs->load("main");
     $outputlangs->load("dict");
     $outputlangs->load("trips");
     $outputlangs->load("project");
     $nblignes = count($object->lines);
     if ($conf->expensereport->dir_output) {
         // Definition of $dir and $file
         if ($object->specimen) {
             $dir = $conf->expensereport->dir_output;
             $file = $dir . "/SPECIMEN.pdf";
         } else {
             $objectref = dol_sanitizeFileName($object->ref);
             $dir = $conf->expensereport->dir_output . "/" . $objectref;
             $file = $dir . "/" . $objectref . ".pdf";
         }
         if (!file_exists($dir)) {
             if (dol_mkdir($dir) < 0) {
                 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
                 return 0;
             }
         }
         if (isset($object->lignes) && !isset($object->lines)) {
             $object->lines = $object->lignes;
         }
         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
             // Create pdf instance
             $pdf = pdf_getInstance($this->format);
             $default_font_size = pdf_getPDFFontSize($outputlangs);
             // Must be after pdf_getInstance
             $heightforinfotot = 50;
             // Height reserved to output the info and total part
             $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)
             $pdf->SetAutoPageBreak(1, 0);
             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_DISABLE_FPDI) && !empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) {
                 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output . '/' . $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_number));
             $pdf->SetSubject($outputlangs->transnoentities("Trips"));
             $pdf->SetCreator("Dolibarr " . DOL_VERSION);
             $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
             $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref) . " " . $outputlangs->transnoentities("Trips"));
             if (!empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) {
                 $pdf->SetCompression(false);
             }
             $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite);
             // Left, Top, Right
             // Positionne $this->atleastonediscount si on a au moins une remise
             for ($i = 0; $i < $nblignes; $i++) {
                 if ($object->lines[$i]->remise_percent) {
                     $this->atleastonediscount++;
                 }
             }
             // New page
             $pdf->AddPage();
             if (!empty($tplidx)) {
                 $pdf->useTemplate($tplidx);
             }
             $pagenb++;
             $this->_pagehead($pdf, $object, 1, $outputlangs);
             $pdf->SetFont('', '', $default_font_size - 1);
             $pdf->MultiCell(0, 3, '');
             // Set interline to 3
             $pdf->SetTextColor(0, 0, 0);
             $tab_top = 95;
             $tab_top_newpage = empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD) ? 95 : 10;
             $tab_height = 110;
             $tab_height_newpage = 110;
             // Show 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);
                     }
                 }
             }
             if ($notetoshow) {
                 $tab_top = 95;
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->writeHTMLCell(190, 3, $this->posxpiece - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
                 $nexY = $pdf->GetY();
                 $height_note = $nexY - $tab_top;
                 // Rect prend une longueur en 3eme param
                 $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_height = $tab_height - $height_note;
                 $tab_top = $nexY + 6;
             } else {
                 $height_note = 0;
             }
             $iniY = $tab_top + 7;
             $curY = $tab_top + 7;
             $nexY = $tab_top + 7;
             // Loop on each lines
             for ($i = 0; $i < $nblignes; $i++) {
                 $piece_comptable = $i + 1;
                 $curY = $nexY;
                 $pdf->SetFont('', '', $default_font_size - 1);
                 // Into loop to work with multipage
                 $pdf->SetTextColor(0, 0, 0);
                 $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();
                 // Description of product line
                 $curX = $this->posxdesc - 1;
                 $showpricebeforepagebreak = 1;
                 // Accountancy piece
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->writeHTMLCell($this->posxcomment - $this->posxpiece - 1, 3, $this->posxpiece - 1, $curY, $piece_comptable, 0, 1);
                 // Comments
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->SetXY($this->posxcomment, $curY);
                 $pdf->writeHTMLCell($this->posxdate - $this->posxdesc - 1, 3, $this->posxdesc - 1, $curY, $object->lines[$i]->comments, 0, 1);
                 //nexY
                 $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.
                 // Date
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->SetXY($this->posxdate, $curY);
                 $pdf->MultiCell($this->posxtype - $this->posxdate - 1, 3, dol_print_date($object->lines[$i]->date, "day", false, $outpulangs), 0, 'C');
                 // Type
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->SetXY($this->posxtype, $curY);
                 $pdf->MultiCell($this->posxprojet - $this->posxtype - 1, 3, $outputlangs->transnoentities($object->lines[$i]->type_fees_code), 0, 'C');
                 // Project
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->SetXY($this->posxprojet, $curY);
                 $pdf->MultiCell($this->posxtva - $this->posxprojet - 1, 3, $object->lines[$i]->projet_ref, 0, 'C');
                 // VAT Rate
                 if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) {
                     $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
                     $pdf->SetFont('', '', $default_font_size - 1);
                     $pdf->SetXY($this->posxtva, $curY);
                     $pdf->MultiCell($this->posxup - $this->posxtva - 1, 3, $vat_rate, 0, 'R');
                 }
                 // Unit price
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->SetXY($this->posxup, $curY);
                 $pdf->MultiCell($this->posxqty - $this->posxup - 1, 3, price($object->lines[$i]->value_unit), 0, 'R');
                 // Quantity
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->SetXY($this->posxqty, $curY);
                 $pdf->MultiCell($this->postotalttc - $this->posxqty, 3, $object->lines[$i]->qty, 0, 'C');
                 // Total with all taxes
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->SetXY($this->postotalttc - 1, $curY);
                 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalttc, 3, price($object->lines[$i]->total_ttc), 0, 'R');
                 $nexY += 5;
                 // Cherche nombre de lignes a venir pour savoir si place suffisante
                 if ($i < $nblignes - 1) {
                     //on recupere la description du produit suivant
                     $follow_descproduitservice = $object->lines[$i + 1]->desc;
                     //on compte le nombre de ligne afin de verifier la place disponible (largeur de ligne 52 caracteres)
                     $nblineFollowDesc = dol_nboflines_bis($follow_descproduitservice, 52, $outputlangs->charset_output) * 4;
                     // Et si on affiche dates de validite, on ajoute encore une ligne
                     if ($object->lines[$i]->date_start && $object->lines[$i]->date_end) {
                         $nblineFollowDesc += 4;
                     }
                 } else {
                     $nblineFollowDesc = 0;
                 }
                 $nexY += 2;
                 // Passe espace entre les lignes
                 // 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);
                     } else {
                         $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
                     }
                     $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 (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);
                     } else {
                         $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
                     }
                     $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);
                 $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);
                 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
             }
             // Show total area box
             $posy = $bottomlasttab + 5;
             //$nexY+95;
             $pdf->SetXY(100, $posy);
             $pdf->MultiCell(60, 5, $outputlangs->transnoentities("TotalHT"), 1, 'L');
             $pdf->SetXY(160, $posy);
             $pdf->MultiCell($this->page_largeur - $this->marge_gauche - 160, 5, price($object->total_ht), 1, 'R');
             $pdf->SetFillColor(248, 248, 248);
             if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) {
                 $posy += 5;
                 $pdf->SetXY(100, $posy);
                 $pdf->SetTextColor(0, 0, 60);
                 $pdf->MultiCell(60, 5, $outputlangs->transnoentities("TotalVAT"), 1, 'L');
                 $pdf->SetXY(160, $posy);
                 $pdf->MultiCell($this->page_largeur - $this->marge_gauche - 160, 5, price($object->total_tva), 1, 'R');
             }
             $posy += 5;
             $pdf->SetXY(100, $posy);
             $pdf->SetFont('', 'B', 10);
             $pdf->SetTextColor(0, 0, 60);
             $pdf->MultiCell(60, 5, $outputlangs->transnoentities("TotalTTC"), 1, 'L');
             $pdf->SetXY(160, $posy);
             $pdf->MultiCell($this->page_largeur - $this->marge_gauche - 160, 5, price($object->total_ttc), 1, 'R');
             // Pied de page
             $this->_pagefoot($pdf, $object, $outputlangs);
             if (method_exists($pdf, 'AliasNbPages')) {
                 $pdf->AliasNbPages();
             }
             $pdf->Close();
             $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 (!empty($conf->global->MAIN_UMASK)) {
                 @chmod($file, octdec($conf->global->MAIN_UMASK));
             }
             return 1;
             // Pas d'erreur
         } else {
             $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
             return 0;
         }
     } else {
         $this->error = $langs->trans("ErrorConstantNotDefined", "EXPENSEREPORT_OUTPUTDIR");
         return 0;
     }
     $this->error = $langs->trans("ErrorUnknown");
     return 0;
     // Erreur par defaut
 }
 /**
  *  Function to build pdf onto disk
  *
  *  @param		Object		$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
  */
 function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
 {
     global $user, $langs, $conf, $mysoc, $db, $hookmanager;
     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';
     }
     $outputlangs->load("main");
     $outputlangs->load("dict");
     $outputlangs->load("companies");
     $outputlangs->load("bills");
     $outputlangs->load("products");
     $nblignes = 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 < $nblignes; $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();
         $amount_credit_notes_included = $object->getSumCreditNotesUsed();
         $amount_deposits_included = $object->getSumDepositsUsed();
         // Definition of $dir and $file
         if ($object->specimen) {
             $dir = $conf->facture->dir_output;
             $file = $dir . "/SPECIMEN.pdf";
         } else {
             $objectref = dol_sanitizeFileName($object->ref);
             $dir = $conf->facture->dir_output . "/" . $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 nblignes with the new facture lines content after hook
             $nblignes = count($object->lines);
             // Create pdf instance
             $pdf = pdf_getInstance($this->format);
             $default_font_size = pdf_getPDFFontSize($outputlangs);
             // Must be after pdf_getInstance
             $heightforinfotot = 50;
             // Height reserved to output the info and total part
             $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)
             $pdf->SetAutoPageBreak(1, 0);
             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_DISABLE_FPDI) && !empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) {
                 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output . '/' . $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("Invoice"));
             $pdf->SetCreator("Dolibarr " . DOL_VERSION);
             $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
             $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref) . " " . $outputlangs->transnoentities("Invoice"));
             if (!empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) {
                 $pdf->SetCompression(false);
             }
             $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite);
             // Left, Top, Right
             // Positionne $this->atleastonediscount si on a au moins une remise
             for ($i = 0; $i < $nblignes; $i++) {
                 if ($object->lines[$i]->remise_percent) {
                     $this->atleastonediscount++;
                 }
             }
             if (empty($this->atleastonediscount) && empty($conf->global->PRODUCT_USE_UNITS)) {
                 $this->posxpicture += $this->postotalht - $this->posxdiscount;
                 $this->posxtva += $this->postotalht - $this->posxdiscount;
                 $this->posxup += $this->postotalht - $this->posxdiscount;
                 $this->posxqty += $this->postotalht - $this->posxdiscount;
                 $this->posxdiscount += $this->postotalht - $this->posxdiscount;
                 //$this->postotalht;
             }
             // Situation invoice handling
             if ($object->situation_cycle_ref) {
                 $this->situationinvoice = True;
                 $progress_width = 14;
                 $this->posxtva -= $progress_width;
                 $this->posxup -= $progress_width;
                 $this->posxqty -= $progress_width;
                 $this->posxdiscount -= $progress_width;
                 $this->posxprogress -= $progress_width;
             }
             // New page
             $pdf->AddPage();
             if (!empty($tplidx)) {
                 $pdf->useTemplate($tplidx);
             }
             $pagenb++;
             $this->_pagehead($pdf, $object, 1, $outputlangs);
             $pdf->SetFont('', '', $default_font_size - 1);
             $pdf->MultiCell(0, 3, '');
             // Set interline to 3
             $pdf->SetTextColor(0, 0, 0);
             $tab_top = 90;
             $tab_top_newpage = empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD) ? 42 : 10;
             $tab_height = 130;
             $tab_height_newpage = 150;
             // Incoterm
             $height_incoterms = 0;
             if ($conf->incoterm->enabled) {
                 $desc_incoterms = $object->getIncotermsForPDF();
                 if ($desc_incoterms) {
                     $tab_top = 88;
                     $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 prend une longueur en 3eme param
                     $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;
                     $height_incoterms += 4;
                 }
             }
             // Affiche 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);
                     }
                 }
             }
             if ($notetoshow) {
                 $tab_top = 88 + $height_incoterms;
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
                 $nexY = $pdf->GetY();
                 $height_note = $nexY - $tab_top;
                 // Rect prend une longueur en 3eme param
                 $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_height = $tab_height - $height_note;
                 $tab_top = $nexY + 6;
             } else {
                 $height_note = 0;
             }
             $iniY = $tab_top + 7;
             $curY = $tab_top + 7;
             $nexY = $tab_top + 7;
             // Loop on each lines
             for ($i = 0; $i < $nblignes; $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)) {
                     $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;
                     $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, 3, $curX, $curY, $hideref, $hidedesc);
                 $pageposafter = $pdf->getPage();
                 if ($pageposafter > $pageposbefore) {
                     $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, 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)) {
                         if ($i == $nblignes - 1) {
                             $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
                         $showpricebeforepagebreak = 0;
                     }
                 } else {
                     $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);
                 // On repositionne la police par defaut
                 // VAT Rate
                 if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) {
                     $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
                     $pdf->SetXY($this->posxtva, $curY);
                     $pdf->MultiCell($this->posxup - $this->posxtva - 0.8, 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);
                 // Enough for 6 chars
                 if ($conf->global->PRODUCT_USE_UNITS) {
                     $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R');
                 } else {
                     $pdf->MultiCell($this->posxdiscount - $this->posxqty - 0.8, 4, $qty, 0, 'R');
                 }
                 // Unit
                 if ($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');
                 }
                 if ($this->situationinvoice) {
                     // Situation progress
                     $progress = pdf_getlineprogress($object, $i, $outputlangs, $hidedetails);
                     $pdf->SetXY($this->posxprogress, $curY);
                     $pdf->MultiCell($this->postotalht - $this->posxprogress, 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);
                 // Collecte des totaux par valeur de tva dans $this->tva["taux"]=total_tva
                 $prev_progress = $object->lines[$i]->get_prev_progress();
                 if ($prev_progress > 0) {
                     if ($conf->multicurrency->enabled && $object->multicurrency_tx != 1) {
                         $tvaligne = $object->lines[$i]->multicurrency_total_tva * ($object->lines[$i]->situation_percent - $prev_progress) / $object->lines[$i]->situation_percent;
                     } else {
                         $tvaligne = $object->lines[$i]->total_tva * ($object->lines[$i]->situation_percent - $prev_progress) / $object->lines[$i]->situation_percent;
                     }
                 } else {
                     if ($conf->multicurrency->enabled && $object->multicurrency_tx != 1) {
                         $tvaligne = $object->lines[$i]->multicurrency_total_tva;
                     } else {
                         $tvaligne = $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 == '') && (!empty($localtax1_rate) || !empty($localtax2_rate))) {
                     $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $object->thirdparty, $mysoc);
                     $localtax1_type = $localtaxtmp_array[0];
                     $localtax2_type = $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 & 0x1) == 0x1) {
                     $vatrate .= '*';
                 }
                 if (!isset($this->tva[$vatrate])) {
                     $this->tva[$vatrate] = '';
                 }
                 $this->tva[$vatrate] += $tvaligne;
                 if ($posYAfterImage > $posYAfterDescription) {
                     $nexY = $posYAfterImage;
                 }
                 // Add line
                 if ($conf->global->MAIN_PDF_DASH_BETWEEN_LINES && $i < $nblignes - 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;
                 // Passe espace entre les lignes
                 // 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 (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;
             }
             // Affiche zone infos
             $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
             // Affiche zone totaux
             $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
             // Affiche zone versements
             if ($deja_regle || $amount_credit_notes_included || $amount_deposits_included) {
                 $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs);
             }
             // Pied de page
             $this->_pagefoot($pdf, $object, $outputlangs);
             if (method_exists($pdf, 'AliasNbPages')) {
                 $pdf->AliasNbPages();
             }
             $pdf->Close();
             $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 (!empty($conf->global->MAIN_UMASK)) {
                 @chmod($file, octdec($conf->global->MAIN_UMASK));
             }
             return 1;
             // Pas d'erreur
         } else {
             $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
             return 0;
         }
     } else {
         $this->error = $langs->trans("ErrorConstantNotDefined", "FAC_OUTPUTDIR");
         return 0;
     }
     $this->error = $langs->trans("ErrorUnknown");
     return 0;
     // Erreur par defaut
 }
 /**
  *  Function to build pdf onto disk
  *
  *  @param		Object			$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
  */
 function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
 {
     global $user, $langs, $conf, $mysoc, $db, $hookmanager;
     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';
     }
     $outputlangs->load("main");
     $outputlangs->load("dict");
     $outputlangs->load("companies");
     $outputlangs->load("interventions");
     if ($conf->ficheinter->dir_output) {
         $object->fetch_thirdparty();
         // Definition of $dir and $file
         if ($object->specimen) {
             $dir = $conf->ficheinter->dir_output;
             $file = $dir . "/SPECIMEN.pdf";
         } else {
             $objectref = dol_sanitizeFileName($object->ref);
             $dir = $conf->ficheinter->dir_output . "/" . $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
             $nblignes = count($object->lines);
             // Create pdf instance
             $pdf = pdf_getInstance($this->format);
             $default_font_size = pdf_getPDFFontSize($outputlangs);
             // Must be after pdf_getInstance
             $heightforinfotot = 50;
             // Height reserved to output the info and total part
             $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)
             $pdf->SetAutoPageBreak(1, 0);
             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_DISABLE_FPDI) && !empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) {
                 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output . '/' . $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("InterventionCard"));
             $pdf->SetCreator("Dolibarr " . DOL_VERSION);
             $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
             $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref) . " " . $outputlangs->transnoentities("InterventionCard"));
             if (!empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) {
                 $pdf->SetCompression(false);
             }
             $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite);
             // Left, Top, Right
             // New page
             $pdf->AddPage();
             if (!empty($tplidx)) {
                 $pdf->useTemplate($tplidx);
             }
             $pagenb++;
             $this->_pagehead($pdf, $object, 1, $outputlangs);
             $pdf->SetFont('', '', $default_font_size - 1);
             $pdf->SetTextColor(0, 0, 0);
             $tab_top = 90;
             $tab_top_newpage = empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD) ? 42 : 10;
             $tab_height = 130;
             $tab_height_newpage = 150;
             // Affiche notes
             $notetoshow = empty($object->note_public) ? '' : $object->note_public;
             if ($notetoshow) {
                 $tab_top = 88;
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
                 $nexY = $pdf->GetY();
                 $height_note = $nexY - $tab_top;
                 // Rect prend une longueur en 3eme param
                 $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_height = $tab_height - $height_note;
                 $tab_top = $nexY + 6;
             } else {
                 $height_note = 0;
             }
             $iniY = $tab_top + 7;
             $curY = $tab_top + 7;
             $nexY = $tab_top + 7;
             $pdf->SetXY($this->marge_gauche, $tab_top);
             $pdf->MultiCell(190, 5, $outputlangs->transnoentities("Description"), 0, 'L', 0);
             $pdf->line($this->marge_gauche, $tab_top + 5, $this->page_largeur - $this->marge_droite, $tab_top + 5);
             $pdf->SetFont('', '', $default_font_size - 1);
             $pdf->SetXY($this->marge_gauche, $tab_top + 5);
             $text = $object->description;
             if ($object->duree > 0) {
                 $totaltime = convertSecondToTime($object->duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
                 $text .= ($text ? ' - ' : '') . $langs->trans("Total") . ": " . $totaltime;
             }
             $desc = dol_htmlentitiesbr($text, 1);
             //print $outputlangs->convToOutputCharset($desc); exit;
             $pdf->writeHTMLCell(180, 3, 10, $tab_top + 5, $outputlangs->convToOutputCharset($desc), 0, 1);
             $nexY = $pdf->GetY();
             $pdf->line($this->marge_gauche, $nexY, $this->page_largeur - $this->marge_droite, $nexY);
             $nblines = count($object->lines);
             // Loop on each lines
             for ($i = 0; $i < $nblines; $i++) {
                 $objectligne = $object->lines[$i];
                 $valide = empty($objectligne->id) ? 0 : $objectligne->fetch($objectligne->id);
                 if ($valide > 0 || $object->specimen) {
                     $curY = $nexY;
                     $pdf->SetFont('', '', $default_font_size - 1);
                     // Into loop to work with multipage
                     $pdf->SetTextColor(0, 0, 0);
                     $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();
                     // Description of product line
                     $curX = $this->posxdesc - 1;
                     // Description of product line
                     $txt = $outputlangs->transnoentities("Date") . " : " . dol_print_date($objectligne->datei, 'dayhour', false, $outputlangs, true);
                     if ($objectligne->duration > 0) {
                         $txt .= " - " . $outputlangs->transnoentities("Duration") . " : " . convertSecondToTime($objectligne->duration);
                     }
                     $txt = '<strong>' . dol_htmlentitiesbr($txt, 1, $outputlangs->charset_output) . '</strong>';
                     $desc = dol_htmlentitiesbr($objectligne->desc, 1);
                     $pdf->startTransaction();
                     $pdf->writeHTMLCell(0, 0, $curX, $curY + 1, dol_concatdesc($txt, $desc), 0, 1, 0);
                     $pageposafter = $pdf->getPage();
                     if ($pageposafter > $pageposbefore) {
                         $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->writeHTMLCell(0, 0, $curX, $curY, $txt . '<br>' . $desc, LR, 1, 0);
                         $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)) {
                             if ($i == $nblines - 1) {
                                 $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 {
                         $pdf->commitTransaction();
                     }
                     $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 is moved completely on next page
                     if ($pageposafter > $pageposbefore) {
                         $pdf->setPage($pageposafter);
                         $curY = $tab_top_newpage;
                     }
                     $pdf->SetFont('', '', $default_font_size - 1);
                     // On repositionne la police par defaut
                     // 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);
                         } else {
                             $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
                         }
                         $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 (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);
                         } else {
                             $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
                         }
                         $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);
                 $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);
                 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
             }
             $this->_pagefoot($pdf, $object, $outputlangs);
             if (method_exists($pdf, 'AliasNbPages')) {
                 $pdf->AliasNbPages();
             }
             $pdf->Close();
             $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 (!empty($conf->global->MAIN_UMASK)) {
                 @chmod($file, octdec($conf->global->MAIN_UMASK));
             }
             return 1;
         } else {
             $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
             return 0;
         }
     } else {
         $this->error = $langs->trans("ErrorConstantNotDefined", "FICHEINTER_OUTPUTDIR");
         return 0;
     }
     $this->error = $langs->trans("ErrorUnknown");
     return 0;
     // Erreur par defaut
 }
Exemple #4
0
     }
     $desc = dol_concatdesc($desc, $product_desc);
     // Add custom code and origin country into description
     if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (!empty($prod->customcode) || !empty($prod->country_code))) {
         $tmptxt = '(';
         if (!empty($prod->customcode)) {
             $tmptxt .= $langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
         }
         if (!empty($prod->customcode) && !empty($prod->country_code)) {
             $tmptxt .= ' - ';
         }
         if (!empty($prod->country_code)) {
             $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0);
         }
         $tmptxt .= ')';
         $desc = dol_concatdesc($desc, $tmptxt);
     }
     $type = $prod->type;
     $fk_unit = $prod->fk_unit;
 } else {
     $pu_ht = price2num($price_ht, 'MU');
     $pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
     $tva_npr = preg_match('/\\*/', $tva_tx) ? 1 : 0;
     $tva_tx = str_replace('*', '', $tva_tx);
     $label = GETPOST('product_label') ? GETPOST('product_label') : '';
     $desc = $product_desc;
     $type = GETPOST('type');
     $fk_unit = GETPOST('units', 'alpha');
 }
 // Margin
 $fournprice = price2num(GETPOST('fournprice' . $predef) ? GETPOST('fournprice' . $predef) : '');
Exemple #5
0
 $deliveryreceipt = $_POST['deliveryreceipt'];
 if ($action == 'send') {
     if (dol_strlen($_POST['subject'])) {
         $subject = $_POST['subject'];
     } else {
         $subject = $langs->transnoentities('CustomerOrder') . ' ' . $object->ref;
     }
     $actiontypecode = 'AC_SUP_INV';
     $actionmsg = $langs->transnoentities('MailSentBy') . ' ' . $from . ' ' . $langs->transnoentities('To') . ' ' . $sendto;
     if ($message) {
         if ($sendtocc) {
             $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('Bcc') . ": " . $sendtocc);
         }
         $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic') . ": " . $subject);
         $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody') . ":");
         $actionmsg = dol_concatdesc($actionmsg, $message);
     }
     $actionmsg2 = $langs->transnoentities('Action' . $actiontypecode);
 }
 // Create form object
 include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
 $formmail = new FormMail($db);
 $attachedfiles = $formmail->get_attached_files();
 $filepath = $attachedfiles['paths'];
 $filename = $attachedfiles['names'];
 $mimetype = $attachedfiles['mimes'];
 // Send mail
 require_once DOL_DOCUMENT_ROOT . '/core/class/CMailFile.class.php';
 $mailfile = new CMailFile($subject, $sendto, $from, $message, $filepath, $mimetype, $filename, $sendtocc, '', $deliveryreceipt, -1);
 if ($mailfile->error) {
     setEventMessages($mailfile->error, $mailfile->errors, 'errors');
Exemple #6
0
                 $price_base_type = $prodcustprice->lines[0]->price_base_type;
                 $prod->tva_tx = $prodcustprice->lines[0]->tva_tx;
             }
         }
     }
     // On reevalue prix selon taux tva car taux tva transaction peut etre different
     // de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
     if ($tva_tx != $prod->tva_tx) {
         if ($price_base_type != 'HT') {
             $pu_ht = price2num($pu_ttc / (1 + $tva_tx / 100), 'MU');
         } else {
             $pu_ttc = price2num($pu_ht * (1 + $tva_tx / 100), 'MU');
         }
     }
     $desc = $prod->description;
     $desc = dol_concatdesc($desc, $product_desc);
     $fk_unit = $prod->fk_unit;
 } else {
     $pu_ht = GETPOST('price_ht');
     $price_base_type = 'HT';
     $tva_tx = GETPOST('tva_tx') ? str_replace('*', '', GETPOST('tva_tx')) : 0;
     // tva_tx field may be disabled, so we use vat rate 0
     $tva_npr = preg_match('/\\*/', GETPOST('tva_tx')) ? 1 : 0;
     $desc = $product_desc;
     $fk_unit = GETPOST('units', 'alpha');
 }
 $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty);
 $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty);
 // ajout prix achat
 $fk_fournprice = $_POST['fournprice'];
 if (!empty($_POST['buying_price'])) {
 /**
  * Adds a product to the order
  *
  * @param Commande $object Order object
  * @param Product $prod Product to add
  * @param int $qty Quantity of the product
  * @throws Exception
  */
 public static function addOrderLine(Commande $object, Product $prod, $qty)
 {
     global $db, $conf, $mysoc, $langs;
     require_once DOL_DOCUMENT_ROOT . '/core/lib/admin.lib.php';
     $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
     $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
     if (!empty($conf->global->PRODUIT_MULTIPRICES) && !empty($object->thirdparty->price_level)) {
         $pu_ht = $prod->multiprices[$object->thirdparty->price_level];
         $pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
         $price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
         if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) {
             $tva_tx = $prod->multiprices_tva_tx[$object->thirdparty->price_level];
         }
         if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) {
             $tva_npr = $prod->multiprices_recuperableonly[$object->thirdparty->price_level];
         }
     } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
         require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
         $prodcustprice = new Productcustomerprice($db);
         $filter = array('t.fk_product' => $prod->id, 't.fk_soc' => $object->thirdparty->id);
         $result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
         if ($result >= 0) {
             if (count($prodcustprice->lines) > 0) {
                 $pu_ht = price($prodcustprice->lines[0]->price);
                 $pu_ttc = price($prodcustprice->lines[0]->price_ttc);
                 $price_base_type = $prodcustprice->lines[0]->price_base_type;
                 $prod->tva_tx = $prodcustprice->lines[0]->tva_tx;
             } else {
                 $pu_ht = $prod->price;
                 $pu_ttc = $prod->price_ttc;
                 $price_base_type = $prod->price_base_type;
             }
         } else {
             throw new Exception($prodcustprice->error);
         }
     } else {
         $pu_ht = $prod->price;
         $pu_ttc = $prod->price_ttc;
         $price_base_type = $prod->price_base_type;
     }
     // if price ht is forced (ie: calculated by margin rate and cost price)
     if (!empty($price_ht)) {
         $pu_ht = price2num($price_ht, 'MU');
         $pu_ttc = price2num($pu_ht * (1 + $tva_tx / 100), 'MU');
     } elseif ($tva_tx != $prod->tva_tx) {
         if ($price_base_type != 'HT') {
             $pu_ht = price2num($pu_ttc / (1 + $tva_tx / 100), 'MU');
         } else {
             $pu_ttc = price2num($pu_ht * (1 + $tva_tx / 100), 'MU');
         }
     }
     // Define output language
     if (!empty($conf->global->MAIN_MULTILANGS) && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
         $outputlangs = $langs;
         $newlang = '';
         if (empty($newlang) && GETPOST('lang_id')) {
             $newlang = GETPOST('lang_id');
         }
         if (empty($newlang)) {
             $newlang = $object->thirdparty->default_lang;
         }
         if (!empty($newlang)) {
             $outputlangs = new Translate("", $conf);
             $outputlangs->setDefaultLang($newlang);
         }
         $desc = !empty($prod->multilangs[$outputlangs->defaultlang]["description"]) ? $prod->multilangs[$outputlangs->defaultlang]["description"] : $prod->description;
     } else {
         $desc = $prod->description;
     }
     // Add custom code and origin country into description
     if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (!empty($prod->customcode) || !empty($prod->country_code))) {
         $tmptxt = '(';
         if (!empty($prod->customcode)) {
             $tmptxt .= $langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
         }
         if (!empty($prod->customcode) && !empty($prod->country_code)) {
             $tmptxt .= ' - ';
         }
         if (!empty($prod->country_code)) {
             $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0);
         }
         $tmptxt .= ')';
         $desc = dol_concatdesc($desc, $tmptxt);
     }
     //3.9.0 version added support for price units
     if (versioncompare(versiondolibarrarray(), array(3, 9, 0)) >= 0) {
         $fk_unit = $prod->fk_unit;
     } else {
         $fk_unit = null;
     }
     // Local Taxes
     $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty);
     $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty);
     $info_bits = 0;
     if ($tva_npr) {
         $info_bits |= 0x1;
     }
     //Percent remise
     if (!empty($object->thirdparty->remise_percent)) {
         $percent_remise = $object->thirdparty->remise_percent;
     } else {
         $percent_remise = 0;
     }
     // Insert line
     $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $prod->id, $percent_remise, $info_bits, 0, $price_base_type, $pu_ttc, '', '', $prod->type, -1, 0, 0, null, 0, '', 0, $fk_unit);
     if ($result < 0) {
         throw new Exception($langs->trans('ErrorAddOrderLine', $prod->ref));
     }
 }
Exemple #8
0
 /**
  *  Check if notification are active for couple action/company.
  * 	If yes, send mail and save trace into llx_notify.
  *
  * 	@param	string	$notifcode		Code of action in llx_c_action_trigger (new usage) or Id of action in llx_c_action_trigger (old usage)
  * 	@param	Object	$object			Object the notification deals on
  *	@return	int						<0 if KO, or number of changes if OK
  */
 function send($notifcode, $object)
 {
     global $user, $conf, $langs, $mysoc, $dolibarr_main_url_root;
     include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
     dol_syslog(get_class($this) . "::send notifcode=" . $notifcode . ", object=" . $object->id);
     $langs->load("other");
     // Define $urlwithroot
     $urlwithouturlroot = preg_replace('/' . preg_quote(DOL_URL_ROOT, '/') . '$/i', '', trim($dolibarr_main_url_root));
     $urlwithroot = $urlwithouturlroot . DOL_URL_ROOT;
     // This is to use external domain name found into config file
     //$urlwithroot=DOL_MAIN_URL_ROOT;						// This is to use same domain name than current
     // Define some vars
     $application = $mysoc->name;
     //if (! empty($conf->global->MAIN_APPLICATION_TITLE)) $application = $conf->global->MAIN_APPLICATION_TITLE;
     $replyto = $conf->notification->email_from;
     $filename = basename($file);
     $mimefile = dol_mimetype($file);
     $object_type = '';
     $link = '';
     $num = 0;
     if (!in_array($notifcode, array('BILL_VALIDATE', 'ORDER_VALIDATE', 'PROPAL_VALIDATE', 'FICHINTER_VALIDATE', 'ORDER_SUPPLIER_VALIDATE', 'ORDER_SUPPLIER_APPROVE', 'ORDER_SUPPLIER_REFUSE', 'SHIPPING_VALIDATE'))) {
         return 0;
     }
     $oldref = empty($object->oldref) ? $object->ref : $object->oldref;
     $newref = empty($object->newref) ? $object->ref : $object->newref;
     // Check notification per third party
     $sql = "SELECT s.nom, c.email, c.rowid as cid, c.lastname, c.firstname, c.default_lang,";
     $sql .= " a.rowid as adid, a.label, a.code, n.rowid, n.type";
     $sql .= " FROM " . MAIN_DB_PREFIX . "socpeople as c,";
     $sql .= " " . MAIN_DB_PREFIX . "c_action_trigger as a,";
     $sql .= " " . MAIN_DB_PREFIX . "notify_def as n,";
     $sql .= " " . MAIN_DB_PREFIX . "societe as s";
     $sql .= " WHERE n.fk_contact = c.rowid AND a.rowid = n.fk_action";
     $sql .= " AND n.fk_soc = s.rowid";
     if (is_numeric($notifcode)) {
         $sql .= " AND n.fk_action = " . $notifcode;
     } else {
         $sql .= " AND a.code = '" . $notifcode . "'";
     }
     // New usage
     $sql .= " AND s.rowid = " . $object->socid;
     $result = $this->db->query($sql);
     if ($result) {
         $num = $this->db->num_rows($result);
         if ($num > 0) {
             $i = 0;
             while ($i < $num && !$error) {
                 $obj = $this->db->fetch_object($result);
                 $sendto = dolGetFirstLastname($obj->firstname, $obj->lastname) . " <" . $obj->email . ">";
                 $notifcodedefid = $obj->adid;
                 if (dol_strlen($obj->email)) {
                     // Set output language
                     $outputlangs = $langs;
                     if ($obj->default_lang && $obj->default_lang != $langs->defaultlang) {
                         $outputlangs = new Translate('', $conf);
                         $outputlangs->setDefaultLang($obj->default_lang);
                     }
                     switch ($notifcode) {
                         case 'BILL_VALIDATE':
                             $link = '/compta/facture.php?facid=' . $object->id;
                             $dir_output = $conf->facture->dir_output;
                             $object_type = 'facture';
                             $mesg = $langs->transnoentitiesnoconv("EMailTextInvoiceValidated", $newref);
                             break;
                         case 'ORDER_VALIDATE':
                             $link = '/commande/card.php?id=' . $object->id;
                             $dir_output = $conf->commande->dir_output;
                             $object_type = 'order';
                             $mesg = $langs->transnoentitiesnoconv("EMailTextOrderValidated", $newref);
                             break;
                         case 'PROPAL_VALIDATE':
                             $link = '/comm/propal.php?id=' . $object->id;
                             $dir_output = $conf->propal->dir_output;
                             $object_type = 'propal';
                             $mesg = $langs->transnoentitiesnoconv("EMailTextProposalValidated", $newref);
                             break;
                         case 'FICHINTER_VALIDATE':
                             $link = '/fichinter/card.php?id=' . $object->id;
                             $dir_output = $conf->facture->dir_output;
                             $object_type = 'ficheinter';
                             $mesg = $langs->transnoentitiesnoconv("EMailTextInterventionValidated", $object->ref);
                             break;
                         case 'ORDER_SUPPLIER_VALIDATE':
                             $link = '/fourn/commande/card.php?id=' . $object->id;
                             $dir_output = $conf->fournisseur->dir_output . '/commande/';
                             $object_type = 'order_supplier';
                             $mesg = $langs->transnoentitiesnoconv("Hello") . ",\n\n";
                             $mesg .= $langs->transnoentitiesnoconv("EMailTextOrderValidatedBy", $object->ref, $user->getFullName($langs));
                             $mesg .= "\n\n" . $langs->transnoentitiesnoconv("Sincerely") . ".\n\n";
                             break;
                         case 'ORDER_SUPPLIER_APPROVE':
                             $link = '/fourn/commande/card.php?id=' . $object->id;
                             $dir_output = $conf->fournisseur->dir_output . '/commande/';
                             $object_type = 'order_supplier';
                             $mesg = $langs->transnoentitiesnoconv("Hello") . ",\n\n";
                             $mesg .= $langs->transnoentitiesnoconv("EMailTextOrderApprovedBy", $newref, $user->getFullName($langs));
                             $mesg .= "\n\n" . $langs->transnoentitiesnoconv("Sincerely") . ".\n\n";
                             break;
                         case 'ORDER_SUPPLIER_REFUSE':
                             $link = '/fourn/commande/card.php?id=' . $object->id;
                             $dir_output = $conf->fournisseur->dir_output . '/commande/';
                             $object_type = 'order_supplier';
                             $mesg = $langs->transnoentitiesnoconv("Hello") . ",\n\n";
                             $mesg .= $langs->transnoentitiesnoconv("EMailTextOrderRefusedBy", $newref, $user->getFullName($langs));
                             $mesg .= "\n\n" . $langs->transnoentitiesnoconv("Sincerely") . ".\n\n";
                             break;
                         case 'SHIPPING_VALIDATE':
                             $dir_output = $conf->expedition->dir_output . '/sending/';
                             $object_type = 'order_supplier';
                             $mesg = $langs->transnoentitiesnoconv("EMailTextExpeditionValidated", $newref);
                             break;
                     }
                     $ref = dol_sanitizeFileName($newref);
                     $pdf_path = $dir_output . "/" . $ref . "/" . $ref . ".pdf";
                     if (!dol_is_file($pdf_path)) {
                         // We can't add PDF as it is not generated yet.
                         $filepdf = '';
                     } else {
                         $filepdf = $pdf_path;
                     }
                     $subject = '[' . $application . '] ' . $outputlangs->transnoentitiesnoconv("DolibarrNotification");
                     $message = $outputlangs->transnoentities("YouReceiveMailBecauseOfNotification", $application, $mysoc->name) . "\n";
                     $message .= $outputlangs->transnoentities("YouReceiveMailBecauseOfNotification2", $application, $mysoc->name) . "\n";
                     $message .= "\n";
                     $message .= $mesg;
                     if ($link) {
                         $message = dol_concatdesc($message, $urlwithroot . $link);
                     }
                     $mailfile = new CMailFile($subject, $sendto, $replyto, $message, array($file), array($mimefile), array($filename[count($filename) - 1]), '', '', 0, -1);
                     if ($mailfile->sendfile()) {
                         $sql = "INSERT INTO " . MAIN_DB_PREFIX . "notify (daten, fk_action, fk_soc, fk_contact, type, objet_type, objet_id, email)";
                         $sql .= " VALUES ('" . $this->db->idate(dol_now()) . "', " . $notifcodedefid . ", " . $object->socid . ", " . $obj->cid . ", '" . $obj->type . "', '" . $object_type . "', " . $object->id . ", '" . $this->db->escape($obj->email) . "')";
                         if (!$this->db->query($sql)) {
                             dol_print_error($this->db);
                         }
                     } else {
                         $error++;
                         $this->errors[] = $mailfile->error;
                     }
                 } else {
                     dol_syslog("No notification sent for " . $sendto . " because email is empty");
                 }
                 $i++;
             }
         } else {
             dol_syslog("No notification to thirdparty sent, nothing into notification setup for the thirdparty socid = " . $object->socid);
         }
     } else {
         $error++;
         $this->errors[] = $this->db->lasterror();
         return -1;
     }
     // Check notification using fixed email
     if (!$error) {
         foreach ($conf->global as $key => $val) {
             if ($val == '' || !preg_match('/^NOTIFICATION_FIXEDEMAIL_' . $notifcode . '_THRESHOLD_HIGHER_(.*)$/', $key, $reg)) {
                 continue;
             }
             $threshold = (double) $reg[1];
             if ($object->total_ht <= $threshold) {
                 dol_syslog("A notification is requested for notifcode = " . $notifcode . " but amount = " . $object->total_ht . " so lower than threshold = " . $threshold . ". We discard this notification");
                 continue;
             }
             $param = 'NOTIFICATION_FIXEDEMAIL_' . $notifcode . '_THRESHOLD_HIGHER_' . $reg[1];
             $sendto = $conf->global->{$param};
             $notifcodedefid = dol_getIdFromCode($this->db, $notifcode, 'c_action_trigger', 'code', 'rowid');
             if ($notifcodedefid <= 0) {
                 dol_print_error($this->db, 'Failed to get id from code');
             }
             $object_type = '';
             $link = '';
             $num++;
             switch ($notifcode) {
                 case 'BILL_VALIDATE':
                     $link = '/compta/facture.php?facid=' . $object->id;
                     $dir_output = $conf->facture->dir_output;
                     $object_type = 'facture';
                     $mesg = $langs->transnoentitiesnoconv("EMailTextInvoiceValidated", $newref);
                     break;
                 case 'ORDER_VALIDATE':
                     $link = '/commande/card.php?id=' . $object->id;
                     $dir_output = $conf->commande->dir_output;
                     $object_type = 'order';
                     $mesg = $langs->transnoentitiesnoconv("EMailTextOrderValidated", $newref);
                     break;
                 case 'PROPAL_VALIDATE':
                     $link = '/comm/propal.php?id=' . $object->id;
                     $dir_output = $conf->propal->dir_output;
                     $object_type = 'propal';
                     $mesg = $langs->transnoentitiesnoconv("EMailTextProposalValidated", $newref);
                     break;
                 case 'FICHINTER_VALIDATE':
                     $link = '/fichinter/card.php?id=' . $object->id;
                     $dir_output = $conf->facture->dir_output;
                     $object_type = 'ficheinter';
                     $mesg = $langs->transnoentitiesnoconv("EMailTextInterventionValidated", $newref);
                     break;
                 case 'ORDER_SUPPLIER_VALIDATE':
                     $link = '/fourn/commande/card.php?id=' . $object->id;
                     $dir_output = $conf->fournisseur->dir_output . '/commande/';
                     $object_type = 'order_supplier';
                     $mesg = $langs->transnoentitiesnoconv("Hello") . ",\n\n";
                     $mesg .= $langs->transnoentitiesnoconv("EMailTextOrderValidatedBy", $newref, $user->getFullName($langs));
                     $mesg .= "\n\n" . $langs->transnoentitiesnoconv("Sincerely") . ".\n\n";
                     break;
                 case 'ORDER_SUPPLIER_APPROVE':
                     $link = '/fourn/commande/card.php?id=' . $object->id;
                     $dir_output = $conf->fournisseur->dir_output . '/commande/';
                     $object_type = 'order_supplier';
                     $mesg = $langs->transnoentitiesnoconv("Hello") . ",\n\n";
                     $mesg .= $langs->transnoentitiesnoconv("EMailTextOrderApprovedBy", $newref, $user->getFullName($langs));
                     $mesg .= "\n\n" . $langs->transnoentitiesnoconv("Sincerely") . ".\n\n";
                     break;
                 case 'ORDER_SUPPLIER_APPROVE2':
                     $link = '/fourn/commande/card.php?id=' . $object->id;
                     $dir_output = $conf->fournisseur->dir_output . '/commande/';
                     $object_type = 'order_supplier';
                     $mesg = $langs->transnoentitiesnoconv("Hello") . ",\n\n";
                     $mesg .= $langs->transnoentitiesnoconv("EMailTextOrderApprovedBy", $newref, $user->getFullName($langs));
                     $mesg .= "\n\n" . $langs->transnoentitiesnoconv("Sincerely") . ".\n\n";
                     break;
                 case 'ORDER_SUPPLIER_REFUSE':
                     $link = '/fourn/commande/card.php?id=' . $object->id;
                     $dir_output = $conf->fournisseur->dir_output . '/commande/';
                     $object_type = 'order_supplier';
                     $mesg = $langs->transnoentitiesnoconv("Hello") . ",\n\n";
                     $mesg .= $langs->transnoentitiesnoconv("EMailTextOrderRefusedBy", $newref, $user->getFullName($langs));
                     $mesg .= "\n\n" . $langs->transnoentitiesnoconv("Sincerely") . ".\n\n";
                     break;
                 case 'SHIPPING_VALIDATE':
                     $dir_output = $conf->expedition->dir_output . '/sending/';
                     $object_type = 'order_supplier';
                     $mesg = $langs->transnoentitiesnoconv("EMailTextExpeditionValidated", $newref);
                     break;
             }
             $ref = dol_sanitizeFileName($newref);
             $pdf_path = $dir_output . "/" . $ref . "/" . $ref . ".pdf";
             if (!dol_is_file($pdf_path)) {
                 // We can't add PDF as it is not generated yet.
                 $filepdf = '';
             } else {
                 $filepdf = $pdf_path;
             }
             $subject = '[' . $application . '] ' . $langs->transnoentitiesnoconv("DolibarrNotification");
             $message = $langs->transnoentities("YouReceiveMailBecauseOfNotification", $application, $mysoc->name) . "\n";
             $message .= $langs->transnoentities("YouReceiveMailBecauseOfNotification2", $application, $mysoc->name) . "\n";
             $message .= "\n";
             $message .= $mesg;
             if ($link) {
                 $message = dol_concatdesc($message, $urlwithroot . $link);
             }
             // Replace keyword __SUPERVISOREMAIL__
             if (preg_match('/__SUPERVISOREMAIL__/', $sendto)) {
                 $newval = '';
                 if ($user->fk_user > 0) {
                     $supervisoruser = new User($this->db);
                     $supervisoruser->fetch($user->fk_user);
                     if ($supervisoruser->email) {
                         $newval = trim(dolGetFirstLastname($supervisoruser->firstname, $supervisoruser->lastname) . ' <' . $supervisoruser->email . '>');
                     }
                 }
                 dol_syslog("Replace the __SUPERVISOREMAIL__ key into recipient email string with " . $newval);
                 $sendto = preg_replace('/__SUPERVISOREMAIL__/', $newval, $sendto);
                 $sendto = preg_replace('/^[\\s,]+/', '', $sendto);
                 // Clean start of string
                 $sendto = preg_replace('/[\\s,]+$/', '', $sendto);
                 // Clean end of string
             }
             if ($sendto) {
                 $mailfile = new CMailFile($subject, $sendto, $replyto, $message, array($file), array($mimefile), array($filename[count($filename) - 1]), '', '', 0, -1);
                 if ($mailfile->sendfile()) {
                     $sql = "INSERT INTO " . MAIN_DB_PREFIX . "notify (daten, fk_action, fk_soc, fk_contact, type, objet_type, objet_id, email)";
                     $sql .= " VALUES ('" . $this->db->idate(dol_now()) . "', " . $notifcodedefid . ", " . $object->socid . ", null, 'email', '" . $object_type . "', " . $object->id . ", '" . $this->db->escape($conf->global->{$param}) . "')";
                     if (!$this->db->query($sql)) {
                         dol_print_error($this->db);
                     }
                 } else {
                     $error++;
                     $this->errors[] = $mailfile->error;
                 }
             }
         }
     }
     if (!$error) {
         return $num;
     } else {
         return -1 * $error;
     }
 }
         }
     }
     // Define line content
     $outputlangs = new Translate('', $conf);
     $outputlangs->setDefaultLang(empty($obj->lang) ? $langs->defaultlang : $obj->lang);
     // By default language of sale representative
     $outputlangs->load("bills");
     $outputlangs->load("main");
     $outputlangs->load("contracts");
     $outputlangs->load("products");
     if (dol_strlen($obj->email)) {
         $message .= $outputlangs->trans("Contract") . " " . $obj->ref . ": " . $langs->trans("Service") . " " . dol_concatdesc($obj->plabel, $obj->description) . " (" . price($obj->total_ttc, 0, $outputlangs, 0, 0, -1, $conf->currency) . ") " . $obj->name . ", " . $outputlangs->trans("DateEndPlannedShort") . " " . dol_print_date($db->jdate($obj->date_fin_validite), 'day') . "\n\n";
         dol_syslog("email_expire_services_to_representatives.php: " . $obj->email);
         $foundtoprocess++;
     }
     print "Service to expire " . $obj->ref . ", label " . dol_concatdesc($obj->plabel, $obj->description) . ", due date " . dol_print_date($db->jdate($obj->date_fin_validite), 'day') . " (linked to company " . $obj->name . ", sale representative " . dolGetFirstLastname($obj->firstname, $obj->lastname) . ", email " . $obj->email . "): ";
     if (dol_strlen($obj->email)) {
         print "qualified.";
     } else {
         print "disqualified (no email).";
     }
     print "\n";
     unset($outputlangs);
     $total += $obj->total_ttc;
     $i++;
 }
 // Si il reste des envois en buffer
 if ($foundtoprocess) {
     if (dol_strlen($oldemail) && $oldemail != 'none') {
         envoi_mail($mode, $oldemail, $message, $total, $oldlang, $oldsalerepresentative, $duration_value);
     } else {
Exemple #10
0
/**
 *  Return line description translated in outputlangs and encoded into UTF8
 *
 *  @param  Line		$line                Current line number (0 = first line, 1 = second line, ...)
 *  @param  Translate	$outputlangs         Object langs for output
 *  @param  int			$hideref             Hide reference
 *  @param  int			$hidedesc            Hide description
 *  @param  int			$issupplierline      Is it a line for a supplier object ?
 *  @return string       				     String with line
 */
function doc_getlinedesc($line, $outputlangs, $hideref = 0, $hidedesc = 0, $issupplierline = 0)
{
    global $db, $conf, $langs;
    $idprod = $line->fk_product;
    $label = !empty($line->label) ? $line->label : (!empty($line->libelle) ? $line->libelle : '');
    $desc = !empty($line->desc) ? $line->desc : (!empty($line->description) ? $line->description : '');
    $ref_supplier = !empty($line->ref_supplier) ? $line->ref_supplier : (!empty($line->ref_fourn) ? $line->ref_fourn : '');
    // TODO Not yet saved for supplier invoices, only supplier orders
    $note = !empty($line->note) ? $line->note : '';
    if ($issupplierline) {
        $prodser = new ProductFournisseur($db);
    } else {
        $prodser = new Product($db);
    }
    if ($idprod) {
        $prodser->fetch($idprod);
        // If a predefined product and multilang and on other lang, we renamed label with label translated
        if (!empty($conf->global->MAIN_MULTILANGS) && $outputlangs->defaultlang != $langs->defaultlang) {
            if (!empty($prodser->multilangs[$outputlangs->defaultlang]["label"]) && $label == $prodser->label) {
                $label = $prodser->multilangs[$outputlangs->defaultlang]["label"];
            }
            if (!empty($prodser->multilangs[$outputlangs->defaultlang]["description"]) && $desc == $prodser->description) {
                $desc = $prodser->multilangs[$outputlangs->defaultlang]["description"];
            }
            if (!empty($prodser->multilangs[$outputlangs->defaultlang]["note"]) && $note == $prodser->note) {
                $note = $prodser->multilangs[$outputlangs->defaultlang]["note"];
            }
        }
    }
    // Description short of product line
    $libelleproduitservice = $label;
    // Description long of product line
    if ($desc && $desc != $label) {
        if ($desc == '(CREDIT_NOTE)' && $line->fk_remise_except) {
            $discount = new DiscountAbsolute($db);
            $discount->fetch($line->fk_remise_except);
            $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromCreditNote", $discount->ref_facture_source);
        } elseif ($desc == '(DEPOSIT)' && $line->fk_remise_except) {
            $discount = new DiscountAbsolute($db);
            $discount->fetch($line->fk_remise_except);
            $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromDeposit", $discount->ref_facture_source);
            // Add date of deposit
            if (!empty($conf->global->INVOICE_ADD_DEPOSIT_DATE)) {
                $libelleproduitservice .= ' (' . dol_print_date($discount->datec, 'day', '', $outputlangs) . ')';
            }
        } else {
            if ($idprod) {
                if (empty($hidedesc)) {
                    $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
                }
            } else {
                $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
            }
        }
    }
    // If line linked to a product
    if ($idprod) {
        // On ajoute la ref
        if ($prodser->ref) {
            $prefix_prodserv = "";
            $ref_prodserv = "";
            if (!empty($conf->global->PRODUCT_ADD_TYPE_IN_DOCUMENTS)) {
                if ($prodser->isService()) {
                    $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Service") . " ";
                } else {
                    $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Product") . " ";
                }
            }
            if (empty($hideref)) {
                if ($issupplierline) {
                    $ref_prodserv = $prodser->ref . ' (' . $outputlangs->trans("SupplierRef") . ' ' . $ref_supplier . ')';
                } else {
                    $ref_prodserv = $prodser->ref;
                }
                // Show local ref only
                $ref_prodserv .= " - ";
            }
            $libelleproduitservice = $prefix_prodserv . $ref_prodserv . $libelleproduitservice;
        }
    }
    if (!empty($line->date_start) || !empty($line->date_end)) {
        $format = 'day';
        // Show duration if exists
        if ($line->date_start && $line->date_end) {
            $period = '(' . $outputlangs->transnoentitiesnoconv('DateFromTo', dol_print_date($line->date_start, $format, false, $outputlangs), dol_print_date($line->date_end, $format, false, $outputlangs)) . ')';
        }
        if ($line->date_start && !$line->date_end) {
            $period = '(' . $outputlangs->transnoentitiesnoconv('DateFrom', dol_print_date($line->date_start, $format, false, $outputlangs)) . ')';
        }
        if (!$line->date_start && $line->date_end) {
            $period = '(' . $outputlangs->transnoentitiesnoconv('DateUntil', dol_print_date($line->date_end, $format, false, $outputlangs)) . ')';
        }
        //print '>'.$outputlangs->charset_output.','.$period;
        $libelleproduitservice = dol_concatdesc($libelleproduitservice, $period);
        //print $libelleproduitservice;
    }
    return $libelleproduitservice;
}
$value_private = $object->note_private;
if (!empty($conf->global->MAIN_AUTO_TIMESTAMP_IN_PUBLIC_NOTES)) {
    $stringtoadd = dol_print_date(dol_now(), 'dayhour') . ' ' . $user->getFullName($langs) . ' --';
    if (GETPOST('action') == 'edit' . $note_public) {
        $value_public = dol_concatdesc($value_public, ($value_public ? "\n" : "") . "-- " . $stringtoadd);
        if (dol_textishtml($value_public)) {
            $value_public .= "<br>\n";
        } else {
            $value_public .= "\n";
        }
    }
}
if (!empty($conf->global->MAIN_AUTO_TIMESTAMP_IN_PRIVATE_NOTES)) {
    $stringtoadd = dol_print_date(dol_now(), 'dayhour') . ' ' . $user->getFullName($langs) . ' --';
    if (GETPOST('action') == 'edit' . $note_private) {
        $value_private = dol_concatdesc($value_private, ($value_private ? "\n" : "") . "-- " . $stringtoadd);
        if (dol_textishtml($value_private)) {
            $value_private .= "<br>\n";
        } else {
            $value_private .= "\n";
        }
    }
}
// Special cases
if ($module == 'propal') {
    $permission = $user->rights->propale->creer;
} elseif ($module == 'fichinter') {
    $permission = $user->rights->ficheinter->creer;
} elseif ($module == 'project') {
    $permission = $user->rights->projet->creer;
} elseif ($module == 'project_task') {
         //if (empty($newemail)) print "Warning: Customer ".$target." has no email. Notice disabled.\n";
     }
     // Define line content
     $outputlangs = new Translate('', $conf);
     $outputlangs->setDefaultLang(empty($obj->default_lang) ? $langs->defaultlang : $obj->default_lang);
     // By default language of customer
     $outputlangs->load("bills");
     $outputlangs->load("main");
     $outputlangs->load("contracts");
     $outputlangs->load("products");
     if (dol_strlen($newemail)) {
         $message .= $outputlangs->trans("Contract") . " " . $obj->ref . ": " . $outputlangs->trans("Service") . " " . dol_concatdesc($obj->plabel, $obj->description) . " (" . price($obj->total_ttc, 0, $outputlangs, 0, 0, -1, $conf->currency) . "), " . $outputlangs->trans("DateEndPlannedShort") . " " . dol_print_date($db->jdate($obj->date_fin_validite), 'day') . "\n\n";
         dol_syslog("email_expire_services_to_customers.php: " . $newemail . " " . $message);
         $foundtoprocess++;
     }
     print "Service to expire " . $obj->ref . ", label " . dol_concatdesc($obj->plabel, $obj->description) . ", due date " . dol_print_date($db->jdate($obj->date_fin_validite), 'day') . ", customer id " . $obj->sid . " " . $obj->name . ", " . ($obj->cid ? "contact id " . $obj->cid . " " . $obj->clastname . " " . $obj->cfirstname . ", " : "") . "email " . $newemail . ", lang " . $outputlangs->defaultlang . ": ";
     if (dol_strlen($newemail)) {
         print "qualified.";
     } else {
         print "disqualified (no email).";
     }
     print "\n";
     unset($outputlangs);
     $total += $obj->total_ttc;
     $i++;
 }
 // Si il reste des envois en buffer
 if ($foundtoprocess) {
     if (dol_strlen($oldemail) && $oldemail != 'none' && empty($trackthirdpartiessent[$oldsid . '|' . $oldemail])) {
         envoi_mail($mode, $oldemail, $message, $total, $oldlang, $oldtarget, $duration_value);
         $trackthirdpartiessent[$oldsid . '|' . $oldemail] = 'contact id ' . $oldcid;
function _createEvent(&$db, &$user, &$langs, &$conf, &$propal, $fk_socpeople, $subject, $message, $type = 'thirdparty')
{
    $actionmsg = $actionmsg2 = '';
    if ($type == 'thirdparty') {
        $sendto = $propal->thirdparty->email;
    } else {
        $sendto = $propal->thirdparty->contact_get_property((int) $fk_socpeople, 'email');
    }
    $actionmsg2 = $langs->transnoentities('MailSentBy') . ' <' . $user->email . '> ' . $langs->transnoentities('To') . ' ' . $sendto;
    if ($message) {
        $actionmsg = $langs->transnoentities('MailSentBy') . ' <' . $user->email . '> ' . $langs->transnoentities('To') . ' ' . $sendto;
        $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic') . ": " . $subject);
        $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody') . ":");
        $actionmsg = dol_concatdesc($actionmsg, $message);
    }
    // Initialisation donnees
    $propal->socid = $propal->thirdparty->id;
    // To link to a company
    $propal->sendtoid = $fk_socpeople;
    // To link to a contact/address
    $propal->actiontypecode = 'AC_PROP';
    $propal->actionmsg = $actionmsg;
    // Long text
    $propal->actionmsg2 = $actionmsg2;
    // Short text
    $propal->fk_element = $propal->id;
    $propal->elementtype = $propal->element;
    // Appel des triggers
    $interface = new Interfaces($db);
    $result = $interface->run_triggers('PROPAL_SENTBYMAIL', $propal, $user, $langs, $conf);
}
 /**
  * testDolConcat
  *
  * @return boolean
  */
 public function testDolConcat()
 {
     $text1 = "A string 1";
     $text2 = "A string 2";
     // text 1 and 2 are text, concat need only \n
     $after = dol_concatdesc($text1, $text2);
     $this->assertEquals("A string 1\nA string 2", $after);
     $text1 = "A<br>string 1";
     $text2 = "A string 2";
     // text 1 is html, concat need <br>\n
     $after = dol_concatdesc($text1, $text2);
     $this->assertEquals("A<br>string 1<br>\nA string 2", $after);
     $text1 = "A string 1";
     $text2 = "A <b>string</b> 2";
     // text 2 is html, concat need <br>\n
     $after = dol_concatdesc($text1, $text2);
     $this->assertEquals("A string 1<br>\nA <b>string</b> 2", $after);
     return true;
 }
 /**
  *  Function to build pdf onto disk
  *
  *  @param		Object		$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
  */
 function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
 {
     global $user, $langs, $conf, $mysoc, $db, $hookmanager;
     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';
     }
     $outputlangs->load("main");
     $outputlangs->load("dict");
     $outputlangs->load("companies");
     $outputlangs->load("bills");
     $outputlangs->load("products");
     $outputlangs->load("orders");
     $outputlangs->load("deliveries");
     $nblignes = count($object->lines);
     if ($conf->commande->dir_output) {
         $object->fetch_thirdparty();
         $deja_regle = "";
         // Definition of $dir and $file
         if ($object->specimen) {
             $dir = $conf->commande->dir_output;
             $file = $dir . "/SPECIMEN.pdf";
         } else {
             $objectref = dol_sanitizeFileName($object->ref);
             $dir = $conf->commande->dir_output . "/" . $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
             // Create pdf instance
             $pdf = pdf_getInstance($this->format);
             $default_font_size = pdf_getPDFFontSize($outputlangs);
             // Must be after pdf_getInstance
             $heightforinfotot = 50;
             // Height reserved to output the info and total part
             $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)
             $pdf->SetAutoPageBreak(1, 0);
             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_DISABLE_FPDI) && !empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) {
                 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output . '/' . $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("Order"));
             $pdf->SetCreator("Dolibarr " . DOL_VERSION);
             $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
             $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref) . " " . $outputlangs->transnoentities("Order"));
             if (!empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) {
                 $pdf->SetCompression(false);
             }
             $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite);
             // Left, Top, Right
             // Positionne $this->atleastonediscount si on a au moins une remise
             for ($i = 0; $i < $nblignes; $i++) {
                 if ($object->lines[$i]->remise_percent) {
                     $this->atleastonediscount++;
                 }
             }
             if (empty($this->atleastonediscount)) {
                 $this->posxpicture += $this->postotalht - $this->posxdiscount;
                 $this->posxtva += $this->postotalht - $this->posxdiscount;
                 $this->posxup += $this->postotalht - $this->posxdiscount;
                 $this->posxqty += $this->postotalht - $this->posxdiscount;
                 $this->posxdiscount += $this->postotalht - $this->posxdiscount;
                 //$this->postotalht;
             }
             // New page
             $pdf->AddPage();
             if (!empty($tplidx)) {
                 $pdf->useTemplate($tplidx);
             }
             $pagenb++;
             $this->_pagehead($pdf, $object, 1, $outputlangs);
             $pdf->SetFont('', '', $default_font_size - 1);
             $pdf->MultiCell(0, 3, '');
             // Set interline to 3
             $pdf->SetTextColor(0, 0, 0);
             $tab_top = 90;
             $tab_top_newpage = empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD) ? 42 : 10;
             $tab_height = 130;
             $tab_height_newpage = 150;
             // Affiche 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);
                     }
                 }
             }
             if ($notetoshow) {
                 $tab_top = 88;
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
                 $nexY = $pdf->GetY();
                 $height_note = $nexY - $tab_top;
                 // Rect prend une longueur en 3eme param
                 $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_height = $tab_height - $height_note;
                 $tab_top = $nexY + 6;
             } else {
                 $height_note = 0;
             }
             $iniY = $tab_top + 7;
             $curY = $tab_top + 7;
             $nexY = $tab_top + 7;
             $inPackage = false;
             $TPackageInfos = array();
             $TChilds = array();
             $package_qty = 0;
             $TStack = array();
             // Loop on each lines
             for ($i = 0; $i < $nblignes; $i++) {
                 $package_qty = $TStack[count($TStack) - 1]['package_qty'];
                 $inPackage = count($TStack) > 0;
                 // Ligne de titre
                 if ($object->lines[$i]->product_type == 9 && $object->lines[$i]->qty < 97 && $object->lines[$i]->fk_product > 0) {
                     $inPackage = true;
                     if ($conf->global->SUBTOTAL_SHOW_QTY_ON_TITLES) {
                         if (!empty($object->lines[$i]->fk_product)) {
                             $product = new Product($db);
                             $product->fetch($object->lines[$i]->fk_product);
                             $TChilds = $product->getChildsArbo($product->id);
                             $TStack[count($TStack)] = array('childs' => $TChilds, 'package' => array(), 'package_qty' => 0);
                             // Si on se trouvait déjà dans un package, on rajoute ce produit à la liste des produits
                             // du précédent package
                             if (count($TStack) > 1) {
                                 $TStack[count($TStack) - 2]['package'][$object->lines[$i]->fk_product] += $object->lines[$i]->qty;
                             }
                         }
                     }
                 }
                 if ($conf->global->SUBTOTAL_SHOW_QTY_ON_TITLES) {
                     if ($inPackage && $object->lines[$i]->product_type != 9 && $object->lines[$i]->fk_product > 0) {
                         $TStack[count($TStack) - 1]['package'][$object->lines[$i]->fk_product] += $object->lines[$i]->qty;
                     }
                 }
                 // Ligne de sous-total
                 if ($inPackage && $object->lines[$i]->product_type == 9 && $object->lines[$i]->qty >= 97) {
                     if (count($TStack) <= 1) {
                         $inPackage = false;
                     }
                     if ($conf->global->SUBTOTAL_SHOW_QTY_ON_TITLES) {
                         // Comparaison pour déterminer la quantité de package
                         $TProducts = array_keys($TStack[count($TStack) - 1]['package']);
                         $TProductsChilds = array_keys($TStack[count($TStack) - 1]['childs']);
                         if ($TProductsChilds == $TProducts) {
                             // Il s'agit d'un package
                             // On récupére la quantité
                             $first_child_id = $TProducts[0];
                             $document_qty = $TStack[count($TStack) - 1]['package'][$first_child_id];
                             $base_qty = $TStack[count($TStack) - 1]['childs'][$first_child_id][1];
                             $TStack[count($TStack) - 1]['package_qty'] = $document_qty / $base_qty;
                             $package_qty = $TStack[count($TStack) - 1]['package_qty'];
                         }
                         array_pop($TStack);
                     }
                 }
                 $curY = $nexY;
                 $pdf->SetFont('', '', $default_font_size - 1);
                 // Into loop to work with multipage
                 $pdf->SetTextColor(0, 0, 0);
                 $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();
                 // Description of product line
                 $curX = $this->posxdesc - 1;
                 $showpricebeforepagebreak = 1;
                 $pdf->startTransaction();
                 pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxtva - $curX, 3, $curX, $curY, $hideref, $hidedesc);
                 $pageposafter = $pdf->getPage();
                 if ($pageposafter > $pageposbefore) {
                     $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->posxtva - $curX, 4, $curX, $curY, $hideref, $hidedesc);
                     $pageposafter = $pdf->getPage();
                     $posyafter = $pdf->GetY();
                     if ($posyafter > $this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot)) {
                         if ($i == $nblignes - 1) {
                             $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
                         $showpricebeforepagebreak = 0;
                     }
                 } else {
                     $pdf->commitTransaction();
                 }
                 $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 is moved completely on next page
                 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
                     $pdf->setPage($pageposafter);
                     $curY = $tab_top_newpage;
                 }
                 $pdf->SetFont('', '', $default_font_size - 1);
                 // On repositionne la police par defaut
                 // VAT Rate
                 if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) {
                     // Si on ne doit masquer que les sous-produits
                     if ($hidedetails && !$inPackage && $conf->global->SUBTOTAL_ONLY_HIDE_SUBPRODUCTS_PRICES) {
                         $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, 0);
                     } else {
                         $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
                     }
                     $pdf->SetXY($this->posxtva, $curY);
                     $pdf->MultiCell($this->posxup - $this->posxtva - 0.8, 3, $vat_rate, 0, 'R');
                 }
                 // Unit price before discount
                 if ($hidedetails && !$inPackage && $conf->global->SUBTOTAL_ONLY_HIDE_SUBPRODUCTS_PRICES) {
                     $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, 0);
                 } else {
                     $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);
                 // Booléen pour déterminer s'il s'agit d'une ligne de titre ou non
                 $isTitle = false;
                 // Quantity
                 // Récupération de la quantité à afficher
                 if ($conf->global->SUBTOTAL_IF_HIDE_PRICES_SHOW_QTY) {
                     if ($conf->global->SUBTOTAL_SHOW_QTY_ON_TITLES && $package_qty > 0) {
                         $qty = $package_qty;
                     } else {
                         $qty = pdf_getlineqty($object, $i, $outputlangs, 0);
                     }
                 } else {
                     if ($conf->global->SUBTOTAL_SHOW_QTY_ON_TITLES && $package_qty > 0) {
                         $qty = $package_qty;
                     } else {
                         $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails);
                     }
                 }
                 $pdf->SetXY($this->posxqty, $curY);
                 $pdf->MultiCell($this->posxdiscount - $this->posxqty - 0.8, 3, $qty, 0, 'R');
                 // Enough for 6 chars
                 // 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->postotalht - $this->posxdiscount + 2, 3, $remise_percent, 0, 'R');
                 }
                 // Total HT line
                 if ($hidedetails && !$inPackage && $conf->global->SUBTOTAL_ONLY_HIDE_SUBPRODUCTS_PRICES) {
                     $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, 0);
                 } else {
                     $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);
                 // Collecte des totaux par valeur de tva dans $this->tva["taux"]=total_tva
                 $tvaligne = $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 == '') && (!empty($localtax1_rate) || !empty($localtax2_rate))) {
                     $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $object->thirdparty, $mysoc);
                     $localtax1_type = $localtaxtmp_array[0];
                     $localtax2_type = $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 & 0x1) == 0x1) {
                     $vatrate .= '*';
                 }
                 if (!isset($this->tva[$vatrate])) {
                     $this->tva[$vatrate] = '';
                 }
                 $this->tva[$vatrate] += $tvaligne;
                 // Add line
                 if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < $nblignes - 1) {
                     $pdf->setPage($pageposafter);
                     $pdf->SetLineStyle(array('dash' => '1,1', 'color' => array(210, 210, 210)));
                     //$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;
                 // Passe espace entre les lignes
                 // 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);
                     } else {
                         $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
                     }
                     $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 (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);
                     } else {
                         $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
                     }
                     $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);
                 $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);
                 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
             }
             // Affiche zone infos
             $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
             if (!$conf->global->SUBTOTAL_HIDE_DOCUMENT_TOTAL) {
                 // Affiche zone totaux
                 $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
             }
             // Affiche zone versements
             if ($deja_regle) {
                 $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs);
             }
             // Pied de page
             $this->_pagefoot($pdf, $object, $outputlangs);
             if (method_exists($pdf, 'AliasNbPages')) {
                 $pdf->AliasNbPages();
             }
             $pdf->Close();
             $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 (!empty($conf->global->MAIN_UMASK)) {
                 @chmod($file, octdec($conf->global->MAIN_UMASK));
             }
             return 1;
             // Pas d'erreur
         } else {
             $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
             return 0;
         }
     } else {
         $this->error = $langs->trans("ErrorConstantNotDefined", "COMMANDE_OUTPUTDIR");
         return 0;
     }
     $this->error = $langs->trans("ErrorUnknown");
     return 0;
     // Erreur par defaut
 }