pdf_stdmovement.modules.php 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181
  1. <?php
  2. /* Copyright (C) 2017 Laurent Destailleur <eldy@stocks.sourceforge.net>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. * or see http://www.gnu.org/
  17. */
  18. /**
  19. * \file htdocs/core/modules/stock/doc/pdf_stdmovement.modules.php
  20. * \ingroup societe
  21. * \brief File of class to build PDF documents for stocks movements
  22. */
  23. require_once DOL_DOCUMENT_ROOT.'/core/modules/stock/modules_movement.php';
  24. require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
  25. require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
  26. require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
  27. require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
  28. require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
  29. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  30. require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
  31. /**
  32. * Class to build documents using ODF templates generator
  33. */
  34. class pdf_stdmovement extends ModelePDFMovement
  35. {
  36. /**
  37. * @var DoliDb Database handler
  38. */
  39. public $db;
  40. /**
  41. * @var string model name
  42. */
  43. public $name;
  44. /**
  45. * @var string model description (short text)
  46. */
  47. public $description;
  48. /**
  49. * @var string document type
  50. */
  51. public $type;
  52. /**
  53. * @var array() Minimum version of PHP required by module.
  54. * e.g.: PHP ≥ 5.4 = array(5, 4)
  55. */
  56. public $phpmin = array(5, 4);
  57. /**
  58. * Dolibarr version of the loaded document
  59. * @public string
  60. */
  61. public $version = 'dolibarr';
  62. /**
  63. * @var int page_largeur
  64. */
  65. public $page_largeur;
  66. /**
  67. * @var int page_hauteur
  68. */
  69. public $page_hauteur;
  70. /**
  71. * @var array format
  72. */
  73. public $format;
  74. /**
  75. * @var int marge_gauche
  76. */
  77. public $marge_gauche;
  78. /**
  79. * @var int marge_droite
  80. */
  81. public $marge_droite;
  82. /**
  83. * @var int marge_haute
  84. */
  85. public $marge_haute;
  86. /**
  87. * @var int marge_basse
  88. */
  89. public $marge_basse;
  90. /**
  91. * Issuer
  92. * @var Societe
  93. */
  94. public $emetteur;
  95. /**
  96. * Constructor
  97. *
  98. * @param DoliDB $db Database handler
  99. */
  100. public function __construct($db)
  101. {
  102. global $conf,$langs,$mysoc;
  103. // Load traductions files requiredby by page
  104. $langs->loadLangs(array("main", "companies"));
  105. $this->db = $db;
  106. $this->name = "stdmouvement";
  107. $this->description = $langs->trans("DocumentModelStandardPDF");
  108. // Dimension page pour format A4
  109. $this->type = 'pdf';
  110. $formatarray=pdf_getFormat();
  111. $this->page_largeur = $formatarray['width'];
  112. $this->page_hauteur = $formatarray['height'];
  113. $this->format = array($this->page_largeur,$this->page_hauteur);
  114. $this->marge_gauche=isset($conf->global->MAIN_PDF_MARGIN_LEFT)?$conf->global->MAIN_PDF_MARGIN_LEFT:10;
  115. $this->marge_droite=isset($conf->global->MAIN_PDF_MARGIN_RIGHT)?$conf->global->MAIN_PDF_MARGIN_RIGHT:10;
  116. $this->marge_haute =isset($conf->global->MAIN_PDF_MARGIN_TOP)?$conf->global->MAIN_PDF_MARGIN_TOP:10;
  117. $this->marge_basse =isset($conf->global->MAIN_PDF_MARGIN_BOTTOM)?$conf->global->MAIN_PDF_MARGIN_BOTTOM:10;
  118. $this->option_logo = 1; // Affiche logo
  119. $this->option_codestockservice = 0; // Affiche code stock-service
  120. $this->option_multilang = 1; // Dispo en plusieurs langues
  121. $this->option_freetext = 0; // Support add of a personalised text
  122. // Recupere emetteur
  123. $this->emetteur=$mysoc;
  124. if (! $this->emetteur->country_code) $this->emetteur->country_code=substr($langs->defaultlang,-2); // By default if not defined
  125. // Define position of columns
  126. $this->wref = 15;
  127. $this->posxidref = $this->marge_gauche;
  128. $this->posxdatemouv = $this->marge_gauche+8;
  129. $this->posxdesc=37;
  130. $this->posxlabel=50;
  131. $this->posxtva=80;
  132. $this->posxqty=105;
  133. $this->posxup=119;
  134. $this->posxunit=136;
  135. $this->posxdiscount=167;
  136. $this->postotalht=180;
  137. if (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) || ! empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) $this->posxtva=$this->posxup;
  138. $this->posxpicture=$this->posxtva - (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH)?20:$conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH); // width of images
  139. if ($this->page_largeur < 210) // To work with US executive format
  140. {
  141. $this->posxpicture-=20;
  142. $this->posxtva-=20;
  143. $this->posxup-=20;
  144. $this->posxqty-=20;
  145. $this->posxunit-=20;
  146. $this->posxdiscount-=20;
  147. $this->postotalht-=20;
  148. }
  149. $this->tva=array();
  150. $this->localtax1=array();
  151. $this->localtax2=array();
  152. $this->atleastoneratenotnull=0;
  153. $this->atleastonediscount=0;
  154. }
  155. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  156. /**
  157. * Function to build a document on disk using the generic odt module.
  158. *
  159. * @param Stock $object Object source to build document
  160. * @param Translate $outputlangs Lang output object
  161. * @param string $srctemplatepath Full path of source filename for generator using a template file
  162. * @param int $hidedetails Do not show line details
  163. * @param int $hidedesc Do not show desc
  164. * @param int $hideref Do not show ref
  165. * @return int 1 if OK, <=0 if KO
  166. */
  167. function write_file($object,$outputlangs,$srctemplatepath,$hidedetails=0,$hidedesc=0,$hideref=0)
  168. {
  169. // phpcs:enable
  170. global $user,$langs,$conf,$mysoc,$db,$hookmanager;
  171. if (! is_object($outputlangs)) $outputlangs=$langs;
  172. // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
  173. if (! empty($conf->global->MAIN_USE_FPDF)) $outputlangs->charset_output='ISO-8859-1';
  174. // Load traductions files requiredby by page
  175. $outputlangs->loadLangs(array("main", "dict", "companies", "bills", "stocks", "orders", "deliveries"));
  176. /**
  177. * TODO: get from object
  178. */
  179. $id=GETPOST('id','int');
  180. $ref = GETPOST('ref','alpha');
  181. $msid=GETPOST('msid','int');
  182. $product_id=GETPOST("product_id");
  183. $action=GETPOST('action','aZ09');
  184. $cancel=GETPOST('cancel','alpha');
  185. $contextpage=GETPOST('contextpage','aZ')?GETPOST('contextpage','aZ'):'movementlist';
  186. $idproduct = GETPOST('idproduct','int');
  187. $year = GETPOST("year");
  188. $month = GETPOST("month");
  189. $search_ref = GETPOST('search_ref', 'alpha');
  190. $search_movement = GETPOST("search_movement");
  191. $search_product_ref = trim(GETPOST("search_product_ref"));
  192. $search_product = trim(GETPOST("search_product"));
  193. $search_warehouse = trim(GETPOST("search_warehouse"));
  194. $search_inventorycode = trim(GETPOST("search_inventorycode"));
  195. $search_user = trim(GETPOST("search_user"));
  196. $search_batch = trim(GETPOST("search_batch"));
  197. $search_qty = trim(GETPOST("search_qty"));
  198. $search_type_mouvement=GETPOST('search_type_mouvement','int');
  199. $limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit;
  200. $page = GETPOST("page",'int');
  201. $sortfield = GETPOST("sortfield",'alpha');
  202. $sortorder = GETPOST("sortorder",'alpha');
  203. if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1
  204. $offset = $limit * $page;
  205. if (! $sortfield) $sortfield="m.datem";
  206. if (! $sortorder) $sortorder="DESC";
  207. $pdluoid=GETPOST('pdluoid','int');
  208. // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
  209. $hookmanager->initHooks(array('movementlist'));
  210. $extrafields = new ExtraFields($db);
  211. // fetch optionals attributes and labels
  212. $extralabels = $extrafields->fetch_name_optionals_label('movement');
  213. $search_array_options=$extrafields->getOptionalsFromPost('movement','','search_');
  214. $productlot=new ProductLot($db);
  215. $productstatic=new Product($db);
  216. $warehousestatic=new Entrepot($db);
  217. $movement=new MouvementStock($db);
  218. $userstatic=new User($db);
  219. $sql = "SELECT p.rowid, p.ref as product_ref, p.label as produit, p.tobatch, p.fk_product_type as type, p.entity,";
  220. $sql.= " e.ref as stock, e.rowid as entrepot_id, e.lieu,";
  221. $sql.= " m.rowid as mid, m.value as qty, m.datem, m.fk_user_author, m.label, m.inventorycode, m.fk_origin, m.origintype,";
  222. $sql.= " m.batch, m.price,";
  223. $sql.= " m.type_mouvement,";
  224. $sql.= " pl.rowid as lotid, pl.eatby, pl.sellby,";
  225. $sql.= " u.login, u.photo, u.lastname, u.firstname";
  226. // Add fields from extrafields
  227. foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$key : '');
  228. // Add fields from hooks
  229. $parameters=array();
  230. $reshook=$hookmanager->executeHooks('printFieldListSelect',$parameters); // Note that $action and $object may have been modified by hook
  231. $sql.=$hookmanager->resPrint;
  232. $sql.= " FROM ".MAIN_DB_PREFIX."entrepot as e,";
  233. $sql.= " ".MAIN_DB_PREFIX."product as p,";
  234. $sql.= " ".MAIN_DB_PREFIX."stock_mouvement as m";
  235. 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)";
  236. $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON m.fk_user_author = u.rowid";
  237. $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_lot as pl ON m.batch = pl.batch AND m.fk_product = pl.fk_product";
  238. $sql.= " WHERE m.fk_product = p.rowid";
  239. if ($msid > 0) $sql .= " AND m.rowid = ".$msid;
  240. $sql.= " AND m.fk_entrepot = e.rowid";
  241. $sql.= " AND e.entity IN (".getEntity('stock').")";
  242. if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) $sql.= " AND p.fk_product_type = 0";
  243. if ($id > 0) $sql.= " AND e.rowid ='".$id."'";
  244. if ($month > 0)
  245. {
  246. if ($year > 0)
  247. $sql.= " AND m.datem BETWEEN '".$db->idate(dol_get_first_day($year,$month,false))."' AND '".$db->idate(dol_get_last_day($year,$month,false))."'";
  248. else
  249. $sql.= " AND date_format(m.datem, '%m') = '$month'";
  250. }
  251. else if ($year > 0)
  252. {
  253. $sql.= " AND m.datem BETWEEN '".$db->idate(dol_get_first_day($year,1,false))."' AND '".$db->idate(dol_get_last_day($year,12,false))."'";
  254. }
  255. if ($idproduct > 0) $sql.= " AND p.rowid = '".$idproduct."'";
  256. if (! empty($search_ref)) $sql.= natural_search('m.rowid', $search_ref, 1);
  257. if (! empty($search_movement)) $sql.= natural_search('m.label', $search_movement);
  258. if (! empty($search_inventorycode)) $sql.= natural_search('m.inventorycode', $search_inventorycode);
  259. if (! empty($search_product_ref)) $sql.= natural_search('p.ref', $search_product_ref);
  260. if (! empty($search_product)) $sql.= natural_search('p.label', $search_product);
  261. if ($search_warehouse > 0) $sql.= " AND e.rowid = '".$db->escape($search_warehouse)."'";
  262. if (! empty($search_user)) $sql.= natural_search('u.login', $search_user);
  263. if (! empty($search_batch)) $sql.= natural_search('m.batch', $search_batch);
  264. if ($search_qty != '') $sql.= natural_search('m.value', $search_qty, 1);
  265. if ($search_type_mouvement > 0) $sql.= " AND m.type_mouvement = '".$db->escape($search_type_mouvement)."'";
  266. // Add where from extra fields
  267. include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
  268. // Add where from hooks
  269. $parameters=array();
  270. $reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters); // Note that $action and $object may have been modified by hook
  271. $sql.=$hookmanager->resPrint;
  272. $sql.= $db->order($sortfield,$sortorder);
  273. $nbtotalofrecords = '';
  274. if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
  275. {
  276. $result = $db->query($sql);
  277. $nbtotalofrecords = $db->num_rows($result);
  278. if (($page * $limit) > $nbtotalofrecords) // if total resultset is smaller then paging size (filtering), goto and load page 0
  279. {
  280. $page = 0;
  281. $offset = 0;
  282. }
  283. }
  284. if(empty($search_inventorycode)) $sql.= $db->plimit($limit+1, $offset);
  285. $resql = $db->query($sql);
  286. $nbtotalofrecords = $db->num_rows($result);
  287. /*
  288. * END TODO
  289. **/
  290. //$nblignes = count($object->lines);
  291. if ($conf->stock->dir_output)
  292. {
  293. if ($resql)
  294. {
  295. $product = new Product($db);
  296. $object = new Entrepot($db);
  297. if ($idproduct > 0)
  298. {
  299. $product->fetch($idproduct);
  300. }
  301. if ($id > 0 || $ref)
  302. {
  303. $result = $object->fetch($id, $ref);
  304. if ($result < 0)
  305. {
  306. dol_print_error($db);
  307. }
  308. }
  309. $num = $db->num_rows($resql);
  310. $arrayofselected=is_array($toselect)?$toselect:array();
  311. $i = 0;
  312. $help_url='EN:Module_Stocks_En|FR:Module_Stock|ES:M&oacute;dulo_Stocks';
  313. if ($msid) $texte = $langs->trans('StockMovementForId', $msid);
  314. else
  315. {
  316. $texte = $langs->trans("ListOfStockMovements");
  317. if ($id) $texte.=' ('.$langs->trans("ForThisWarehouse").')';
  318. }
  319. }
  320. // Definition of $dir and $file
  321. if ($object->specimen)
  322. {
  323. $dir = $conf->stock->dir_output . "/movement";
  324. $file = $dir . "/SPECIMEN.pdf";
  325. }
  326. else
  327. {
  328. $objectref = dol_sanitizeFileName($object->ref);
  329. if(!empty($search_inventorycode)) $objectref.="_".$id."_".$search_inventorycode;
  330. if($search_type_mouvement) $objectref.="_".$search_type_mouvement;
  331. $dir = $conf->stock->dir_output . "/movement/" . $objectref;
  332. $file = $dir . "/" . $objectref . ".pdf";
  333. }
  334. $stockFournisseur = new ProductFournisseur($this->db);
  335. $supplierprices = $stockFournisseur->list_product_fournisseur_price($object->id);
  336. $object->supplierprices = $supplierprices;
  337. $productstatic=new Product($db);
  338. if (! file_exists($dir))
  339. {
  340. if (dol_mkdir($dir) < 0)
  341. {
  342. $this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir);
  343. return -1;
  344. }
  345. }
  346. if (file_exists($dir))
  347. {
  348. // Add pdfgeneration hook
  349. if (! is_object($hookmanager))
  350. {
  351. include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
  352. $hookmanager=new HookManager($this->db);
  353. }
  354. $hookmanager->initHooks(array('pdfgeneration'));
  355. $parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs);
  356. global $action;
  357. $reshook=$hookmanager->executeHooks('beforePDFCreation',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  358. // Create pdf instance
  359. $pdf=pdf_getInstance($this->format);
  360. $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
  361. $pdf->SetAutoPageBreak(1,0);
  362. $heightforinfotot = 40; // Height reserved to output the info and total part
  363. $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
  364. $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
  365. if (class_exists('TCPDF'))
  366. {
  367. $pdf->setPrintHeader(false);
  368. $pdf->setPrintFooter(false);
  369. }
  370. $pdf->SetFont(pdf_getPDFFont($outputlangs));
  371. // Set path to the background PDF File
  372. if (empty($conf->global->MAIN_DISABLE_FPDI) && ! empty($conf->global->MAIN_ADD_PDF_BACKGROUND))
  373. {
  374. $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND);
  375. $tplidx = $pdf->importPage(1);
  376. }
  377. $pdf->Open();
  378. $pagenb=0;
  379. $pdf->SetDrawColor(128,128,128);
  380. $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
  381. $pdf->SetSubject($outputlangs->transnoentities("Stock"));
  382. $pdf->SetCreator("Dolibarr ".DOL_VERSION);
  383. $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
  384. $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Stock")." ".$outputlangs->convToOutputCharset($object->libelle));
  385. if (! empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false);
  386. $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
  387. // New page
  388. $pdf->AddPage();
  389. if (! empty($tplidx)) $pdf->useTemplate($tplidx);
  390. $pagenb++;
  391. $this->_pagehead($pdf, $object, 1, $outputlangs);
  392. $pdf->SetFont('','', $default_font_size - 1);
  393. $pdf->MultiCell(0, 3, ''); // Set interline to 3
  394. $pdf->SetTextColor(0,0,0);
  395. $tab_top = 42;
  396. $tab_top_newpage = (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)?42:10);
  397. $tab_height = 130;
  398. $tab_height_newpage = 150;
  399. /* ************************************************************************** */
  400. /* */
  401. /* Affichage de la liste des produits du MouvementStock */
  402. /* */
  403. /* ************************************************************************** */
  404. $nexY+=5;
  405. $nexY = $pdf->GetY();
  406. $nexY+=10;
  407. $totalunit=0;
  408. $totalvalue=$totalvaluesell=0;
  409. $arrayofuniqueproduct = array();
  410. //dol_syslog('List products', LOG_DEBUG);
  411. $resql = $db->query($sql);
  412. if ($resql)
  413. {
  414. $num = $db->num_rows($resql);
  415. $i = 0;
  416. $nblignes = $num;
  417. for ($i = 0 ; $i < $nblignes ; $i++)
  418. {
  419. $objp = $db->fetch_object($resql);
  420. // Multilangs
  421. if (! empty($conf->global->MAIN_MULTILANGS)) // si l'option est active
  422. {
  423. $sql = "SELECT label";
  424. $sql.= " FROM ".MAIN_DB_PREFIX."product_lang";
  425. $sql.= " WHERE fk_product=".$objp->rowid;
  426. $sql.= " AND lang='". $langs->getDefaultLang() ."'";
  427. $sql.= " LIMIT 1";
  428. $result = $db->query($sql);
  429. if ($result)
  430. {
  431. $objtp = $db->fetch_object($result);
  432. if ($objtp->label != '') $objp->produit = $objtp->label;
  433. }
  434. }
  435. $curY = $nexY;
  436. $pdf->SetFont('','', $default_font_size - 1); // Into loop to work with multipage
  437. $pdf->SetTextColor(0,0,0);
  438. $pdf->setTopMargin($tab_top_newpage);
  439. $pdf->setPageOrientation('', 1, $heightforfooter+$heightforfreetext+$heightforinfotot); // The only function to edit the bottom margin of current page to set it.
  440. $pageposbefore=$pdf->getPage();
  441. // Description of product line
  442. $curX = $this->posxdesc-1;
  443. $showpricebeforepagebreak=1;
  444. $pdf->startTransaction();
  445. pdf_writelinedesc($pdf,$object,$i,$outputlangs,$this->posxtva-$curX,3,$curX,$curY,$hideref,$hidedesc);
  446. $pageposafter=$pdf->getPage();
  447. if ($pageposafter > $pageposbefore) // There is a pagebreak
  448. {
  449. $pdf->rollbackTransaction(true);
  450. $pageposafter=$pageposbefore;
  451. //print $pageposafter.'-'.$pageposbefore;exit;
  452. $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
  453. pdf_writelinedesc($pdf,$object,$i,$outputlangs,$this->posxtva-$curX,4,$curX,$curY,$hideref,$hidedesc);
  454. $pageposafter=$pdf->getPage();
  455. $posyafter=$pdf->GetY();
  456. if ($posyafter > ($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))) // There is no space left for total+free text
  457. {
  458. if ($i == ($nblignes-1)) // No more lines, and no space left to show total, so we create a new page
  459. {
  460. $pdf->AddPage('','',true);
  461. if (! empty($tplidx)) $pdf->useTemplate($tplidx);
  462. if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs);
  463. $pdf->setPage($pageposafter+1);
  464. }
  465. }
  466. else
  467. {
  468. // We found a page break
  469. $showpricebeforepagebreak=0;
  470. }
  471. }
  472. else // No pagebreak
  473. {
  474. $pdf->commitTransaction();
  475. }
  476. $posYAfterDescription=$pdf->GetY();
  477. $nexY = $pdf->GetY();
  478. $pageposafter=$pdf->getPage();
  479. $pdf->setPage($pageposbefore);
  480. $pdf->setTopMargin($this->marge_haute);
  481. $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
  482. // We suppose that a too long description is moved completely on next page
  483. if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
  484. $pdf->setPage($pageposafter); $curY = $tab_top_newpage;
  485. }
  486. $pdf->SetFont('','', $default_font_size - 1); // On repositionne la police par defaut
  487. // $objp = $db->fetch_object($resql);
  488. $userstatic->id=$objp->fk_user_author;
  489. $userstatic->login=$objp->login;
  490. $userstatic->lastname=$objp->lastname;
  491. $userstatic->firstname=$objp->firstname;
  492. $userstatic->photo=$objp->photo;
  493. $productstatic->id=$objp->rowid;
  494. $productstatic->ref=$objp->product_ref;
  495. $productstatic->label=$objp->produit;
  496. $productstatic->type=$objp->type;
  497. $productstatic->entity=$objp->entity;
  498. $productstatic->status_batch=$objp->tobatch;
  499. $productlot->id = $objp->lotid;
  500. $productlot->batch= $objp->batch;
  501. $productlot->eatby= $objp->eatby;
  502. $productlot->sellby= $objp->sellby;
  503. $warehousestatic->id=$objp->entrepot_id;
  504. $warehousestatic->libelle=$objp->stock;
  505. $warehousestatic->lieu=$objp->lieu;
  506. $arrayofuniqueproduct[$objp->rowid]=$objp->produit;
  507. if(!empty($objp->fk_origin)) {
  508. $origin = $movement->get_origin($objp->fk_origin, $objp->origintype);
  509. } else {
  510. $origin = '';
  511. }
  512. // Id movement.
  513. $pdf->SetXY($this->posxidref, $curY);
  514. $pdf->MultiCell($this->posxdesc-$this->posxidref-0.8, 3, $objp->mid, 0, 'L');
  515. // Date.
  516. $pdf->SetXY($this->posxdatemouv, $curY);
  517. $pdf->MultiCell($this->posxdesc-$this->posxdatemouv-0.8, 6, dol_print_date($db->jdate($objp->datem),'dayhour'), 0, 'L');
  518. // Ref.
  519. $pdf->SetXY($this->posxdesc, $curY);
  520. $pdf->MultiCell($this->posxlabel-$this->posxdesc-0.8, 3, $productstatic->ref, 0, 'L');
  521. // Label
  522. $pdf->SetXY($this->posxlabel+0.8, $curY);
  523. $pdf->MultiCell($this->posxqty-$this->posxlabel-0.8, 6, $productstatic->label, 0, 'L');
  524. // Lot/serie
  525. $pdf->SetXY($this->posxqty, $curY);
  526. $pdf->MultiCell($this->posxup-$this->posxqty-0.8, 3, $productlot->batch, 0, 'R');
  527. // Inv. code
  528. $pdf->SetXY($this->posxup, $curY);
  529. $pdf->MultiCell($this->posxunit-$this->posxup-0.8, 3, $objp->inventorycode, 0, 'R');
  530. // Label mouvement
  531. $pdf->SetXY($this->posxunit, $curY);
  532. $pdf->MultiCell($this->posxdiscount-$this->posxunit-0.8, 3, $objp->label, 0, 'R');
  533. $totalvalue+=price2num($objp->ppmp*$objp->value,'MT');
  534. // Origin
  535. $pricemin=$objp->price;
  536. $pdf->SetXY($this->posxdiscount, $curY);
  537. $pdf->MultiCell($this->postotalht-$this->posxdiscount-0.8, 3, $origin, 0, 'R', 0);
  538. // Qty
  539. $valtoshow=price2num($objp->qty, 'MS');
  540. $towrite = (empty($valtoshow)?'0':$valtoshow);
  541. $totalunit+=$objp->qty;
  542. $pdf->SetXY($this->postotalht, $curY);
  543. $pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->postotalht, 3, $objp->qty, 0, 'R', 0);
  544. $totalvaluesell+=price2num($pricemin*$objp->value,'MT');
  545. $nexY+=3.5; // Passe espace entre les lignes
  546. // Add line
  547. if (! empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblignes - 1))
  548. {
  549. $pdf->setPage($pageposafter);
  550. $pdf->SetLineStyle(array('dash'=>'1,1','color'=>array(80,80,80)));
  551. //$pdf->SetDrawColor(190,190,200);
  552. $pdf->line($this->marge_gauche, $nexY+1, $this->page_largeur - $this->marge_droite, $nexY+1);
  553. $pdf->SetLineStyle(array('dash'=>0));
  554. }
  555. $nexY+=2; // Passe espace entre les lignes
  556. // Detect if some page were added automatically and output _tableau for past pages
  557. while ($pagenb < $pageposafter)
  558. {
  559. $pdf->setPage($pagenb);
  560. if ($pagenb == 1)
  561. {
  562. $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
  563. }
  564. else
  565. {
  566. $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
  567. }
  568. $this->_pagefoot($pdf,$object,$outputlangs,1);
  569. $pagenb++;
  570. $pdf->setPage($pagenb);
  571. $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
  572. if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs);
  573. }
  574. if (isset($object->lines[$i+1]->pagebreak) && $object->lines[$i+1]->pagebreak)
  575. {
  576. if ($pagenb == 1)
  577. {
  578. $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
  579. }
  580. else
  581. {
  582. $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
  583. }
  584. $this->_pagefoot($pdf,$object,$outputlangs,1);
  585. // New page
  586. $pdf->AddPage();
  587. if (! empty($tplidx)) $pdf->useTemplate($tplidx);
  588. $pagenb++;
  589. if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs);
  590. }
  591. }
  592. $db->free($resql);
  593. /**
  594. * footer table
  595. */
  596. $nexY = $pdf->GetY();
  597. $nexY+=5;
  598. $curY = $nexY;
  599. $pdf->SetLineStyle(array('dash'=>'0','color'=>array(220,26,26)));
  600. $pdf->line($this->marge_gauche, $curY-1, $this->page_largeur-$this->marge_droite, $curY-1);
  601. $pdf->SetLineStyle(array('dash'=>0));
  602. $pdf->SetFont('','B',$default_font_size-1);
  603. $pdf->SetTextColor(0,0,120);
  604. // Total
  605. $pdf->SetXY($this->posxidref, $curY);
  606. $pdf->MultiCell($this->posxdesc-$this->posxidref, 3, $langs->trans("Total"), 0, 'L');
  607. // Total Qty
  608. $pdf->SetXY($this->postotalht, $curY);
  609. $pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->postotalht, 3, $totalunit, 0, 'R', 0);
  610. }
  611. else
  612. {
  613. dol_print_error($db);
  614. }
  615. if ($notetoshow)
  616. {
  617. $substitutionarray=pdf_getSubstitutionArray($outputlangs, null, $object);
  618. complete_substitutions_array($substitutionarray, $outputlangs, $object);
  619. $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
  620. $tab_top = 88;
  621. $pdf->SetFont('','', $default_font_size - 1);
  622. $pdf->writeHTMLCell(190, 3, $this->posxdesc-1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
  623. $nexY = $pdf->GetY();
  624. $height_note=$nexY-$tab_top;
  625. // Rect prend une longueur en 3eme param
  626. $pdf->SetDrawColor(192,192,192);
  627. $pdf->Rect($this->marge_gauche, $tab_top-1, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $height_note+1);
  628. $tab_height = $tab_height - $height_note;
  629. $tab_top = $nexY+6;
  630. }
  631. else
  632. {
  633. $height_note=0;
  634. }
  635. $iniY = $tab_top + 7;
  636. $curY = $tab_top + 7;
  637. $nexY = $tab_top + 7;
  638. $tab_top = $tab_top_newpage+21;
  639. // Show square
  640. if ($pagenb == 1)
  641. {
  642. $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0, $object->multicurrency_code);
  643. $bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
  644. }
  645. else
  646. {
  647. $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
  648. $bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
  649. }
  650. $bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
  651. // Affiche zone infos
  652. //$posy=$this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
  653. // Affiche zone totaux
  654. //$posy=$this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
  655. // Pied de page
  656. $this->_pagefoot($pdf,$object,$outputlangs);
  657. if (method_exists($pdf,'AliasNbPages')) $pdf->AliasNbPages();
  658. $pdf->Close();
  659. $pdf->Output($file,'F');
  660. // Add pdfgeneration hook
  661. $hookmanager->initHooks(array('pdfgeneration'));
  662. $parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs);
  663. global $action;
  664. $reshook=$hookmanager->executeHooks('afterPDFCreation',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
  665. if (! empty($conf->global->MAIN_UMASK))
  666. @chmod($file, octdec($conf->global->MAIN_UMASK));
  667. $this->result = array('fullpath'=>$file);
  668. return 1; // Pas d'erreur
  669. }
  670. else
  671. {
  672. $this->error=$langs->trans("ErrorCanNotCreateDir",$dir);
  673. return 0;
  674. }
  675. }
  676. else
  677. {
  678. $this->error=$langs->trans("ErrorConstantNotDefined","PRODUCT_OUTPUTDIR");
  679. return 0;
  680. }
  681. }
  682. /**
  683. * Show table for lines
  684. *
  685. * @param TCPDF $pdf Object PDF
  686. * @param string $tab_top Top position of table
  687. * @param string $tab_height Height of table (rectangle)
  688. * @param int $nexY Y (not used)
  689. * @param Translate $outputlangs Langs object
  690. * @param int $hidetop 1=Hide top bar of array and title, 0=Hide nothing, -1=Hide only title
  691. * @param int $hidebottom Hide bottom bar of array
  692. * @param string $currency Currency code
  693. * @return void
  694. */
  695. function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='')
  696. {
  697. global $conf;
  698. // Force to disable hidetop and hidebottom
  699. $hidebottom=0;
  700. if ($hidetop) $hidetop=-1;
  701. $currency = !empty($currency) ? $currency : $conf->currency;
  702. $default_font_size = pdf_getPDFFontSize($outputlangs);
  703. // Amount in (at tab_top - 1)
  704. $pdf->SetTextColor(0,0,0);
  705. $pdf->SetFont('','', $default_font_size - 2);
  706. if (empty($hidetop))
  707. {
  708. $titre = $outputlangs->transnoentities("AmountInCurrency",$outputlangs->transnoentitiesnoconv("Currency".$currency));
  709. $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top-4);
  710. $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
  711. //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
  712. 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));
  713. }
  714. $pdf->SetDrawColor(128,128,128);
  715. $pdf->SetFont('','B', $default_font_size - 3);
  716. // Output Rect
  717. //$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
  718. $pdf->SetLineStyle(array('dash'=>'0','color'=>array(220,26,26)));
  719. $pdf->SetDrawColor(220,26,26);
  720. $pdf->line($this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_droite, $tab_top);
  721. $pdf->SetLineStyle(array('dash'=>0));
  722. $pdf->SetDrawColor(128,128,128);
  723. $pdf->SetTextColor(0,0,120);
  724. //Ref mouv
  725. if (empty($hidetop))
  726. {
  727. //$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
  728. $pdf->SetXY($this->posxidref, $tab_top+1);
  729. $pdf->MultiCell($this->posxdatemouv-$this->posxdatemouv-0.8,3, $outputlangs->transnoentities("Ref"),'','L');
  730. }
  731. //Date mouv
  732. //$pdf->line($this->posxlabel-1, $tab_top, $this->posxlabel-1, $tab_top + $tab_height);
  733. if (empty($hidetop))
  734. {
  735. $pdf->SetXY($this->posxdatemouv, $tab_top+1);
  736. $pdf->MultiCell($this->posxdesc-$this->posxdatemouv,2, $outputlangs->transnoentities("Date"),'','C');
  737. }
  738. //Ref Product
  739. //$pdf->line($this->posxqty-1, $tab_top, $this->posxqty-1, $tab_top + $tab_height);
  740. if (empty($hidetop))
  741. {
  742. $pdf->SetXY($this->posxdesc-1, $tab_top+1);
  743. $pdf->MultiCell($this->posxlabel-$this->posxdesc,2, $outputlangs->transnoentities("Ref. Product"),'','C');
  744. }
  745. //Label Product
  746. //$pdf->line($this->posxup-1, $tab_top, $this->posxup-1, $tab_top + $tab_height);
  747. if (empty($hidetop))
  748. {
  749. $pdf->SetXY($this->posxlabel-1, $tab_top+1);
  750. $pdf->MultiCell($this->posxqty-$this->posxlabel,2, $outputlangs->transnoentities("Label"),'','C');
  751. }
  752. //Lot/serie Product
  753. //$pdf->line($this->posxqty - 1, $tab_top, $this->posxqty - 1, $tab_top + $tab_height);
  754. if (empty($hidetop))
  755. {
  756. $pdf->SetXY($this->posxqty, $tab_top + 1);
  757. $pdf->MultiCell($this->posxup - $this->posxqty, 2, $outputlangs->transnoentities("Lot/Série"), '','C');
  758. }
  759. //Code Inv
  760. //$pdf->line($this->posxup-1, $tab_top, $this->posxup-1, $tab_top + $tab_height);
  761. if (empty($hidetop))
  762. {
  763. $pdf->SetXY($this->posxup-1, $tab_top+1);
  764. $pdf->MultiCell($this->posxunit-$this->posxup,2, $outputlangs->transnoentities("Inventory Code"),'','C');
  765. }
  766. //Label mouvement
  767. //$pdf->line($this->posxunit, $tab_top, $this->posxunit, $tab_top + $tab_height);
  768. if (empty($hidetop))
  769. {
  770. $pdf->SetXY($this->posxunit, $tab_top+1);
  771. $pdf->MultiCell($this->posxdiscount-$this->posxunit,2, $outputlangs->transnoentities("Label Mouvement"),'','C');
  772. }
  773. //Origin
  774. //$pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height);
  775. if (empty($hidetop))
  776. {
  777. $pdf->SetXY($this->posxdiscount+2, $tab_top+1);
  778. $pdf->MultiCell($this->postotalht-$this->posxdiscount-0.8,2, $outputlangs->transnoentities("Origin"),'','C');
  779. }
  780. //Qty
  781. //$pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height);
  782. if (empty($hidetop))
  783. {
  784. $pdf->SetXY($this->postotalht+2, $tab_top+1);
  785. $pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->postotalht,2, $outputlangs->transnoentities("Qty"),'','C');
  786. }
  787. $pdf->SetDrawColor(220,26,26);
  788. $pdf->SetLineStyle(array('dash'=>'0','color'=>array(220,26,26)));
  789. $pdf->line($this->marge_gauche, $tab_top+11, $this->page_largeur-$this->marge_droite, $tab_top+11);
  790. $pdf->SetLineStyle(array('dash'=>0));
  791. }
  792. /**
  793. * Show top header of page.
  794. *
  795. * @param TCPDF $pdf Object PDF
  796. * @param Object $object Object to show
  797. * @param int $showaddress 0=no, 1=yes
  798. * @param Translate $outputlangs Object lang for output
  799. * @param string $titlekey Translation key to show as title of document
  800. * @return void
  801. */
  802. function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey="")
  803. {
  804. global $conf,$langs,$db,$hookmanager;
  805. // Load traductions files requiredby by page
  806. $outputlangs->loadLangs(array("main", "propal", "companies", "bills", "orders", "stocks"));
  807. $default_font_size = pdf_getPDFFontSize($outputlangs);
  808. if ($object->type == 1) $titlekey='ServiceSheet';
  809. else $titlekey='StockSheet';
  810. pdf_pagehead($pdf,$outputlangs,$this->page_hauteur);
  811. // Show Draft Watermark
  812. if($object->statut==0 && (! empty($conf->global->COMMANDE_DRAFT_WATERMARK)) )
  813. {
  814. pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',$conf->global->COMMANDE_DRAFT_WATERMARK);
  815. }
  816. $pdf->SetTextColor(0,0,60);
  817. $pdf->SetFont('','B', $default_font_size + 3);
  818. $posy=$this->marge_haute;
  819. $posx=$this->page_largeur-$this->marge_droite-100;
  820. $pdf->SetXY($this->marge_gauche,$posy);
  821. // Logo
  822. $logo=$conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo;
  823. if ($this->emetteur->logo)
  824. {
  825. if (is_readable($logo))
  826. {
  827. $height=pdf_getHeightForLogo($logo);
  828. $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
  829. }
  830. else
  831. {
  832. $pdf->SetTextColor(200,0,0);
  833. $pdf->SetFont('','B', $default_font_size -2);
  834. $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound",$logo), 0, 'L');
  835. $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
  836. }
  837. }
  838. else
  839. {
  840. $text=$this->emetteur->name;
  841. $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L');
  842. }
  843. $pdf->SetFont('','B', $default_font_size + 3);
  844. $pdf->SetXY($posx,$posy);
  845. $pdf->SetTextColor(0,0,60);
  846. $title=$outputlangs->transnoentities("Warehouse");
  847. $pdf->MultiCell(100, 3, $title, '', 'R');
  848. $pdf->SetFont('','B',$default_font_size);
  849. $posy+=5;
  850. $pdf->SetXY($posx,$posy);
  851. $pdf->SetTextColor(0,0,60);
  852. $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : " . $outputlangs->convToOutputCharset($object->libelle), '', 'R');
  853. $posy+=5;
  854. $pdf->SetFont('','', $default_font_size - 1);
  855. $pdf->SetXY($posx,$posy);
  856. $pdf->SetTextColor(0,0,60);
  857. $pdf->MultiCell(100, 3, $outputlangs->transnoentities("LocationSummary").' :', '', 'R');
  858. $posy+=4;
  859. $pdf->SetXY($posx-50,$posy);
  860. $pdf->MultiCell(150, 3, $object->lieu, '', 'R');
  861. // Parent MouvementStock
  862. $posy+=4;
  863. $pdf->SetXY($posx,$posy);
  864. $pdf->SetTextColor(0,0,60);
  865. $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ParentWarehouse").' :', '', 'R');
  866. $posy+=4;
  867. $pdf->SetXY($posx-50,$posy);
  868. $e = new MouvementStock($db);
  869. if(!empty($object->fk_parent) && $e->fetch($object->fk_parent) > 0)
  870. {
  871. $pdf->MultiCell(150, 3, $e->libelle, '', 'R');
  872. }
  873. else
  874. {
  875. $pdf->MultiCell(150, 3, $outputlangs->transnoentities("None"), '', 'R');
  876. }
  877. // Description
  878. $nexY = $pdf->GetY();
  879. $nexY+=5;
  880. $pdf->SetXY($posx,$posy);
  881. $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, '<b>'.$outputlangs->transnoentities("Description").' : </b>'.nl2br($object->description), 0, 1);
  882. $nexY = $pdf->GetY();
  883. $calcproductsunique=$object->nb_different_products();
  884. $calcproducts=$object->nb_products();
  885. // Total nb of different products
  886. $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, '<b>'.$outputlangs->transnoentities("NumberOfDifferentProducts").' : </b>'.(empty($calcproductsunique['nb'])?'0':$calcproductsunique['nb']), 0, 1);
  887. $nexY = $pdf->GetY();
  888. // Nb of products
  889. $valtoshow=price2num($calcproducts['nb'], 'MS');
  890. $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, '<b>'.$outputlangs->transnoentities("NumberOfProducts").' : </b>'.(empty($valtoshow)?'0':$valtoshow), 0, 1);
  891. $nexY = $pdf->GetY();
  892. // Value
  893. $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, '<b>'.$outputlangs->transnoentities("EstimatedStockValueShort").' : </b>'. price((empty($calcproducts['value'])?'0':price2num($calcproducts['value'],'MT')), 0, $langs, 0, -1, -1, $conf->currency), 0, 1);
  894. $nexY = $pdf->GetY();
  895. // Last movement
  896. $sql = "SELECT max(m.datem) as datem";
  897. $sql .= " FROM ".MAIN_DB_PREFIX."stock_mouvement as m";
  898. $sql .= " WHERE m.fk_entrepot = '".$object->id."'";
  899. $resqlbis = $db->query($sql);
  900. if ($resqlbis)
  901. {
  902. $obj = $db->fetch_object($resqlbis);
  903. $lastmovementdate=$db->jdate($obj->datem);
  904. }
  905. else
  906. {
  907. dol_print_error($db);
  908. }
  909. if ($lastmovementdate)
  910. {
  911. $toWrite = dol_print_date($lastmovementdate,'dayhour').' ';
  912. }
  913. else
  914. {
  915. $toWrite = $outputlangs->transnoentities("None");
  916. }
  917. $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, '<b>'.$outputlangs->transnoentities("LastMovement").' : </b>'.$toWrite, 0, 1);
  918. $nexY = $pdf->GetY();
  919. /*if ($object->ref_client)
  920. {
  921. $posy+=5;
  922. $pdf->SetXY($posx,$posy);
  923. $pdf->SetTextColor(0,0,60);
  924. $pdf->MultiCell(100, 3, $outputlangs->transnoentities("RefCustomer")." : " . $outputlangs->convToOutputCharset($object->ref_client), '', 'R');
  925. }*/
  926. /*$posy+=4;
  927. $pdf->SetXY($posx,$posy);
  928. $pdf->SetTextColor(0,0,60);
  929. $pdf->MultiCell(100, 3, $outputlangs->transnoentities("OrderDate")." : " . dol_print_date($object->date,"%d %b %Y",false,$outputlangs,true), '', 'R');
  930. */
  931. // Get contact
  932. /*
  933. if (!empty($conf->global->DOC_SHOW_FIRST_SALES_REP))
  934. {
  935. $arrayidcontact=$object->getIdContact('internal','SALESREPFOLL');
  936. if (count($arrayidcontact) > 0)
  937. {
  938. $usertmp=new User($this->db);
  939. $usertmp->fetch($arrayidcontact[0]);
  940. $posy+=4;
  941. $pdf->SetXY($posx,$posy);
  942. $pdf->SetTextColor(0,0,60);
  943. $pdf->MultiCell(100, 3, $langs->trans("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R');
  944. }
  945. }*/
  946. $posy+=2;
  947. // Show list of linked objects
  948. //$posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size);
  949. if ($showaddress)
  950. {
  951. /*
  952. // Sender properties
  953. $carac_emetteur = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty);
  954. // Show sender
  955. $posy=42;
  956. $posx=$this->marge_gauche;
  957. if (! empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) $posx=$this->page_largeur-$this->marge_droite-80;
  958. $hautcadre=40;
  959. // Show sender frame
  960. $pdf->SetTextColor(0,0,0);
  961. $pdf->SetFont('','', $default_font_size - 2);
  962. $pdf->SetXY($posx,$posy-5);
  963. $pdf->MultiCell(66,5, $outputlangs->transnoentities("BillFrom").":", 0, 'L');
  964. $pdf->SetXY($posx,$posy);
  965. $pdf->SetFillColor(230,230,230);
  966. $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1);
  967. $pdf->SetTextColor(0,0,60);
  968. // Show sender name
  969. $pdf->SetXY($posx+2,$posy+3);
  970. $pdf->SetFont('','B', $default_font_size);
  971. $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L');
  972. $posy=$pdf->getY();
  973. // Show sender information
  974. $pdf->SetXY($posx+2,$posy);
  975. $pdf->SetFont('','', $default_font_size - 1);
  976. $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L');
  977. */
  978. }
  979. $pdf->SetTextColor(0,0,0);
  980. }
  981. /**
  982. * Show footer of page. Need this->emetteur object
  983. *
  984. * @param TCPDF $pdf PDF
  985. * @param Object $object Object to show
  986. * @param Translate $outputlangs Object lang for output
  987. * @param int $hidefreetext 1=Hide free text
  988. * @return int Return height of bottom margin including footer text
  989. */
  990. function _pagefoot(&$pdf,$object,$outputlangs,$hidefreetext=0)
  991. {
  992. global $conf;
  993. $showdetails=$conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS;
  994. return pdf_pagefoot($pdf,$outputlangs,'PRODUCT_FREE_TEXT',$this->emetteur,$this->marge_basse,$this->marge_gauche,$this->page_hauteur,$object,$showdetails,$hidefreetext);
  995. }
  996. }