From 42dee75ba3dc3a5ed83987f880c4c3b0e306755e Mon Sep 17 00:00:00 2001 From: wdammak <26695620+wdammak@users.noreply.github.com> Date: Tue, 1 May 2018 23:32:35 +0100 Subject: [PATCH 01/10] Add: Overload styles files from a current folder of module & theme My goal is to overload css files only for the current module and without changing the source code of the module but just by adding a folder style in the module folder. Then just place the css files to overload in this folder they will be automatically added in the head. The same method is applied to the current theme. To test, for example, place a custom.css file in the societe/style/custom.css folder and check the head of a company module page. --- htdocs/main.inc.php | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index f1d6487d5de..19e74d1ddc2 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1206,6 +1206,54 @@ function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs print ''."\n"; if (! empty($conf->global->MAIN_FIX_FLASH_ON_CHROME)) print ''."\n".''."\n"; + //Overload css files to the current theme + // Check if the /theme/nameoftheme/style folder exists and Add the contains css files to head + if (file_exists(dirname(dol_buildpath($conf->css, 0))."/style")) + { + //browse the css dir and add the contains css files + if ($handle = opendir(dirname(dol_buildpath($conf->css, 0))."/style")) + { + while (false !== ($entry = readdir($handle))) + { + list($filename, $extension) = explode(".", $entry); + if ($entry !== '.' && $entry !== '..' && $extension == 'css') + { + print ''."\n"; + } + } + closedir($handle); + } + } + + //Overload css files to the current module + // Check if the /module/style folder exists and Add the contains css files to head + $cur_modulepart = explode("/",$_SERVER["PHP_SELF"]); + if(is_array($cur_modulepart) && count($cur_modulepart)>0) + { + foreach($conf->modules as $module) + { + if(in_array($module, $cur_modulepart)) + { + if (file_exists(getcwd().DIRECTORY_SEPARATOR."style")) + { + //browse the style dir and add the contains css files + if ($handle = opendir(getcwd().DIRECTORY_SEPARATOR."style")) + { + while (false !== ($entry = readdir($handle))) + { + list($filename, $extension) = explode(".", $entry); + if ($entry !== '.' && $entry !== '..' && $extension == 'css') + { + print ''."\n"; + } + } + closedir($handle); + } + } + } + } + } + // CSS forced by modules (relative url starting with /) if (! empty($conf->modules_parts['css'])) { From bca8d0844e97765139ad0babfcd7f033d4e06f03 Mon Sep 17 00:00:00 2001 From: wdammak <26695620+wdammak@users.noreply.github.com> Date: Thu, 3 May 2018 00:38:38 +0100 Subject: [PATCH 02/10] Prepare the adding pdf models to the stock module --- htdocs/install/mysql/migration/7.0.0-8.0.0.sql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/install/mysql/migration/7.0.0-8.0.0.sql b/htdocs/install/mysql/migration/7.0.0-8.0.0.sql index 3ca87e97053..51b83612983 100644 --- a/htdocs/install/mysql/migration/7.0.0-8.0.0.sql +++ b/htdocs/install/mysql/migration/7.0.0-8.0.0.sql @@ -451,3 +451,7 @@ ALTER TABLE llx_accounting_journal ADD UNIQUE INDEX uk_accounting_journal_code ( UPDATE llx_c_email_templates SET lang = '' WHERE lang IS NULL; +-- Warehouse +ALTER TABLE `llx_entrepot` ADD `model_pdf` VARCHAR(255) AFTER `fk_user_author`; +ALTER TABLE `llx_stock_mouvement` ADD `model_pdf` VARCHAR(255) AFTER `origintype`; + From 2cf1aa967c5a327f4968a07b5620ad999c19ad98 Mon Sep 17 00:00:00 2001 From: wdammak <26695620+wdammak@users.noreply.github.com> Date: Thu, 3 May 2018 01:01:05 +0100 Subject: [PATCH 03/10] Add warehouse models pdf --- htdocs/core/modules/modStock.class.php | 83 +- .../doc/doc_generic_stock_odt.modules.php | 503 +++++++ .../stock/doc/pdf_standard.modules.php | 1158 ++++++++++++++++ .../stock/doc/pdf_stdmouvement.modules.php | 1159 +++++++++++++++++ .../modules/stock/modules_stock.class.php | 90 ++ htdocs/core/modules/stock/modules_stock.php | 52 + 6 files changed, 3041 insertions(+), 4 deletions(-) create mode 100644 htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php create mode 100644 htdocs/core/modules/stock/doc/pdf_standard.modules.php create mode 100644 htdocs/core/modules/stock/doc/pdf_stdmouvement.modules.php create mode 100644 htdocs/core/modules/stock/modules_stock.class.php create mode 100644 htdocs/core/modules/stock/modules_stock.php diff --git a/htdocs/core/modules/modStock.class.php b/htdocs/core/modules/modStock.class.php index ca518ed8851..55c0bfe6410 100644 --- a/htdocs/core/modules/modStock.class.php +++ b/htdocs/core/modules/modStock.class.php @@ -60,7 +60,7 @@ class modStock extends DolibarrModules $this->picto='stock'; // Data directories to create when module is enabled - $this->dirs = array(); + $this->dirs = array("/stock/temp"); $this->config_page_url = array("stock.php"); @@ -70,9 +70,38 @@ class modStock extends DolibarrModules $this->langfiles = array("stocks"); // Constants - $this->const = array( - 0=>array('STOCK_ALLOW_NEGATIVE_TRANSFER','chaine','1','',1) - ); + $this->const = array(); + $r=0; + + $this->const[$r] = array('STOCK_ALLOW_NEGATIVE_TRANSFER','chaine','1','',1); + + $r++; + $this->const[$r][0] = "STOCK_ADDON_PDF"; + $this->const[$r][1] = "chaine"; + $this->const[$r][2] = "Standard"; + $this->const[$r][3] = 'Name of PDF model of stock'; + $this->const[$r][4] = 0; + + $r++; + $this->const[$r][0] = "MOUVEMENT_ADDON_PDF"; + $this->const[$r][1] = "chaine"; + $this->const[$r][2] = "StdMouvement"; + $this->const[$r][3] = 'Name of PDF model of stock mouvement'; + $this->const[$r][4] = 0; + + $r++; + $this->const[$r][0] = "STOCK_ADDON_PDF_ODT_PATH"; + $this->const[$r][1] = "chaine"; + $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/stocks"; + $this->const[$r][3] = ""; + $this->const[$r][4] = 0; + + $r++; + $this->const[$r][0] = "MOUVEMENT_ADDON_PDF_ODT_PATH"; + $this->const[$r][1] = "chaine"; + $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/stocks/mouvements"; + $this->const[$r][3] = ""; + $this->const[$r][4] = 0; // Boxes $this->boxes = array(); @@ -266,4 +295,50 @@ class modStock extends DolibarrModules ); } + + + /** + * Function called when module is enabled. + * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + function init($options='') + { + global $conf,$langs; + + // Permissions + $this->remove($options); + + //ODT template + $src=DOL_DOCUMENT_ROOT.'/install/doctemplates/stock/template_stock.odt'; + $dirodt=DOL_DATA_ROOT.'/doctemplates/stock'; + $dest=$dirodt.'/template_stock.odt'; + + if (file_exists($src) && ! file_exists($dest)) + { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + dol_mkdir($dirodt); + $result=dol_copy($src,$dest,0,0); + if ($result < 0) + { + $langs->load("errors"); + $this->error=$langs->trans('ErrorFailToCopyFile',$src,$dest); + return 0; + } + } + + $sql = array(); + + $sql = array( + "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->db->escape($this->const[1][2])."' AND type = 'stock' AND entity = ".$conf->entity, + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[1][2])."','stock',".$conf->entity.")", + "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->db->escape($this->const[2][2])."' AND type = 'mouvement' AND entity = ".$conf->entity, + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[2][2])."','mouvement',".$conf->entity.")", + ); + + return $this->_init($sql,$options); + } } diff --git a/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php b/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php new file mode 100644 index 00000000000..0cadf3362d4 --- /dev/null +++ b/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php @@ -0,0 +1,503 @@ + + * Copyright (C) 2012 Juanjo Menent +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* or see http://www.gnu.org/ +*/ + +/** + * \file htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php + * \ingroup societe + * \brief File of class to build ODT documents for stocks/services + */ + +require_once DOL_DOCUMENT_ROOT.'/core/modules/stock/modules_stock.class.php'; +require_once DOL_DOCUMENT_ROOT.'/stock/class/stock.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php'; + + +/** + * Class to build documents using ODF templates generator + */ +class doc_generic_stock_odt extends ModelePDFStock +{ + var $emetteur; // Objet societe qui emet + + var $phpmin = array(5,2,0); // Minimum version of PHP required by module + var $version = 'dolibarr'; + + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + function __construct($db) + { + global $conf,$langs,$mysoc; + + $langs->load("main"); + $langs->load("companies"); + + $this->db = $db; + $this->name = "ODT templates"; + $this->description = $langs->trans("DocumentModelOdt"); + $this->scandir = 'STOCK_ADDON_PDF_ODT_PATH'; // Name of constant that is used to save list of directories to scan + + // Dimension page pour format A4 + $this->type = 'odt'; + $this->page_largeur = 0; + $this->page_hauteur = 0; + $this->format = array($this->page_largeur,$this->page_hauteur); + $this->marge_gauche=0; + $this->marge_droite=0; + $this->marge_haute=0; + $this->marge_basse=0; + + $this->option_logo = 1; // Affiche logo + $this->option_tva = 0; // Gere option tva STOCK_TVAOPTION + $this->option_modereg = 0; // Affiche mode reglement + $this->option_condreg = 0; // Affiche conditions reglement + $this->option_codeproduitservice = 0; // Affiche code produit-service + $this->option_multilang = 1; // Dispo en plusieurs langues + $this->option_escompte = 0; // Affiche si il y a eu escompte + $this->option_credit_note = 0; // Support credit notes + $this->option_freetext = 1; // Support add of a personalised text + $this->option_draft_watermark = 0; // Support add of a watermark on drafts + + // Recupere emetteur + $this->emetteur=$mysoc; + if (! $this->emetteur->country_code) $this->emetteur->country_code=substr($langs->defaultlang,-2); // By default if not defined + } + + + /** + * Return description of a module + * + * @param Translate $langs Lang object to use for output + * @return string Description + */ + function info($langs) + { + global $conf,$langs; + + $langs->load("companies"); + $langs->load("errors"); + + $form = new Form($this->db); + + $texte = $this->description.".
\n"; + $texte.= '
'; + $texte.= ''; + $texte.= ''; + $texte.= ''; + if ($conf->global->MAIN_PROPAL_CHOOSE_ODT_DOCUMENT > 0) + { + $texte.= ''; + $texte.= ''; + $texte.= ''; + } + $texte.= ''; + + // List of directories area + $texte.= ''; + + $texte.= ''; + $texte.= ''; + + $texte.= '
'; + $texttitle=$langs->trans("ListOfDirectories"); + $listofdir=explode(',',preg_replace('/[\r\n]+/',',',trim($conf->global->STOCK_ADDON_PDF_ODT_PATH))); + $listoffiles=array(); + foreach($listofdir as $key=>$tmpdir) + { + $tmpdir=trim($tmpdir); + $tmpdir=preg_replace('/DOL_DATA_ROOT/',DOL_DATA_ROOT,$tmpdir); + if (! $tmpdir) { + unset($listofdir[$key]); continue; + } + if (! is_dir($tmpdir)) $texttitle.=img_warning($langs->trans("ErrorDirNotFound",$tmpdir),0); + else + { + $tmpfiles=dol_dir_list($tmpdir,'files',0,'\.(ods|odt)'); + if (count($tmpfiles)) $listoffiles=array_merge($listoffiles,$tmpfiles); + } + } + $texthelp=$langs->trans("ListOfDirectoriesForModelGenODT"); + // Add list of substitution keys + $texthelp.='
'.$langs->trans("FollowingSubstitutionKeysCanBeUsed").'
'; + $texthelp.=$langs->transnoentitiesnoconv("FullListOnOnlineDocumentation"); // This contains an url, we don't modify it + + $texte.= $form->textwithpicto($texttitle,$texthelp,1,'help','',1); + $texte.= '
'; + $texte.= ''; + $texte.= '
'; + $texte.= ''; + $texte.= '
'; + + // Scan directories + if (count($listofdir)) + { + $texte.=$langs->trans("NumberOfModelFilesFound").': '.count($listoffiles).''; + + /*if ($conf->global->MAIN_STOCK_CHOOSE_ODT_DOCUMENT > 0) + { + // Model for creation + $liste=ModelePDFStock::liste_modeles($this->db); + $texte.= ''; + $texte.= ''; + $texte.= ''; + $texte.= '"; + + $texte.= ''; + $texte.= ''; + $texte.= '"; + $texte.= ''; + + $texte.= ''; + $texte.= '"; + $texte.= '
'.$langs->trans("DefaultModelPropalCreate").''; + $texte.= $form->selectarray('value2',$liste,$conf->global->STOCK_ADDON_PDF_ODT_DEFAULT); + $texte.= "
'.$langs->trans("DefaultModelPropalToBill").''; + $texte.= $form->selectarray('value3',$liste,$conf->global->STOCK_ADDON_PDF_ODT_TOBILL); + $texte.= "
'.$langs->trans("DefaultModelPropalClosed").''; + $texte.= $form->selectarray('value4',$liste,$conf->global->STOCK_ADDON_PDF_ODT_CLOSED); + $texte.= "
'; + }*/ + } + + $texte.= '
'; + $texte.= $langs->trans("ExampleOfDirectoriesForModelGen"); + $texte.= '
'; + $texte.= '
'; + + return $texte; + } + + /** + * Function to build a document on disk using the generic odt module. + * + * @param Stock $object Object source to build document + * @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 if OK, <=0 if KO + */ + function write_file($object,$outputlangs,$srctemplatepath,$hidedetails=0,$hidedesc=0,$hideref=0) + { + global $stock,$langs,$conf,$mysoc,$hookmanager,$user; + + if (empty($srctemplatepath)) + { + dol_syslog("doc_generic_odt::write_file parameter srctemplatepath empty", LOG_WARNING); + return -1; + } + + // Add odtgeneration hook + if (! is_object($hookmanager)) + { + include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; + $hookmanager=new HookManager($this->db); + } + $hookmanager->initHooks(array('odtgeneration')); + global $action; + + if (! is_object($outputlangs)) $outputlangs=$langs; + $sav_charset_output=$outputlangs->charset_output; + $outputlangs->charset_output='UTF-8'; + + $outputlangs->load("main"); + $outputlangs->load("dict"); + $outputlangs->load("companies"); + $outputlangs->load("bills"); + if ($conf->produit->dir_output) + { + // If $object is id instead of object + if (! is_object($object)) + { + $id = $object; + $object = new Stock($this->db); + $result=$object->fetch($id); + if ($result < 0) + { + dol_print_error($this->db,$object->error); + return -1; + } + } + $stockFournisseur = new StockFournisseur($this->db); + $supplierprices = $stockFournisseur->list_stock_fournisseur_price($object->id); + $object->supplierprices = $supplierprices; + + $dir = $conf->produit->dir_output; + $objectref = dol_sanitizeFileName($object->ref); + if (! preg_match('/specimen/i',$objectref)) $dir.= "/" . $objectref; + $file = $dir . "/" . $objectref . ".odt"; + + if (! file_exists($dir)) + { + if (dol_mkdir($dir) < 0) + { + $this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir); + return -1; + } + } + + if (file_exists($dir)) + { + //print "srctemplatepath=".$srctemplatepath; // Src filename + $newfile=basename($srctemplatepath); + $newfiletmp=preg_replace('/\.od(t|s)/i','',$newfile); + $newfiletmp=preg_replace('/template_/i','',$newfiletmp); + $newfiletmp=preg_replace('/modele_/i','',$newfiletmp); + + $newfiletmp=$objectref.'_'.$newfiletmp; + + // Get extension (ods or odt) + $newfileformat=substr($newfile, strrpos($newfile, '.')+1); + if ( ! empty($conf->global->MAIN_DOC_USE_TIMING)) + { + $format=$conf->global->MAIN_DOC_USE_TIMING; + if ($format == '1') $format='%Y%m%d%H%M%S'; + $filename=$newfiletmp.'-'.dol_print_date(dol_now(),$format).'.'.$newfileformat; + } + else + { + $filename=$newfiletmp.'.'.$newfileformat; + } + $file=$dir.'/'.$filename; + //print "newdir=".$dir; + //print "newfile=".$newfile; + //print "file=".$file; + //print "conf->produit->dir_temp=".$conf->produit->dir_temp; + + dol_mkdir($conf->produit->dir_temp); + + + // If CUSTOMER contact defined on stock, we use it + $usecontact=false; + $arrayidcontact=$object->getIdContact('external','CUSTOMER'); + if (count($arrayidcontact) > 0) + { + $usecontact=true; + $result=$object->fetch_contact($arrayidcontact[0]); + } + + // Recipient name + if (! empty($usecontact)) + { + // On peut utiliser le nom de la societe du contact + if (! empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT)) $socobject = $object->contact; + else { + $socobject = $object->thirdparty; + // if we have a CUSTOMER contact and we dont use it as recipient we store the contact object for later use + $contactobject = $object->contact; + } + } + else + { + $socobject=$object->thirdparty; + } + // Make substitution + $substitutionarray=array( + '__FROM_NAME__' => $this->emetteur->name, + '__FROM_EMAIL__' => $this->emetteur->email, + '__TOTAL_TTC__' => $object->total_ttc, + '__TOTAL_HT__' => $object->total_ht, + '__TOTAL_VAT__' => $object->total_vat + ); + complete_substitutions_array($substitutionarray, $langs, $object); + // Call the ODTSubstitution hook + $parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs,'substitutionarray'=>&$substitutionarray); + $reshook=$hookmanager->executeHooks('ODTSubstitution',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks + + // Line of free text + $newfreetext=''; + $paramfreetext='stock_FREE_TEXT'; + if (! empty($conf->global->$paramfreetext)) + { + $newfreetext=make_substitutions($conf->global->$paramfreetext,$substitutionarray); + } + + // Open and load template + require_once ODTPHP_PATH.'odf.php'; + try { + $odfHandler = new odf( + $srctemplatepath, + array( + 'PATH_TO_TMP' => $conf->produit->dir_temp, + 'ZIP_PROXY' => 'PclZipProxy', // PhpZipProxy or PclZipProxy. Got "bad compression method" error when using PhpZipProxy. + 'DELIMITER_LEFT' => '{', + 'DELIMITER_RIGHT' => '}' + ) + ); + } + catch(Exception $e) + { + $this->error=$e->getMessage(); + return -1; + } + // After construction $odfHandler->contentXml contains content and + // [!-- BEGIN row.lines --]*[!-- END row.lines --] has been replaced by + // [!-- BEGIN lines --]*[!-- END lines --] + //print html_entity_decode($odfHandler->__toString()); + //print exit; + + $object->fetch_optionals(); + + // Make substitutions into odt of freetext + try { + $odfHandler->setVars('free_text', $newfreetext, true, 'UTF-8'); + } + catch(OdfException $e) + { + } + + // Define substitution array + $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object); + $array_object_from_properties = $this->get_substitutionarray_each_var_object($object, $outputlangs); + //$array_objet=$this->get_substitutionarray_object($object,$outputlangs); + $array_user=$this->get_substitutionarray_user($user,$outputlangs); + $array_soc=$this->get_substitutionarray_mysoc($mysoc,$outputlangs); + $array_thirdparty=$this->get_substitutionarray_thirdparty($socobject,$outputlangs); + $array_other=$this->get_substitutionarray_other($outputlangs); + // retrieve contact information for use in stock as contact_xxx tags + $array_thirdparty_contact = array(); + if ($usecontact) $array_thirdparty_contact=$this->get_substitutionarray_contact($contactobject,$outputlangs,'contact'); + + $tmparray = array_merge($substitutionarray,$array_object_from_properties,$array_user,$array_soc,$array_thirdparty,$array_other,$array_thirdparty_contact); + complete_substitutions_array($tmparray, $outputlangs, $object); + + // Call the ODTSubstitution hook + $parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs,'substitutionarray'=>&$tmparray); + $reshook=$hookmanager->executeHooks('ODTSubstitution',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks + + foreach($tmparray as $key=>$value) + { + try { + if (preg_match('/logo$/',$key)) // Image + { + if (file_exists($value)) $odfHandler->setImage($key, $value); + else $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8'); + } + else // Text + { + $odfHandler->setVars($key, $value, true, 'UTF-8'); + } + } + catch(OdfException $e) + { + } + } + // Replace tags of lines + try + { + $listlines = $odfHandler->setSegment('supplierprices'); + if(!empty($object->supplierprices)){ + foreach ($object->supplierprices as $supplierprice) + { + $array_lines = $this->get_substitutionarray_each_var_object($supplierprice, $outputlangs); + complete_substitutions_array($array_lines, $outputlangs, $object, $supplierprice, "completesubstitutionarray_lines"); + // Call the ODTSubstitutionLine hook + $parameters=array('odfHandler'=>&$odfHandler,'file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs,'substitutionarray'=>&$array_lines,'line'=>$supplierprice); + $reshook=$hookmanager->executeHooks('ODTSubstitutionLine',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks + foreach($array_lines as $key => $val) + { + try + { + $listlines->setVars($key, $val, true, 'UTF-8'); + } + catch(OdfException $e) + { + } + catch(SegmentException $e) + { + } + } + $listlines->merge(); + } + } + $odfHandler->mergeSegment($listlines); + } + catch(OdfException $e) + { + $this->error=$e->getMessage(); + dol_syslog($this->error, LOG_WARNING); + return -1; + } + + // Replace labels translated + $tmparray=$outputlangs->get_translations_for_substitutions(); + foreach($tmparray as $key=>$value) + { + try { + $odfHandler->setVars($key, $value, true, 'UTF-8'); + } + catch(OdfException $e) + { + } + } + + // Call the beforeODTSave hook + $parameters=array('odfHandler'=>&$odfHandler,'file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs); + $reshook=$hookmanager->executeHooks('beforeODTSave',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks + + // Write new file + if (!empty($conf->global->MAIN_ODT_AS_PDF)) { + try { + $odfHandler->exportAsAttachedPDF($file); + }catch (Exception $e){ + $this->error=$e->getMessage(); + return -1; + } + } + else { + try { + $odfHandler->saveToDisk($file); + }catch (Exception $e){ + $this->error=$e->getMessage(); + return -1; + } + } + + $reshook=$hookmanager->executeHooks('afterODTCreation',$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)); + + $odfHandler=null; // Destroy object + + $this->result = array('fullpath'=>$file); + + return 1; // Success + } + else + { + $this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir); + return -1; + } + } + + return -1; + } + +} + diff --git a/htdocs/core/modules/stock/doc/pdf_standard.modules.php b/htdocs/core/modules/stock/doc/pdf_standard.modules.php new file mode 100644 index 00000000000..5825bd693f5 --- /dev/null +++ b/htdocs/core/modules/stock/doc/pdf_standard.modules.php @@ -0,0 +1,1158 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/stock/doc/pdf_standard.modules.php + * \ingroup societe + * \brief File of class to build PDF documents for stocks/services + */ + +require_once DOL_DOCUMENT_ROOT.'/core/modules/stock/modules_stock.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; +require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; + + +/** + * Class to build documents using ODF templates generator + */ +class pdf_standard extends ModelePDFStock +{ + /** + * @var DoliDb Database handler + */ + public $db; + + /** + * @var string model name + */ + public $name; + + /** + * @var string model description (short text) + */ + public $description; + + /** + * @var string document type + */ + public $type; + + /** + * @var array() Minimum version of PHP required by module. + * e.g.: PHP ≥ 5.3 = array(5, 3) + */ + public $phpmin = array(5, 2); + + /** + * Dolibarr version of the loaded document + * @public string + */ + public $version = 'dolibarr'; + + public $page_largeur; + public $page_hauteur; + public $format; + public $marge_gauche; + public $marge_droite; + public $marge_haute; + public $marge_basse; + + public $emetteur; // Objet societe qui emet + + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + global $conf,$langs,$mysoc; + + $langs->load("main"); + $langs->load("companies"); + + $this->db = $db; + $this->name = "standard"; + $this->description = $langs->trans("DocumentModelStandardPDF"); + + // Dimension page pour format A4 + $this->type = 'pdf'; + $formatarray=pdf_getFormat(); + $this->page_largeur = $formatarray['width']; + $this->page_hauteur = $formatarray['height']; + $this->format = array($this->page_largeur,$this->page_hauteur); + $this->marge_gauche=isset($conf->global->MAIN_PDF_MARGIN_LEFT)?$conf->global->MAIN_PDF_MARGIN_LEFT:10; + $this->marge_droite=isset($conf->global->MAIN_PDF_MARGIN_RIGHT)?$conf->global->MAIN_PDF_MARGIN_RIGHT:10; + $this->marge_haute =isset($conf->global->MAIN_PDF_MARGIN_TOP)?$conf->global->MAIN_PDF_MARGIN_TOP:10; + $this->marge_basse =isset($conf->global->MAIN_PDF_MARGIN_BOTTOM)?$conf->global->MAIN_PDF_MARGIN_BOTTOM:10; + + $this->option_logo = 1; // Affiche logo + $this->option_codestockservice = 0; // Affiche code stock-service + $this->option_multilang = 1; // Dispo en plusieurs langues + $this->option_freetext = 0; // Support add of a personalised text + + // Recupere emetteur + $this->emetteur=$mysoc; + if (! $this->emetteur->country_code) $this->emetteur->country_code=substr($langs->defaultlang,-2); // By default if not defined + + // Define position of columns + $this->wref = 15; + $this->posxdesc=$this->marge_gauche+1; + $this->posxlabel=$this->posxdesc+$this->wref; + $this->posxtva=80; + $this->posxqty=95; + $this->posxup=115; + $this->posxunit=135; + $this->posxdiscount=155; + $this->postotalht=175; + + if (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) || ! empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) $this->posxtva=$this->posxup; + $this->posxpicture=$this->posxtva - (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH)?20:$conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH); // width of images + if ($this->page_largeur < 210) // To work with US executive format + { + $this->posxpicture-=20; + $this->posxtva-=20; + $this->posxup-=20; + $this->posxqty-=20; + $this->posxunit-=20; + $this->posxdiscount-=20; + $this->postotalht-=20; + } + $this->tva=array(); + $this->localtax1=array(); + $this->localtax2=array(); + $this->atleastoneratenotnull=0; + $this->atleastonediscount=0; + } + + + /** + * Function to build a document on disk using the generic odt module. + * + * @param Stock $object Object source to build document + * @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 if OK, <=0 if 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("stocks"); + $outputlangs->load("orders"); + $outputlangs->load("deliveries"); + + $nblignes = count($object->lines); + + if ($conf->stock->dir_output) + { + // Definition of $dir and $file + if ($object->specimen) + { + $dir = $conf->stock->dir_output; + $file = $dir . "/SPECIMEN.pdf"; + } + else + { + $objectref = dol_sanitizeFileName($object->ref); + $dir = $conf->stock->dir_output . "/" . $objectref; + $file = $dir . "/" . $objectref . ".pdf"; + } + + $stockFournisseur = new ProductFournisseur($this->db); + $supplierprices = $stockFournisseur->list_product_fournisseur_price($object->id); + $object->supplierprices = $supplierprices; + + $productstatic=new Product($db); + + if (! file_exists($dir)) + { + if (dol_mkdir($dir) < 0) + { + $this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir); + return -1; + } + } + + 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 + $pdf->SetAutoPageBreak(1,0); + + $heightforinfotot = 40; // 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) + + 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("Stock")); + $pdf->SetCreator("Dolibarr ".DOL_VERSION); + $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs))); + $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Stock")." ".$outputlangs->convToOutputCharset($object->libelle)); + 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->MultiCell(0, 3, ''); // Set interline to 3 + $pdf->SetTextColor(0,0,0); + + $tab_top = 42; + $tab_top_newpage = (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)?42:10); + $tab_height = 130; + $tab_height_newpage = 150; + + /* ************************************************************************** */ + /* */ + /* Affichage de la liste des produits de l'entrepot */ + /* */ + /* ************************************************************************** */ + + $nexY+=5; + $nexY = $pdf->GetY(); + $nexY+=10; + + $totalunit=0; + $totalvalue=$totalvaluesell=0; + + $sql = "SELECT p.rowid as rowid, p.ref, p.label as produit, p.tobatch, p.fk_product_type as type, p.pmp as ppmp, p.price, p.price_ttc, p.entity,"; + $sql.= " ps.reel as value"; + $sql.= " FROM ".MAIN_DB_PREFIX."product_stock as ps, ".MAIN_DB_PREFIX."product as p"; + $sql.= " WHERE ps.fk_product = p.rowid"; + $sql.= " AND ps.reel <> 0"; // We do not show if stock is 0 (no product in this warehouse) + $sql.= " AND ps.fk_entrepot = ".$object->id; + $sql.= $db->order($sortfield,$sortorder); + + //dol_syslog('List products', LOG_DEBUG); + $resql = $db->query($sql); + if ($resql) + { + $num = $db->num_rows($resql); + $i = 0; + $nblignes = $num; + for ($i = 0 ; $i < $nblignes ; $i++) + { + $objp = $db->fetch_object($resql); + + // Multilangs + if (! empty($conf->global->MAIN_MULTILANGS)) // si l'option est active + { + $sql = "SELECT label"; + $sql.= " FROM ".MAIN_DB_PREFIX."product_lang"; + $sql.= " WHERE fk_product=".$objp->rowid; + $sql.= " AND lang='". $langs->getDefaultLang() ."'"; + $sql.= " LIMIT 1"; + + $result = $db->query($sql); + if ($result) + { + $objtp = $db->fetch_object($result); + if ($objtp->label != '') $objp->produit = $objtp->label; + } + } + + $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) // There is a pagebreak + { + $pdf->rollbackTransaction(true); + $pageposafter=$pageposbefore; + //print $pageposafter.'-'.$pageposbefore;exit; + $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it. + pdf_writelinedesc($pdf,$object,$i,$outputlangs,$this->posxtva-$curX,4,$curX,$curY,$hideref,$hidedesc); + $pageposafter=$pdf->getPage(); + $posyafter=$pdf->GetY(); + if ($posyafter > ($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))) // There is no space left for total+free text + { + if ($i == ($nblignes-1)) // No more lines, and no space left to show total, so we create a new page + { + $pdf->AddPage('','',true); + if (! empty($tplidx)) $pdf->useTemplate($tplidx); + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); + $pdf->setPage($pageposafter+1); + } + } + else + { + // We found a page break + $showpricebeforepagebreak=0; + } + } + else // No pagebreak + { + $pdf->commitTransaction(); + } + $posYAfterDescription=$pdf->GetY(); + + $nexY = $pdf->GetY(); + $pageposafter=$pdf->getPage(); + + $pdf->setPage($pageposbefore); + $pdf->setTopMargin($this->marge_haute); + $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. + + // We suppose that a too long description 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 + + $productstatic->id=$objp->rowid; + $productstatic->ref = $objp->ref; + $productstatic->label = $objp->produit; + $productstatic->type=$objp->type; + $productstatic->entity=$objp->entity; + $productstatic->status_batch=$objp->tobatch; + + // Ref. + $pdf->SetXY($this->posxdesc, $curY); + $pdf->MultiCell($this->wref, 3, $productstatic->ref, 0, 'L'); + + // Label + $pdf->SetXY($this->posxlabel+0.8, $curY); + $pdf->MultiCell($this->posxqty-$this->posxlabel-0.8, 3, $objp->produit, 0, 'L'); + + // Quantity + $valtoshow=price2num($objp->value, 'MS'); + $towrite = (empty($valtoshow)?'0':$valtoshow); + + $pdf->SetXY($this->posxqty, $curY); + $pdf->MultiCell($this->posxup-$this->posxqty-0.8, 3, $towrite, 0, 'R'); + + $totalunit+=$objp->value; + + $pdf->SetXY($this->posxup, $curY); + $pdf->MultiCell($this->posxunit-$this->posxup-0.8, 3, price(price2num($objp->ppmp,'MU'), 0, $outputlangs), 0, 'R'); + + // Total PMP + $pdf->SetXY($this->posxunit, $curY); + $pdf->MultiCell($this->posxdiscount-$this->posxunit-0.8, 3, price(price2num($objp->ppmp*$objp->value,'MT'), 0, $outputlangs), 0, 'R'); + $totalvalue+=price2num($objp->ppmp*$objp->value,'MT'); + + // Price sell min + if (empty($conf->global->PRODUIT_MULTIPRICES)) + { + $pricemin=$objp->price; + $pdf->SetXY($this->posxdiscount, $curY); + $pdf->MultiCell($this->postotalht-$this->posxdiscount, 3, price(price2num($pricemin,'MU'), 0, $outputlangs), 0, 'R', 0); + + // Total sell min + $pdf->SetXY($this->postotalht, $curY); + $pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->postotalht, 3, price(price2num($pricemin*$objp->value,'MT'), 0, $outputlangs), 0, 'R', 0); + } + $totalvaluesell+=price2num($pricemin*$objp->value,'MT'); + + // 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(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); + } + } + + $db->free($resql); + + /** + * footer table + */ + $nexY = $pdf->GetY(); + $nexY+=2; + $curY = $nexY; + + $pdf->SetLineStyle(array('dash'=>'0','color'=>array(220,26,26))); + $pdf->line($this->marge_gauche, $curY-1, $this->page_largeur-$this->marge_droite, $curY-1); + $pdf->SetLineStyle(array('dash'=>0)); + + $pdf->SetFont('','B',$default_font_size-1); + $pdf->SetTextColor(0,0,120); + + // Ref. + $pdf->SetXY($this->posxdesc, $curY); + $pdf->MultiCell($this->wref, 3, $langs->trans("Total"), 0, 'L'); + + // Quantity + $valtoshow=price2num($totalunit, 'MS'); + $towrite = empty($valtoshow)?'0':$valtoshow; + + $pdf->SetXY($this->posxqty, $curY); + $pdf->MultiCell($this->posxup-$this->posxqty-0.8, 3, $towrite, 0, 'R'); + + // Total PMP + $pdf->SetXY($this->posxunit, $curY); + $pdf->MultiCell($this->posxdiscount-$this->posxunit-0.8, 3, price(price2num($totalvalue,'MT'), 0, $outputlangs), 0, 'R'); + + // Price sell min + if (empty($conf->global->PRODUIT_MULTIPRICES)) + { + // Total sell min + $pdf->SetXY($this->postotalht, $curY); + $pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->postotalht, 3, price(price2num($totalvaluesell,'MT'), 0, $outputlangs), 0, 'R', 0); + } + } + else + { + dol_print_error($db); + } + + if ($notetoshow) + { + $substitutionarray=pdf_getSubstitutionArray($outputlangs, null, $object); + complete_substitutions_array($substitutionarray, $outputlangs, $object); + $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs); + + $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; + + // 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); + + $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 stock 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) // There is a pagebreak + { + $pdf->rollbackTransaction(true); + $pageposafter=$pageposbefore; + //print $pageposafter.'-'.$pageposbefore;exit; + $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it. + pdf_writelinedesc($pdf,$object,$i,$outputlangs,$this->posxtva-$curX,4,$curX,$curY,$hideref,$hidedesc); + $pageposafter=$pdf->getPage(); + $posyafter=$pdf->GetY(); + if ($posyafter > ($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))) // There is no space left for total+free text + { + if ($i == ($nblignes-1)) // No more lines, and no space left to show total, so we create a new page + { + $pdf->AddPage('','',true); + if (! empty($tplidx)) $pdf->useTemplate($tplidx); + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); + $pdf->setPage($pageposafter+1); + } + } + else + { + // We found a page break + $showpricebeforepagebreak=0; + } + } + else // No pagebreak + { + $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) && empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) + { + $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 + $pdf->SetXY($this->posxdiscount, $curY); + 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 + $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 + 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=='') // if tax type not defined + && (! empty($localtax1_rate) || ! empty($localtax2_rate))) // and there is local tax + { + $localtaxtmp_array=getLocalTaxesFromRate($vatrate,0,$object->thirdparty,$mysoc); + $localtax1_type = $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 & 0x01) == 0x01) $vatrate.='*'; + if (! isset($this->tva[$vatrate])) $this->tva[$vatrate]=0; + $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(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); + } + } + */ + $tab_top = $tab_top_newpage+21; + + // 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; + } + + $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); + + // 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)); + + $this->result = array('fullpath'=>$file); + + return 1; // Pas d'erreur + } + else + { + $this->error=$langs->trans("ErrorCanNotCreateDir",$dir); + return 0; + } + } + else + { + $this->error=$langs->trans("ErrorConstantNotDefined","PRODUCT_OUTPUTDIR"); + return 0; + } + } + + + /** + * Show table for lines + * + * @param TCPDF $pdf Object PDF + * @param string $tab_top Top position of table + * @param string $tab_height Height of table (rectangle) + * @param int $nexY Y (not used) + * @param Translate $outputlangs Langs object + * @param int $hidetop 1=Hide top bar of array and title, 0=Hide nothing, -1=Hide only title + * @param int $hidebottom Hide bottom bar of array + * @param string $currency Currency code + * @return void + */ + function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='') + { + global $conf; + + // Force to disable hidetop and hidebottom + $hidebottom=0; + if ($hidetop) $hidetop=-1; + + $currency = !empty($currency) ? $currency : $conf->currency; + $default_font_size = pdf_getPDFFontSize($outputlangs); + + // Amount in (at tab_top - 1) + $pdf->SetTextColor(0,0,0); + $pdf->SetFont('','', $default_font_size - 2); + + if (empty($hidetop)) + { + $titre = $outputlangs->transnoentities("AmountInCurrency",$outputlangs->transnoentitiesnoconv("Currency".$currency)); + $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top-4); + $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre); + + //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230'; + if (! empty($conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)) $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_droite-$this->marge_gauche, 5, 'F', null, explode(',',$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)); + } + + $pdf->SetDrawColor(128,128,128); + $pdf->SetFont('','B', $default_font_size - 3); + + // Output Rect + //$this->printRect($pdf,$this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect prend une longueur en 3eme param et 4eme param + + $pdf->SetLineStyle(array('dash'=>'0','color'=>array(220,26,26))); + $pdf->SetDrawColor(220,26,26); + $pdf->line($this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_droite, $tab_top); + $pdf->SetLineStyle(array('dash'=>0)); + $pdf->SetDrawColor(128,128,128); + $pdf->SetTextColor(0,0,120); + + if (empty($hidetop)) + { + //$pdf->line($this->marge_gauche, $tab_top+5, $this->page_largeur-$this->marge_droite, $tab_top+5); // line prend une position y en 2eme param et 4eme param + $pdf->SetXY($this->posxdesc-1, $tab_top+1); + $pdf->MultiCell($this->wref,3, $outputlangs->transnoentities("Ref"),'','L'); + } + + //$pdf->line($this->posxlabel-1, $tab_top, $this->posxlabel-1, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->posxlabel-3, $tab_top+1); + $pdf->MultiCell($this->posxqty-$this->posxlabel+3,2, $outputlangs->transnoentities("Label"),'','C'); + } + + //$pdf->line($this->posxqty-1, $tab_top, $this->posxqty-1, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->posxqty-1, $tab_top+1); + $pdf->MultiCell($this->posxup-$this->posxqty-1,2, $outputlangs->transnoentities("Units"),'','C'); + } + + //$pdf->line($this->posxup-1, $tab_top, $this->posxup-1, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->posxup-1, $tab_top+1); + $pdf->MultiCell($this->posxunit-$this->posxup-1,2, $outputlangs->transnoentities("AverageUnitPricePMPShort"),'','C'); + } + + //$pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->posxunit - 1, $tab_top + 1); + $pdf->MultiCell($this->posxdiscount - $this->posxunit - 1, 2, $outputlangs->transnoentities("EstimatedStockValueShort"), '', + 'C'); + } + + //$pdf->line($this->posxdiscount-1, $tab_top, $this->posxdiscount-1, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->posxdiscount-1, $tab_top+1); + $pdf->MultiCell($this->postotalht-$this->posxdiscount+1,2, $outputlangs->transnoentities("SellPriceMin"),'','C'); + } + + //$pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->postotalht-1, $tab_top+1); + $pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->postotalht,2, $outputlangs->transnoentities("EstimatedStockValueSellShort"),'','C'); + } + + $pdf->SetDrawColor(220,26,26); + $pdf->SetLineStyle(array('dash'=>'0','color'=>array(220,26,26))); + $pdf->line($this->marge_gauche, $tab_top+11, $this->page_largeur-$this->marge_droite, $tab_top+11); + $pdf->SetLineStyle(array('dash'=>0)); + + } + + /** + * Show top header of page. + * + * @param TCPDF $pdf Object PDF + * @param Object $object Object to show + * @param int $showaddress 0=no, 1=yes + * @param Translate $outputlangs Object lang for output + * @param string $titlekey Translation key to show as title of document + * @return void + */ + function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey="") + { + global $conf,$langs,$db,$hookmanager; + + $outputlangs->load("main"); + $outputlangs->load("bills"); + $outputlangs->load("propal"); + $outputlangs->load("companies"); + $outputlangs->load("orders"); + $outputlangs->load("stocks"); + $default_font_size = pdf_getPDFFontSize($outputlangs); + + if ($object->type == 1) $titlekey='ServiceSheet'; + else $titlekey='StockSheet'; + + pdf_pagehead($pdf,$outputlangs,$this->page_hauteur); + + // Show Draft Watermark + if($object->statut==0 && (! empty($conf->global->COMMANDE_DRAFT_WATERMARK)) ) + { + pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',$conf->global->COMMANDE_DRAFT_WATERMARK); + } + + $pdf->SetTextColor(0,0,60); + $pdf->SetFont('','B', $default_font_size + 3); + + $posy=$this->marge_haute; + $posx=$this->page_largeur-$this->marge_droite-100; + + $pdf->SetXY($this->marge_gauche,$posy); + + // Logo + $logo=$conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo; + if ($this->emetteur->logo) + { + if (is_readable($logo)) + { + $height=pdf_getHeightForLogo($logo); + $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto) + } + else + { + $pdf->SetTextColor(200,0,0); + $pdf->SetFont('','B', $default_font_size -2); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound",$logo), 0, 'L'); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L'); + } + } + else + { + $text=$this->emetteur->name; + $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); + } + + $pdf->SetFont('','B', $default_font_size + 3); + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + $title=$outputlangs->transnoentities("Warehouse"); + $pdf->MultiCell(100, 3, $title, '', 'R'); + + $pdf->SetFont('','B',$default_font_size); + + $posy+=5; + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + + $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : " . $outputlangs->convToOutputCharset($object->libelle), '', 'R'); + + $posy+=5; + $pdf->SetFont('','', $default_font_size - 1); + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("LocationSummary").' :', '', 'R'); + + $posy+=4; + $pdf->SetXY($posx-50,$posy); + $pdf->MultiCell(150, 3, $object->lieu, '', 'R'); + + + // Parent entrepot + $posy+=4; + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ParentWarehouse").' :', '', 'R'); + + $posy+=4; + $pdf->SetXY($posx-50,$posy); + $e = new Entrepot($db); + if(!empty($object->fk_parent) && $e->fetch($object->fk_parent) > 0) + { + $pdf->MultiCell(150, 3, $e->libelle, '', 'R'); + } + else + { + $pdf->MultiCell(150, 3, $outputlangs->transnoentities("None"), '', 'R'); + } + + // Description + $nexY = $pdf->GetY(); + $nexY+=5; + $pdf->SetXY($posx,$posy); + $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, ''.$outputlangs->transnoentities("Description").' : '.nl2br($object->description), 0, 1); + $nexY = $pdf->GetY(); + + $calcproductsunique=$object->nb_different_products(); + $calcproducts=$object->nb_products(); + + // Total nb of different products + $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, ''.$outputlangs->transnoentities("NumberOfDifferentProducts").' : '.(empty($calcproductsunique['nb'])?'0':$calcproductsunique['nb']), 0, 1); + $nexY = $pdf->GetY(); + + // Nb of products + $valtoshow=price2num($calcproducts['nb'], 'MS'); + $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, ''.$outputlangs->transnoentities("NumberOfProducts").' : '.(empty($valtoshow)?'0':$valtoshow), 0, 1); + $nexY = $pdf->GetY(); + + // Value + $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, ''.$outputlangs->transnoentities("EstimatedStockValueShort").' : '. price((empty($calcproducts['value'])?'0':price2num($calcproducts['value'],'MT')), 0, $langs, 0, -1, -1, $conf->currency), 0, 1); + $nexY = $pdf->GetY(); + + + // Last movement + $sql = "SELECT max(m.datem) as datem"; + $sql .= " FROM ".MAIN_DB_PREFIX."stock_mouvement as m"; + $sql .= " WHERE m.fk_entrepot = '".$object->id."'"; + $resqlbis = $db->query($sql); + if ($resqlbis) + { + $obj = $db->fetch_object($resqlbis); + $lastmovementdate=$db->jdate($obj->datem); + } + else + { + dol_print_error($db); + } + + if ($lastmovementdate) + { + $toWrite = dol_print_date($lastmovementdate,'dayhour').' '; + } + else + { + $toWrite = $outputlangs->transnoentities("None"); + } + + $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, ''.$outputlangs->transnoentities("LastMovement").' : '.$toWrite, 0, 1); + $nexY = $pdf->GetY(); + + + /*if ($object->ref_client) + { + $posy+=5; + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("RefCustomer")." : " . $outputlangs->convToOutputCharset($object->ref_client), '', 'R'); + }*/ + + /*$posy+=4; + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("OrderDate")." : " . dol_print_date($object->date,"%d %b %Y",false,$outputlangs,true), '', 'R'); + */ + + // Get contact + /* + if (!empty($conf->global->DOC_SHOW_FIRST_SALES_REP)) + { + $arrayidcontact=$object->getIdContact('internal','SALESREPFOLL'); + if (count($arrayidcontact) > 0) + { + $usertmp=new User($this->db); + $usertmp->fetch($arrayidcontact[0]); + $posy+=4; + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(100, 3, $langs->trans("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + } + }*/ + + $posy+=2; + + // Show list of linked objects + $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size); + + if ($showaddress) + { + /* + // Sender properties + $carac_emetteur = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty); + + // Show sender + $posy=42; + $posx=$this->marge_gauche; + if (! empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) $posx=$this->page_largeur-$this->marge_droite-80; + $hautcadre=40; + + // Show sender frame + $pdf->SetTextColor(0,0,0); + $pdf->SetFont('','', $default_font_size - 2); + $pdf->SetXY($posx,$posy-5); + $pdf->MultiCell(66,5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->SetXY($posx,$posy); + $pdf->SetFillColor(230,230,230); + $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); + $pdf->SetTextColor(0,0,60); + + // Show sender name + $pdf->SetXY($posx+2,$posy+3); + $pdf->SetFont('','B', $default_font_size); + $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + $posy=$pdf->getY(); + + // Show sender information + $pdf->SetXY($posx+2,$posy); + $pdf->SetFont('','', $default_font_size - 1); + $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L'); + */ + } + + $pdf->SetTextColor(0,0,0); + } + + /** + * Show footer of page. Need this->emetteur object + * + * @param TCPDF $pdf PDF + * @param Object $object Object to show + * @param Translate $outputlangs Object lang for output + * @param int $hidefreetext 1=Hide free text + * @return int Return height of bottom margin including footer text + */ + function _pagefoot(&$pdf,$object,$outputlangs,$hidefreetext=0) + { + global $conf; + $showdetails=$conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS; + return pdf_pagefoot($pdf,$outputlangs,'PRODUCT_FREE_TEXT',$this->emetteur,$this->marge_basse,$this->marge_gauche,$this->page_hauteur,$object,$showdetails,$hidefreetext); + } + +} + diff --git a/htdocs/core/modules/stock/doc/pdf_stdmouvement.modules.php b/htdocs/core/modules/stock/doc/pdf_stdmouvement.modules.php new file mode 100644 index 00000000000..16d979d60ee --- /dev/null +++ b/htdocs/core/modules/stock/doc/pdf_stdmouvement.modules.php @@ -0,0 +1,1159 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/stock/doc/pdf_standard.modules.php + * \ingroup societe + * \brief File of class to build PDF documents for stocks/services + */ + +require_once DOL_DOCUMENT_ROOT.'/core/modules/stock/modules_stock.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php'; +require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; + + +/** + * Class to build documents using ODF templates generator + */ +class pdf_stdmouvement extends ModelePDFMouvement +{ + /** + * @var DoliDb Database handler + */ + public $db; + + /** + * @var string model name + */ + public $name; + + /** + * @var string model description (short text) + */ + public $description; + + /** + * @var string document type + */ + public $type; + + /** + * @var array() Minimum version of PHP required by module. + * e.g.: PHP ≥ 5.3 = array(5, 3) + */ + public $phpmin = array(5, 2); + + /** + * Dolibarr version of the loaded document + * @public string + */ + public $version = 'dolibarr'; + + public $page_largeur; + public $page_hauteur; + public $format; + public $marge_gauche; + public $marge_droite; + public $marge_haute; + public $marge_basse; + + public $emetteur; // Objet societe qui emet + + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + global $conf,$langs,$mysoc; + + $langs->load("main"); + $langs->load("companies"); + + $this->db = $db; + $this->name = "stdmouvement"; + $this->description = $langs->trans("DocumentModelStandardPDF"); + + // Dimension page pour format A4 + $this->type = 'pdf'; + $formatarray=pdf_getFormat(); + $this->page_largeur = $formatarray['width']; + $this->page_hauteur = $formatarray['height']; + $this->format = array($this->page_largeur,$this->page_hauteur); + $this->marge_gauche=isset($conf->global->MAIN_PDF_MARGIN_LEFT)?$conf->global->MAIN_PDF_MARGIN_LEFT:10; + $this->marge_droite=isset($conf->global->MAIN_PDF_MARGIN_RIGHT)?$conf->global->MAIN_PDF_MARGIN_RIGHT:10; + $this->marge_haute =isset($conf->global->MAIN_PDF_MARGIN_TOP)?$conf->global->MAIN_PDF_MARGIN_TOP:10; + $this->marge_basse =isset($conf->global->MAIN_PDF_MARGIN_BOTTOM)?$conf->global->MAIN_PDF_MARGIN_BOTTOM:10; + + $this->option_logo = 1; // Affiche logo + $this->option_codestockservice = 0; // Affiche code stock-service + $this->option_multilang = 1; // Dispo en plusieurs langues + $this->option_freetext = 0; // Support add of a personalised text + + // Recupere emetteur + $this->emetteur=$mysoc; + if (! $this->emetteur->country_code) $this->emetteur->country_code=substr($langs->defaultlang,-2); // By default if not defined + + // Define position of columns + $this->wref = 15; + $this->posxidref = $this->marge_gauche; + $this->posxdatemouv = $this->marge_gauche+8;; + $this->posxdesc=37; + $this->posxlabel=50; + $this->posxtva=80; + $this->posxqty=105; + $this->posxup=119; + $this->posxunit=136; + $this->posxdiscount=167; + $this->postotalht=180; + + if (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) || ! empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) $this->posxtva=$this->posxup; + $this->posxpicture=$this->posxtva - (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH)?20:$conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH); // width of images + if ($this->page_largeur < 210) // To work with US executive format + { + $this->posxpicture-=20; + $this->posxtva-=20; + $this->posxup-=20; + $this->posxqty-=20; + $this->posxunit-=20; + $this->posxdiscount-=20; + $this->postotalht-=20; + } + $this->tva=array(); + $this->localtax1=array(); + $this->localtax2=array(); + $this->atleastoneratenotnull=0; + $this->atleastonediscount=0; + } + + + /** + * Function to build a document on disk using the generic odt module. + * + * @param Stock $object Object source to build document + * @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 if OK, <=0 if 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("stocks"); + $outputlangs->load("orders"); + $outputlangs->load("deliveries"); + + /** + * TODO: get from object + */ + + $id=GETPOST('id','int'); + $ref = GETPOST('ref','alpha'); + $msid=GETPOST('msid','int'); + $product_id=GETPOST("product_id"); + $action=GETPOST('action','aZ09'); + $cancel=GETPOST('cancel','alpha'); + $contextpage=GETPOST('contextpage','aZ')?GETPOST('contextpage','aZ'):'movementlist'; + + $idproduct = GETPOST('idproduct','int'); + $year = GETPOST("year"); + $month = GETPOST("month"); + $search_ref = GETPOST('search_ref', 'alpha'); + $search_movement = GETPOST("search_movement"); + $search_product_ref = trim(GETPOST("search_product_ref")); + $search_product = trim(GETPOST("search_product")); + $search_warehouse = trim(GETPOST("search_warehouse")); + $search_inventorycode = trim(GETPOST("search_inventorycode")); + $search_user = trim(GETPOST("search_user")); + $search_batch = trim(GETPOST("search_batch")); + $search_qty = trim(GETPOST("search_qty")); + $search_type_mouvement=GETPOST('search_type_mouvement','int'); + + $limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit; + $page = GETPOST("page",'int'); + $sortfield = GETPOST("sortfield",'alpha'); + $sortorder = GETPOST("sortorder",'alpha'); + if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 + $offset = $limit * $page; + if (! $sortfield) $sortfield="m.datem"; + if (! $sortorder) $sortorder="DESC"; + + $pdluoid=GETPOST('pdluoid','int'); + + // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context + $hookmanager->initHooks(array('movementlist')); + $extrafields = new ExtraFields($db); + + // fetch optionals attributes and labels + $extralabels = $extrafields->fetch_name_optionals_label('movement'); + $search_array_options=$extrafields->getOptionalsFromPost($extralabels,'','search_'); + + $productlot=new ProductLot($db); + $productstatic=new Product($db); + $warehousestatic=new Entrepot($db); + $movement=new MouvementStock($db); + $userstatic=new User($db); + + $sql = "SELECT p.rowid, p.ref as product_ref, p.label as produit, p.tobatch, p.fk_product_type as type, p.entity,"; + $sql.= " e.ref as stock, e.rowid as entrepot_id, e.lieu,"; + $sql.= " m.rowid as mid, m.value as qty, m.datem, m.fk_user_author, m.label, m.inventorycode, m.fk_origin, m.origintype,"; + $sql.= " m.batch, m.price,"; + $sql.= " m.type_mouvement,"; + $sql.= " pl.rowid as lotid, pl.eatby, pl.sellby,"; + $sql.= " u.login, u.photo, u.lastname, u.firstname"; + // Add fields from extrafields + foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$key : ''); + // Add fields from hooks + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldListSelect',$parameters); // Note that $action and $object may have been modified by hook + $sql.=$hookmanager->resPrint; + $sql.= " FROM ".MAIN_DB_PREFIX."entrepot as e,"; + $sql.= " ".MAIN_DB_PREFIX."product as p,"; + $sql.= " ".MAIN_DB_PREFIX."stock_mouvement as m"; + if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."movement_extrafields as ef on (m.rowid = ef.fk_object)"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON m.fk_user_author = u.rowid"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_lot as pl ON m.batch = pl.batch AND m.fk_product = pl.fk_product"; + $sql.= " WHERE m.fk_product = p.rowid"; + if ($msid > 0) $sql .= " AND m.rowid = ".$msid; + $sql.= " AND m.fk_entrepot = e.rowid"; + $sql.= " AND e.entity IN (".getEntity('stock').")"; + if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) $sql.= " AND p.fk_product_type = 0"; + if ($id > 0) $sql.= " AND e.rowid ='".$id."'"; + if ($month > 0) + { + if ($year > 0) + $sql.= " AND m.datem BETWEEN '".$db->idate(dol_get_first_day($year,$month,false))."' AND '".$db->idate(dol_get_last_day($year,$month,false))."'"; + else + $sql.= " AND date_format(m.datem, '%m') = '$month'"; + } + else if ($year > 0) + { + $sql.= " AND m.datem BETWEEN '".$db->idate(dol_get_first_day($year,1,false))."' AND '".$db->idate(dol_get_last_day($year,12,false))."'"; + } + if ($idproduct > 0) $sql.= " AND p.rowid = '".$idproduct."'"; + if (! empty($search_ref)) $sql.= natural_search('m.rowid', $search_ref, 1); + if (! empty($search_movement)) $sql.= natural_search('m.label', $search_movement); + if (! empty($search_inventorycode)) $sql.= natural_search('m.inventorycode', $search_inventorycode); + if (! empty($search_product_ref)) $sql.= natural_search('p.ref', $search_product_ref); + if (! empty($search_product)) $sql.= natural_search('p.label', $search_product); + if ($search_warehouse > 0) $sql.= " AND e.rowid = '".$db->escape($search_warehouse)."'"; + if (! empty($search_user)) $sql.= natural_search('u.login', $search_user); + if (! empty($search_batch)) $sql.= natural_search('m.batch', $search_batch); + if ($search_qty != '') $sql.= natural_search('m.value', $search_qty, 1); + if ($search_type_mouvement > 0) $sql.= " AND m.type_mouvement = '".$db->escape($search_type_mouvement)."'"; + // Add where from extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; + // Add where from hooks + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters); // Note that $action and $object may have been modified by hook + $sql.=$hookmanager->resPrint; + $sql.= $db->order($sortfield,$sortorder); + + $nbtotalofrecords = ''; + if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) + { + $result = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); + if (($page * $limit) > $nbtotalofrecords) // if total resultset is smaller then paging size (filtering), goto and load page 0 + { + $page = 0; + $offset = 0; + } + } + + if(empty($search_inventorycode)) $sql.= $db->plimit($limit+1, $offset); + + + $resql = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); + + /* + * END TODO + **/ + + //$nblignes = count($object->lines); + + if ($conf->stock->dir_output) + { + + if ($resql) + { + $product = new Product($db); + $object = new Entrepot($db); + + if ($idproduct > 0) + { + $product->fetch($idproduct); + } + if ($id > 0 || $ref) + { + $result = $object->fetch($id, $ref); + if ($result < 0) + { + dol_print_error($db); + } + } + + $num = $db->num_rows($resql); + + $arrayofselected=is_array($toselect)?$toselect:array(); + + $i = 0; + $help_url='EN:Module_Stocks_En|FR:Module_Stock|ES:Módulo_Stocks'; + if ($msid) $texte = $langs->trans('StockMovementForId', $msid); + else + { + $texte = $langs->trans("ListOfStockMovements"); + if ($id) $texte.=' ('.$langs->trans("ForThisWarehouse").')'; + } + } + + // Definition of $dir and $file + if ($object->specimen) + { + $dir = $conf->stock->dir_output . "/mouvement"; + $file = $dir . "/SPECIMEN.pdf"; + } + else + { + $objectref = dol_sanitizeFileName($object->ref); + if(!empty($search_inventorycode)) $objectref.="_".$id."_".$search_inventorycode; + if($search_type_mouvement) $objectref.="_".$search_type_mouvement; + $dir = $conf->stock->dir_output . "/mouvement/" . $objectref; + $file = $dir . "/" . $objectref . ".pdf"; + } + + $stockFournisseur = new ProductFournisseur($this->db); + $supplierprices = $stockFournisseur->list_product_fournisseur_price($object->id); + $object->supplierprices = $supplierprices; + + $productstatic=new Product($db); + + if (! file_exists($dir)) + { + if (dol_mkdir($dir) < 0) + { + $this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir); + return -1; + } + } + + 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 + $pdf->SetAutoPageBreak(1,0); + + $heightforinfotot = 40; // 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) + + 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("Stock")); + $pdf->SetCreator("Dolibarr ".DOL_VERSION); + $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs))); + $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Stock")." ".$outputlangs->convToOutputCharset($object->libelle)); + 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->MultiCell(0, 3, ''); // Set interline to 3 + $pdf->SetTextColor(0,0,0); + + $tab_top = 42; + $tab_top_newpage = (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)?42:10); + $tab_height = 130; + $tab_height_newpage = 150; + + /* ************************************************************************** */ + /* */ + /* Affichage de la liste des produits du MouvementStock */ + /* */ + /* ************************************************************************** */ + + $nexY+=5; + $nexY = $pdf->GetY(); + $nexY+=10; + + $totalunit=0; + $totalvalue=$totalvaluesell=0; + + //dol_syslog('List products', LOG_DEBUG); + $resql = $db->query($sql); + if ($resql) + { + $num = $db->num_rows($resql); + $i = 0; + $nblignes = $num; + for ($i = 0 ; $i < $nblignes ; $i++) + { + $objp = $db->fetch_object($resql); + + // Multilangs + if (! empty($conf->global->MAIN_MULTILANGS)) // si l'option est active + { + $sql = "SELECT label"; + $sql.= " FROM ".MAIN_DB_PREFIX."product_lang"; + $sql.= " WHERE fk_product=".$objp->rowid; + $sql.= " AND lang='". $langs->getDefaultLang() ."'"; + $sql.= " LIMIT 1"; + + $result = $db->query($sql); + if ($result) + { + $objtp = $db->fetch_object($result); + if ($objtp->label != '') $objp->produit = $objtp->label; + } + } + + $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) // There is a pagebreak + { + $pdf->rollbackTransaction(true); + $pageposafter=$pageposbefore; + //print $pageposafter.'-'.$pageposbefore;exit; + $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it. + pdf_writelinedesc($pdf,$object,$i,$outputlangs,$this->posxtva-$curX,4,$curX,$curY,$hideref,$hidedesc); + $pageposafter=$pdf->getPage(); + $posyafter=$pdf->GetY(); + if ($posyafter > ($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))) // There is no space left for total+free text + { + if ($i == ($nblignes-1)) // No more lines, and no space left to show total, so we create a new page + { + $pdf->AddPage('','',true); + if (! empty($tplidx)) $pdf->useTemplate($tplidx); + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); + $pdf->setPage($pageposafter+1); + } + } + else + { + // We found a page break + $showpricebeforepagebreak=0; + } + } + else // No pagebreak + { + $pdf->commitTransaction(); + } + $posYAfterDescription=$pdf->GetY(); + + $nexY = $pdf->GetY(); + $pageposafter=$pdf->getPage(); + + $pdf->setPage($pageposbefore); + $pdf->setTopMargin($this->marge_haute); + $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. + + // We suppose that a too long description 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 + + // $objp = $db->fetch_object($resql); + + $userstatic->id=$objp->fk_user_author; + $userstatic->login=$objp->login; + $userstatic->lastname=$objp->lastname; + $userstatic->firstname=$objp->firstname; + $userstatic->photo=$objp->photo; + + $productstatic->id=$objp->rowid; + $productstatic->ref=$objp->product_ref; + $productstatic->label=$objp->produit; + $productstatic->type=$objp->type; + $productstatic->entity=$objp->entity; + $productstatic->status_batch=$objp->tobatch; + + $productlot->id = $objp->lotid; + $productlot->batch= $objp->batch; + $productlot->eatby= $objp->eatby; + $productlot->sellby= $objp->sellby; + + $warehousestatic->id=$objp->entrepot_id; + $warehousestatic->libelle=$objp->stock; + $warehousestatic->lieu=$objp->lieu; + + $arrayofuniqueproduct[$objp->rowid]=$objp->produit; + if(!empty($objp->fk_origin)) { + $origin = $movement->get_origin($objp->fk_origin, $objp->origintype); + } else { + $origin = ''; + } + + // Id movement. + $pdf->SetXY($this->posxidref, $curY); + $pdf->MultiCell($this->posxdesc-$this->posxidref-0.8, 3, $objp->mid, 0, 'L'); + + // Date. + $pdf->SetXY($this->posxdatemouv, $curY); + $pdf->MultiCell($this->posxdesc-$this->posxdatemouv-0.8, 6, dol_print_date($db->jdate($objp->datem),'dayhour'), 0, 'L'); + + // Ref. + $pdf->SetXY($this->posxdesc, $curY); + $pdf->MultiCell($this->posxlabel-$this->posxdesc-0.8, 3, $productstatic->ref, 0, 'L'); + + // Label + $pdf->SetXY($this->posxlabel+0.8, $curY); + $pdf->MultiCell($this->posxqty-$this->posxlabel-0.8, 6, $productstatic->label, 0, 'L'); + + // Lot/serie + $pdf->SetXY($this->posxqty, $curY); + $pdf->MultiCell($this->posxup-$this->posxqty-0.8, 3, $productlot->batch, 0, 'R'); + + // Inv. code + $pdf->SetXY($this->posxup, $curY); + $pdf->MultiCell($this->posxunit-$this->posxup-0.8, 3, $objp->inventorycode, 0, 'R'); + + // Label mouvement + $pdf->SetXY($this->posxunit, $curY); + $pdf->MultiCell($this->posxdiscount-$this->posxunit-0.8, 3, $objp->label, 0, 'R'); + $totalvalue+=price2num($objp->ppmp*$objp->value,'MT'); + + // Origin + $pricemin=$objp->price; + $pdf->SetXY($this->posxdiscount, $curY); + $pdf->MultiCell($this->postotalht-$this->posxdiscount-0.8, 3, $origin, 0, 'R', 0); + + // Qty + $valtoshow=price2num($objp->qty, 'MS'); + $towrite = (empty($valtoshow)?'0':$valtoshow); + $totalunit+=$objp->qty; + + $pdf->SetXY($this->postotalht, $curY); + $pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->postotalht, 3, $objp->qty, 0, 'R', 0); + + $totalvaluesell+=price2num($pricemin*$objp->value,'MT'); + + $nexY+=3.5; // Passe espace entre les lignes + // 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(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); + } + } + + $db->free($resql); + + /** + * footer table + */ + $nexY = $pdf->GetY(); + $nexY+=5; + $curY = $nexY; + + $pdf->SetLineStyle(array('dash'=>'0','color'=>array(220,26,26))); + $pdf->line($this->marge_gauche, $curY-1, $this->page_largeur-$this->marge_droite, $curY-1); + $pdf->SetLineStyle(array('dash'=>0)); + + $pdf->SetFont('','B',$default_font_size-1); + $pdf->SetTextColor(0,0,120); + + // Total + $pdf->SetXY($this->posxidref, $curY); + $pdf->MultiCell($this->posxdesc-$this->posxidref, 3, $langs->trans("Total"), 0, 'L'); + + // Total Qty + $pdf->SetXY($this->postotalht, $curY); + $pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->postotalht, 3, $totalunit, 0, 'R', 0); + + } + else + { + dol_print_error($db); + } + + if ($notetoshow) + { + $substitutionarray=pdf_getSubstitutionArray($outputlangs, null, $object); + complete_substitutions_array($substitutionarray, $outputlangs, $object); + $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs); + + $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; + + $tab_top = $tab_top_newpage+21; + + // 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; + } + + $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); + + // 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)); + + $this->result = array('fullpath'=>$file); + + return 1; // Pas d'erreur + } + else + { + $this->error=$langs->trans("ErrorCanNotCreateDir",$dir); + return 0; + } + } + else + { + $this->error=$langs->trans("ErrorConstantNotDefined","PRODUCT_OUTPUTDIR"); + return 0; + } + } + + + /** + * Show table for lines + * + * @param TCPDF $pdf Object PDF + * @param string $tab_top Top position of table + * @param string $tab_height Height of table (rectangle) + * @param int $nexY Y (not used) + * @param Translate $outputlangs Langs object + * @param int $hidetop 1=Hide top bar of array and title, 0=Hide nothing, -1=Hide only title + * @param int $hidebottom Hide bottom bar of array + * @param string $currency Currency code + * @return void + */ + function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='') + { + global $conf; + + // Force to disable hidetop and hidebottom + $hidebottom=0; + if ($hidetop) $hidetop=-1; + + $currency = !empty($currency) ? $currency : $conf->currency; + $default_font_size = pdf_getPDFFontSize($outputlangs); + + // Amount in (at tab_top - 1) + $pdf->SetTextColor(0,0,0); + $pdf->SetFont('','', $default_font_size - 2); + + if (empty($hidetop)) + { + $titre = $outputlangs->transnoentities("AmountInCurrency",$outputlangs->transnoentitiesnoconv("Currency".$currency)); + $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top-4); + $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre); + + //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230'; + if (! empty($conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)) $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_droite-$this->marge_gauche, 5, 'F', null, explode(',',$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)); + } + + $pdf->SetDrawColor(128,128,128); + $pdf->SetFont('','B', $default_font_size - 3); + + // Output Rect + //$this->printRect($pdf,$this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect prend une longueur en 3eme param et 4eme param + + $pdf->SetLineStyle(array('dash'=>'0','color'=>array(220,26,26))); + $pdf->SetDrawColor(220,26,26); + $pdf->line($this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_droite, $tab_top); + $pdf->SetLineStyle(array('dash'=>0)); + $pdf->SetDrawColor(128,128,128); + $pdf->SetTextColor(0,0,120); + + //Ref mouv + if (empty($hidetop)) + { + //$pdf->line($this->marge_gauche, $tab_top+5, $this->page_largeur-$this->marge_droite, $tab_top+5); // line prend une position y en 2eme param et 4eme param + $pdf->SetXY($this->posxidref, $tab_top+1); + $pdf->MultiCell($this->posxdatemouv-$this->posxdatemouv-0.8,3, $outputlangs->transnoentities("Ref"),'','L'); + } + + //Date mouv + //$pdf->line($this->posxlabel-1, $tab_top, $this->posxlabel-1, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->posxdatemouv, $tab_top+1); + $pdf->MultiCell($this->posxdesc-$this->posxdatemouv,2, $outputlangs->transnoentities("Date"),'','C'); + } + + //Ref Product + //$pdf->line($this->posxqty-1, $tab_top, $this->posxqty-1, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->posxdesc-1, $tab_top+1); + $pdf->MultiCell($this->posxlabel-$this->posxdesc,2, $outputlangs->transnoentities("Ref. Product"),'','C'); + } + + //Label Product + //$pdf->line($this->posxup-1, $tab_top, $this->posxup-1, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->posxlabel-1, $tab_top+1); + $pdf->MultiCell($this->posxqty-$this->posxlabel,2, $outputlangs->transnoentities("Label"),'','C'); + } + + //Lot/serie Product + //$pdf->line($this->posxqty - 1, $tab_top, $this->posxqty - 1, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->posxqty, $tab_top + 1); + $pdf->MultiCell($this->posxup - $this->posxqty, 2, $outputlangs->transnoentities("Lot/Série"), '','C'); + } + + //Code Inv + //$pdf->line($this->posxup-1, $tab_top, $this->posxup-1, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->posxup-1, $tab_top+1); + $pdf->MultiCell($this->posxunit-$this->posxup,2, $outputlangs->transnoentities("Inventory Code"),'','C'); + } + + //Label mouvement + //$pdf->line($this->posxunit, $tab_top, $this->posxunit, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->posxunit, $tab_top+1); + $pdf->MultiCell($this->posxdiscount-$this->posxunit,2, $outputlangs->transnoentities("Label Mouvement"),'','C'); + } + + //Origin + //$pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->posxdiscount+2, $tab_top+1); + $pdf->MultiCell($this->postotalht-$this->posxdiscount-0.8,2, $outputlangs->transnoentities("Origin"),'','C'); + } + + //Qty + //$pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height); + if (empty($hidetop)) + { + $pdf->SetXY($this->postotalht+2, $tab_top+1); + $pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->postotalht,2, $outputlangs->transnoentities("Qty"),'','C'); + } + + $pdf->SetDrawColor(220,26,26); + $pdf->SetLineStyle(array('dash'=>'0','color'=>array(220,26,26))); + $pdf->line($this->marge_gauche, $tab_top+11, $this->page_largeur-$this->marge_droite, $tab_top+11); + $pdf->SetLineStyle(array('dash'=>0)); + + } + + /** + * Show top header of page. + * + * @param TCPDF $pdf Object PDF + * @param Object $object Object to show + * @param int $showaddress 0=no, 1=yes + * @param Translate $outputlangs Object lang for output + * @param string $titlekey Translation key to show as title of document + * @return void + */ + function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey="") + { + global $conf,$langs,$db,$hookmanager; + + $outputlangs->load("main"); + $outputlangs->load("bills"); + $outputlangs->load("propal"); + $outputlangs->load("companies"); + $outputlangs->load("orders"); + $outputlangs->load("stocks"); + $default_font_size = pdf_getPDFFontSize($outputlangs); + + if ($object->type == 1) $titlekey='ServiceSheet'; + else $titlekey='StockSheet'; + + pdf_pagehead($pdf,$outputlangs,$this->page_hauteur); + + // Show Draft Watermark + if($object->statut==0 && (! empty($conf->global->COMMANDE_DRAFT_WATERMARK)) ) + { + pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',$conf->global->COMMANDE_DRAFT_WATERMARK); + } + + $pdf->SetTextColor(0,0,60); + $pdf->SetFont('','B', $default_font_size + 3); + + $posy=$this->marge_haute; + $posx=$this->page_largeur-$this->marge_droite-100; + + $pdf->SetXY($this->marge_gauche,$posy); + + // Logo + $logo=$conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo; + if ($this->emetteur->logo) + { + if (is_readable($logo)) + { + $height=pdf_getHeightForLogo($logo); + $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto) + } + else + { + $pdf->SetTextColor(200,0,0); + $pdf->SetFont('','B', $default_font_size -2); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound",$logo), 0, 'L'); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L'); + } + } + else + { + $text=$this->emetteur->name; + $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); + } + + $pdf->SetFont('','B', $default_font_size + 3); + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + $title=$outputlangs->transnoentities("Warehouse"); + $pdf->MultiCell(100, 3, $title, '', 'R'); + + $pdf->SetFont('','B',$default_font_size); + + $posy+=5; + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + + $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : " . $outputlangs->convToOutputCharset($object->libelle), '', 'R'); + + $posy+=5; + $pdf->SetFont('','', $default_font_size - 1); + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("LocationSummary").' :', '', 'R'); + + $posy+=4; + $pdf->SetXY($posx-50,$posy); + $pdf->MultiCell(150, 3, $object->lieu, '', 'R'); + + + // Parent MouvementStock + $posy+=4; + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ParentWarehouse").' :', '', 'R'); + + $posy+=4; + $pdf->SetXY($posx-50,$posy); + $e = new MouvementStock($db); + if(!empty($object->fk_parent) && $e->fetch($object->fk_parent) > 0) + { + $pdf->MultiCell(150, 3, $e->libelle, '', 'R'); + } + else + { + $pdf->MultiCell(150, 3, $outputlangs->transnoentities("None"), '', 'R'); + } + + // Description + $nexY = $pdf->GetY(); + $nexY+=5; + $pdf->SetXY($posx,$posy); + $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, ''.$outputlangs->transnoentities("Description").' : '.nl2br($object->description), 0, 1); + $nexY = $pdf->GetY(); + + $calcproductsunique=$object->nb_different_products(); + $calcproducts=$object->nb_products(); + + // Total nb of different products + $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, ''.$outputlangs->transnoentities("NumberOfDifferentProducts").' : '.(empty($calcproductsunique['nb'])?'0':$calcproductsunique['nb']), 0, 1); + $nexY = $pdf->GetY(); + + // Nb of products + $valtoshow=price2num($calcproducts['nb'], 'MS'); + $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, ''.$outputlangs->transnoentities("NumberOfProducts").' : '.(empty($valtoshow)?'0':$valtoshow), 0, 1); + $nexY = $pdf->GetY(); + + // Value + $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, ''.$outputlangs->transnoentities("EstimatedStockValueShort").' : '. price((empty($calcproducts['value'])?'0':price2num($calcproducts['value'],'MT')), 0, $langs, 0, -1, -1, $conf->currency), 0, 1); + $nexY = $pdf->GetY(); + + + // Last movement + $sql = "SELECT max(m.datem) as datem"; + $sql .= " FROM ".MAIN_DB_PREFIX."stock_mouvement as m"; + $sql .= " WHERE m.fk_entrepot = '".$object->id."'"; + $resqlbis = $db->query($sql); + if ($resqlbis) + { + $obj = $db->fetch_object($resqlbis); + $lastmovementdate=$db->jdate($obj->datem); + } + else + { + dol_print_error($db); + } + + if ($lastmovementdate) + { + $toWrite = dol_print_date($lastmovementdate,'dayhour').' '; + } + else + { + $toWrite = $outputlangs->transnoentities("None"); + } + + $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, ''.$outputlangs->transnoentities("LastMovement").' : '.$toWrite, 0, 1); + $nexY = $pdf->GetY(); + + + /*if ($object->ref_client) + { + $posy+=5; + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("RefCustomer")." : " . $outputlangs->convToOutputCharset($object->ref_client), '', 'R'); + }*/ + + /*$posy+=4; + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("OrderDate")." : " . dol_print_date($object->date,"%d %b %Y",false,$outputlangs,true), '', 'R'); + */ + + // Get contact + /* + if (!empty($conf->global->DOC_SHOW_FIRST_SALES_REP)) + { + $arrayidcontact=$object->getIdContact('internal','SALESREPFOLL'); + if (count($arrayidcontact) > 0) + { + $usertmp=new User($this->db); + $usertmp->fetch($arrayidcontact[0]); + $posy+=4; + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(100, 3, $langs->trans("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + } + }*/ + + $posy+=2; + + // Show list of linked objects + //$posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size); + + if ($showaddress) + { + /* + // Sender properties + $carac_emetteur = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty); + + // Show sender + $posy=42; + $posx=$this->marge_gauche; + if (! empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) $posx=$this->page_largeur-$this->marge_droite-80; + $hautcadre=40; + + // Show sender frame + $pdf->SetTextColor(0,0,0); + $pdf->SetFont('','', $default_font_size - 2); + $pdf->SetXY($posx,$posy-5); + $pdf->MultiCell(66,5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->SetXY($posx,$posy); + $pdf->SetFillColor(230,230,230); + $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); + $pdf->SetTextColor(0,0,60); + + // Show sender name + $pdf->SetXY($posx+2,$posy+3); + $pdf->SetFont('','B', $default_font_size); + $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + $posy=$pdf->getY(); + + // Show sender information + $pdf->SetXY($posx+2,$posy); + $pdf->SetFont('','', $default_font_size - 1); + $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L'); + */ + } + + $pdf->SetTextColor(0,0,0); + } + + /** + * Show footer of page. Need this->emetteur object + * + * @param TCPDF $pdf PDF + * @param Object $object Object to show + * @param Translate $outputlangs Object lang for output + * @param int $hidefreetext 1=Hide free text + * @return int Return height of bottom margin including footer text + */ + function _pagefoot(&$pdf,$object,$outputlangs,$hidefreetext=0) + { + global $conf; + $showdetails=$conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS; + return pdf_pagefoot($pdf,$outputlangs,'PRODUCT_FREE_TEXT',$this->emetteur,$this->marge_basse,$this->marge_gauche,$this->page_hauteur,$object,$showdetails,$hidefreetext); + } + +} + diff --git a/htdocs/core/modules/stock/modules_stock.class.php b/htdocs/core/modules/stock/modules_stock.class.php new file mode 100644 index 00000000000..9af3aa11501 --- /dev/null +++ b/htdocs/core/modules/stock/modules_stock.class.php @@ -0,0 +1,90 @@ + + * Copyright (C) 2004-2010 Laurent Destailleur + * Copyright (C) 2004 Eric Seigne + * Copyright (C) 2005-2012 Regis Houssin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + */ + + +/** + * \class ModeleStock + * \brief Parent class for warehouse generators + */ + +/** + * \file htdocs/core/modules/stock/modules_stock.php + * \ingroup stock + * \brief File with parent class for generating warehouse to PDF and File of class to manage warehouse mouvement + */ + + require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php'; + +/** + * Parent class to manage warehouse document templates + */ +abstract class ModelePDFStock extends CommonDocGenerator +{ + var $error=''; + + + /** + * Return list of active generation modules + * + * @param DoliDB $db Database handler + * @param integer $maxfilenamelength Max length of value to show + * @return array List of templates + */ + static function liste_modeles($db,$maxfilenamelength=0) + { + global $conf; + + $type='stock'; + $liste=array(); + + include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + $liste=getListOfModels($db,$type,$maxfilenamelength); + return $liste; + } +} + + +/** + * Parent class to manage warehouse mouvement document templates + */ +abstract class ModelePDFMouvement extends CommonDocGenerator +{ + var $error=''; + + + /** + * Return list of active generation modules + * + * @param DoliDB $db Database handler + * @param integer $maxfilenamelength Max length of value to show + * @return array List of templates + */ + static function liste_modeles($db,$maxfilenamelength=0) + { + global $conf; + + $type='mouvementcom'; + $liste=array(); + include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + $liste=getListOfModels($db,$type,$maxfilenamelength); + return $liste; + } +} \ No newline at end of file diff --git a/htdocs/core/modules/stock/modules_stock.php b/htdocs/core/modules/stock/modules_stock.php new file mode 100644 index 00000000000..f1c72601b97 --- /dev/null +++ b/htdocs/core/modules/stock/modules_stock.php @@ -0,0 +1,52 @@ + + * Copyright (C) 2004-2010 Laurent Destailleur + * Copyright (C) 2004 Eric Seigne + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2016 Charlie Benke + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + */ + +require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php'; + +/** + * \class ModeleStock + * \brief Parent class for stock models of doc generators + */ +abstract class ModeleStock extends CommonDocGenerator +{ + var $error=''; + + /** + * Return list of active generation modules + * + * @param DoliDB $db Database handler + * @param integer $maxfilenamelength Max length of value to show + * @return array List of templates + */ + static function liste_modeles($db,$maxfilenamelength=0) + { + global $conf; + + $type='stock'; + $liste=array(); + + include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + $liste=getListOfModels($db,$type,$maxfilenamelength); + + return $liste; + } +} From d766cb66b8814588abce4393a20f6b7b56263a8c Mon Sep 17 00:00:00 2001 From: wdammak <26695620+wdammak@users.noreply.github.com> Date: Fri, 4 May 2018 16:14:41 +0100 Subject: [PATCH 04/10] Overload styles files from a current folder of module & theme --- htdocs/main.inc.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index e20451e2415..bd803febe5f 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1235,10 +1235,10 @@ function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs if (! empty($conf->global->MAIN_FIX_FLASH_ON_CHROME)) print ''."\n".''."\n"; //Overload css files to the current theme - // Check if the /theme/nameoftheme/style folder exists and Add the contains css files to head + // Check if the /theme/nameoftheme/style folder exists and add the contains css files to head if (file_exists(dirname(dol_buildpath($conf->css, 0))."/style")) { - //browse the css dir and add the contains css files + //browse the style dir and add the contains css files if ($handle = opendir(dirname(dol_buildpath($conf->css, 0))."/style")) { while (false !== ($entry = readdir($handle))) @@ -1254,7 +1254,7 @@ function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs } //Overload css files to the current module - // Check if the /module/style folder exists and Add the contains css files to head + // Check if the /module/style folder exists and add the contains css files to head $cur_modulepart = explode("/",$_SERVER["PHP_SELF"]); if(is_array($cur_modulepart) && count($cur_modulepart)>0) { From 1b2dbedd154b6e1849985294b3fba8f31aefc9d6 Mon Sep 17 00:00:00 2001 From: wdammak <26695620+wdammak@users.noreply.github.com> Date: Fri, 4 May 2018 22:06:44 +0100 Subject: [PATCH 05/10] Add models pdf to warehouse module - Warehouse report - Mouvement report From fb81088a4b8b9de12faa7923176c2ba23e3a6e2c Mon Sep 17 00:00:00 2001 From: wdammak <26695620+wdammak@users.noreply.github.com> Date: Sat, 5 May 2018 13:44:11 +0100 Subject: [PATCH 06/10] Add models warehouse and movement --- htdocs/core/modules/stock/modules_stock.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/stock/modules_stock.class.php b/htdocs/core/modules/stock/modules_stock.class.php index 9af3aa11501..283ae75b6a3 100644 --- a/htdocs/core/modules/stock/modules_stock.class.php +++ b/htdocs/core/modules/stock/modules_stock.class.php @@ -81,7 +81,7 @@ abstract class ModelePDFMouvement extends CommonDocGenerator { global $conf; - $type='mouvementcom'; + $type='mouvement'; $liste=array(); include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; $liste=getListOfModels($db,$type,$maxfilenamelength); From c90d0e6cb35a6b4dd084708a4f727fd2d1a28591 Mon Sep 17 00:00:00 2001 From: wdammak <26695620+wdammak@users.noreply.github.com> Date: Sun, 6 May 2018 17:30:54 +0100 Subject: [PATCH 07/10] Add pdf warehouse to warehouse module From e733ea29791c2c26c7ea96400399a4e6502a3780 Mon Sep 17 00:00:00 2001 From: wdammak <26695620+wdammak@users.noreply.github.com> Date: Sun, 6 May 2018 17:54:59 +0100 Subject: [PATCH 08/10] Revert "Add models pdf to warehouse module" From 70a185a9e640af08895074e7fa0f8966e93f9310 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 10 May 2018 13:11:52 +0200 Subject: [PATCH 09/10] Update main.inc.php --- htdocs/main.inc.php | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index bd803febe5f..cd728711244 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1253,35 +1253,6 @@ function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs } } - //Overload css files to the current module - // Check if the /module/style folder exists and add the contains css files to head - $cur_modulepart = explode("/",$_SERVER["PHP_SELF"]); - if(is_array($cur_modulepart) && count($cur_modulepart)>0) - { - foreach($conf->modules as $module) - { - if(in_array($module, $cur_modulepart)) - { - if (file_exists(getcwd().DIRECTORY_SEPARATOR."style")) - { - //browse the style dir and add the contains css files - if ($handle = opendir(getcwd().DIRECTORY_SEPARATOR."style")) - { - while (false !== ($entry = readdir($handle))) - { - list($filename, $extension) = explode(".", $entry); - if ($entry !== '.' && $entry !== '..' && $extension == 'css') - { - print ''."\n"; - } - } - closedir($handle); - } - } - } - } - } - // CSS forced by modules (relative url starting with /) if (! empty($conf->modules_parts['css'])) { From a6966fe295b5849e8682b774158d71c32afce57d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 10 May 2018 13:12:24 +0200 Subject: [PATCH 10/10] Update main.inc.php --- htdocs/main.inc.php | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index cd728711244..eaea0dc420c 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1234,25 +1234,6 @@ function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs print ''."\n"; if (! empty($conf->global->MAIN_FIX_FLASH_ON_CHROME)) print ''."\n".''."\n"; - //Overload css files to the current theme - // Check if the /theme/nameoftheme/style folder exists and add the contains css files to head - if (file_exists(dirname(dol_buildpath($conf->css, 0))."/style")) - { - //browse the style dir and add the contains css files - if ($handle = opendir(dirname(dol_buildpath($conf->css, 0))."/style")) - { - while (false !== ($entry = readdir($handle))) - { - list($filename, $extension) = explode(".", $entry); - if ($entry !== '.' && $entry !== '..' && $extension == 'css') - { - print ''."\n"; - } - } - closedir($handle); - } - } - // CSS forced by modules (relative url starting with /) if (! empty($conf->modules_parts['css'])) {