delivery.class.php 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257
  1. <?php
  2. /* Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2005-2014 Regis Houssin <regis.houssin@inodbox.com>
  4. * Copyright (C) 2006-2007 Laurent Destailleur <eldy@users.sourceforge.net>
  5. * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
  6. * Copyright (C) 2011-2023 Philippe Grand <philippe.grand@atoo-net.com>
  7. * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
  8. * Copyright (C) 2014-2015 Marcos García <marcosgdf@gmail.com>
  9. * Copyright (C) 2023 Frédéric France <frederic.france@netlogic.fr>
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 3 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  23. */
  24. /**
  25. * \file htdocs/delivery/class/delivery.class.php
  26. * \ingroup delivery
  27. * \brief Delivery Order Management Class File
  28. */
  29. require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
  30. require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
  31. require_once DOL_DOCUMENT_ROOT.'/core/class/commonincoterm.class.php';
  32. require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
  33. if (isModEnabled("propal")) {
  34. require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
  35. }
  36. if (isModEnabled('commande')) {
  37. require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
  38. }
  39. /**
  40. * Class to manage receptions
  41. */
  42. class Delivery extends CommonObject
  43. {
  44. use CommonIncoterm;
  45. /**
  46. * @var string ID to identify managed object
  47. */
  48. public $element = "delivery";
  49. /**
  50. * @var string Field with ID of parent key if this field has a parent
  51. */
  52. public $fk_element = "fk_delivery";
  53. /**
  54. * @var string Name of table without prefix where object is stored
  55. */
  56. public $table_element = "delivery";
  57. /**
  58. * @var string Name of subtable line
  59. */
  60. public $table_element_line = "deliverydet";
  61. /**
  62. * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
  63. */
  64. public $picto = 'sending';
  65. /**
  66. * @var int draft status
  67. */
  68. public $draft;
  69. /**
  70. * @var int thirdparty id
  71. */
  72. public $socid;
  73. /**
  74. * @var string ref custome
  75. */
  76. public $ref_customer;
  77. /**
  78. * @var integer|string Date really received
  79. */
  80. public $date_delivery;
  81. /**
  82. * @var integer|string date_creation
  83. */
  84. public $date_creation;
  85. /**
  86. * @var integer|string date_valid
  87. */
  88. public $date_valid;
  89. /**
  90. * @var string model pdf
  91. */
  92. public $model_pdf;
  93. public $commande_id;
  94. /**
  95. * @var array Status labels
  96. */
  97. public $labelStatus;
  98. /**
  99. * @var DeliveryLine[] lines
  100. */
  101. public $lines = array();
  102. /**
  103. * @var int user_author_id
  104. */
  105. public $user_author_id;
  106. /**
  107. * Constructor
  108. *
  109. * @param DoliDB $db Database handler
  110. */
  111. public function __construct($db)
  112. {
  113. $this->db = $db;
  114. // List of short language codes for status
  115. $this->labelStatus[-1] = 'StatusDeliveryCanceled';
  116. $this->labelStatus[0] = 'StatusDeliveryDraft';
  117. $this->labelStatus[1] = 'StatusDeliveryValidated';
  118. }
  119. /**
  120. * Create delivery receipt in database
  121. *
  122. * @param User $user Objet du user qui cree
  123. * @return int Return integer <0 si erreur, id delivery cree si ok
  124. */
  125. public function create($user)
  126. {
  127. global $conf;
  128. dol_syslog("Delivery::create");
  129. if (empty($this->model_pdf)) {
  130. $this->model_pdf = $conf->global->DELIVERY_ADDON_PDF;
  131. }
  132. $error = 0;
  133. $now = dol_now();
  134. /* Delivery note as draft On positionne en mode draft le bon de livraison */
  135. $this->draft = 1;
  136. $this->user = $user;
  137. $this->db->begin();
  138. $sql = "INSERT INTO ".MAIN_DB_PREFIX."delivery (";
  139. $sql .= "ref";
  140. $sql .= ", entity";
  141. $sql .= ", fk_soc";
  142. $sql .= ", ref_customer";
  143. $sql .= ", date_creation";
  144. $sql .= ", fk_user_author";
  145. $sql .= ", date_delivery";
  146. $sql .= ", fk_address";
  147. $sql .= ", note_private";
  148. $sql .= ", note_public";
  149. $sql .= ", model_pdf";
  150. $sql .= ", fk_incoterms, location_incoterms";
  151. $sql .= ") VALUES (";
  152. $sql .= "'(PROV)'";
  153. $sql .= ", ".((int) $conf->entity);
  154. $sql .= ", ".((int) $this->socid);
  155. $sql .= ", '".$this->db->escape($this->ref_customer)."'";
  156. $sql .= ", '".$this->db->idate($now)."'";
  157. $sql .= ", ".((int) $user->id);
  158. $sql .= ", ".($this->date_delivery ? "'".$this->db->idate($this->date_delivery)."'" : "null");
  159. $sql .= ", ".($this->fk_delivery_address > 0 ? $this->fk_delivery_address : "null");
  160. $sql .= ", ".(!empty($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null");
  161. $sql .= ", ".(!empty($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : "null");
  162. $sql .= ", ".(!empty($this->model_pdf) ? "'".$this->db->escape($this->model_pdf)."'" : "null");
  163. $sql .= ", ".(int) $this->fk_incoterms;
  164. $sql .= ", '".$this->db->escape($this->location_incoterms)."'";
  165. $sql .= ")";
  166. dol_syslog("Delivery::create", LOG_DEBUG);
  167. $resql = $this->db->query($sql);
  168. if ($resql) {
  169. $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."delivery");
  170. $numref = "(PROV".$this->id.")";
  171. $sql = "UPDATE ".MAIN_DB_PREFIX."delivery ";
  172. $sql .= "SET ref = '".$this->db->escape($numref)."'";
  173. $sql .= " WHERE rowid = ".((int) $this->id);
  174. dol_syslog("Delivery::create", LOG_DEBUG);
  175. $resql = $this->db->query($sql);
  176. if ($resql) {
  177. if (!getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION')) {
  178. $commande = new Commande($this->db);
  179. $commande->id = $this->commande_id;
  180. $commande->fetch_lines();
  181. }
  182. /*
  183. * Inserting products into the database
  184. */
  185. $num = count($this->lines);
  186. for ($i = 0; $i < $num; $i++) {
  187. $origin_id = $this->lines[$i]->origin_line_id;
  188. if (!$origin_id) {
  189. $origin_id = $this->lines[$i]->commande_ligne_id; // For backward compatibility
  190. }
  191. if (!$this->create_line($origin_id, $this->lines[$i]->qty, $this->lines[$i]->fk_product, $this->lines[$i]->description, $this->lines[$i]->array_options)) {
  192. $error++;
  193. }
  194. }
  195. if (!$error && $this->id && $this->origin_id) {
  196. $ret = $this->add_object_linked();
  197. if (!$ret) {
  198. $error++;
  199. }
  200. if (!getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION')) {
  201. $ret = $this->setStatut(2, $this->origin_id, $this->origin);
  202. if (!$ret) {
  203. $error++;
  204. }
  205. }
  206. }
  207. if (!$error) {
  208. $this->db->commit();
  209. return $this->id;
  210. } else {
  211. $error++;
  212. $this->error = $this->db->lasterror()." - sql=".$this->db->lastqueryerror;
  213. $this->db->rollback();
  214. return -3;
  215. }
  216. } else {
  217. $error++;
  218. $this->error = $this->db->lasterror()." - sql=".$this->db->lastqueryerror;
  219. $this->db->rollback();
  220. return -2;
  221. }
  222. } else {
  223. $error++;
  224. $this->error = $this->db->lasterror()." - sql=".$this->db->lastqueryerror;
  225. $this->db->rollback();
  226. return -1;
  227. }
  228. }
  229. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  230. /**
  231. * Create a line
  232. *
  233. * @param string $origin_id Id of order
  234. * @param string $qty Quantity
  235. * @param string $fk_product Id of predefined product
  236. * @param string $description Description
  237. * @param array $array_options Array options
  238. * @return int Return integer <0 if KO, >0 if OK
  239. */
  240. public function create_line($origin_id, $qty, $fk_product, $description, $array_options = null)
  241. {
  242. // phpcs:enable
  243. $error = 0;
  244. $idprod = $fk_product;
  245. $sql = "INSERT INTO ".MAIN_DB_PREFIX."deliverydet (fk_delivery, fk_origin_line,";
  246. $sql .= " fk_product, description, qty)";
  247. $sql .= " VALUES (".$this->id.",".((int) $origin_id).",";
  248. $sql .= " ".($idprod > 0 ? ((int) $idprod) : "null").",";
  249. $sql .= " ".($description ? "'".$this->db->escape($description)."'" : "null").",";
  250. $sql .= (price2num($qty, 'MS')).")";
  251. dol_syslog(get_class($this)."::create_line", LOG_DEBUG);
  252. if (!$this->db->query($sql)) {
  253. $error++;
  254. }
  255. $id = $this->db->last_insert_id(MAIN_DB_PREFIX."deliverydet");
  256. if (is_array($array_options) && count($array_options) > 0) {
  257. $line = new DeliveryLine($this->db);
  258. $line->id = $id;
  259. $line->array_options = $array_options;
  260. $result = $line->insertExtraFields();
  261. }
  262. if (!$error) {
  263. return 1;
  264. }
  265. return -1;
  266. }
  267. /**
  268. * Load a delivery receipt
  269. *
  270. * @param int $id Id of object to load
  271. * @return integer
  272. */
  273. public function fetch($id)
  274. {
  275. $sql = "SELECT l.rowid, l.fk_soc, l.date_creation, l.date_valid, l.ref, l.ref_customer, l.fk_user_author,";
  276. $sql .= " l.total_ht, l.fk_statut, l.fk_user_valid, l.note_private, l.note_public";
  277. $sql .= ", l.date_delivery, l.fk_address, l.model_pdf";
  278. $sql .= ", el.fk_source as origin_id, el.sourcetype as origin";
  279. $sql .= ', l.fk_incoterms, l.location_incoterms';
  280. $sql .= ", i.libelle as label_incoterms";
  281. $sql .= " FROM ".MAIN_DB_PREFIX."delivery as l";
  282. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."element_element as el ON el.fk_target = l.rowid AND el.targettype = '".$this->db->escape($this->element)."'";
  283. $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_incoterms as i ON l.fk_incoterms = i.rowid';
  284. $sql .= " WHERE l.rowid = ".((int) $id);
  285. dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
  286. $result = $this->db->query($sql);
  287. if ($result) {
  288. if ($this->db->num_rows($result)) {
  289. $obj = $this->db->fetch_object($result);
  290. $this->id = $obj->rowid;
  291. $this->date_delivery = $this->db->jdate($obj->date_delivery);
  292. $this->date_creation = $this->db->jdate($obj->date_creation);
  293. $this->date_valid = $this->db->jdate($obj->date_valid);
  294. $this->ref = $obj->ref;
  295. $this->ref_customer = $obj->ref_customer;
  296. $this->socid = $obj->fk_soc;
  297. $this->statut = $obj->fk_statut;
  298. $this->status = $obj->fk_statut;
  299. $this->user_author_id = $obj->fk_user_author;
  300. $this->user_validation_id = $obj->fk_user_valid;
  301. $this->fk_delivery_address = $obj->fk_address;
  302. $this->note = $obj->note_private; //TODO deprecated
  303. $this->note_private = $obj->note_private;
  304. $this->note_public = $obj->note_public;
  305. $this->model_pdf = $obj->model_pdf;
  306. $this->origin = $obj->origin; // May be 'shipping'
  307. $this->origin_id = $obj->origin_id; // May be id of shipping
  308. //Incoterms
  309. $this->fk_incoterms = $obj->fk_incoterms;
  310. $this->location_incoterms = $obj->location_incoterms;
  311. $this->label_incoterms = $obj->label_incoterms;
  312. $this->db->free($result);
  313. if ($this->statut == 0) {
  314. $this->draft = 1;
  315. }
  316. // Retrieve all extrafields
  317. // fetch optionals attributes and labels
  318. $this->fetch_optionals();
  319. // Load lines
  320. $result = $this->fetch_lines();
  321. if ($result < 0) {
  322. return -3;
  323. }
  324. return 1;
  325. } else {
  326. $this->error = 'Delivery with id '.$id.' not found sql='.$sql;
  327. dol_syslog(get_class($this).'::fetch Error '.$this->error, LOG_ERR);
  328. return -2;
  329. }
  330. } else {
  331. $this->error = $this->db->error();
  332. return -1;
  333. }
  334. }
  335. /**
  336. * Validate object and update stock if option enabled
  337. *
  338. * @param User $user Object user that validate
  339. * @param int $notrigger 1=Does not execute triggers, 0= execute triggers
  340. * @return int
  341. */
  342. public function valid($user, $notrigger = 0)
  343. {
  344. global $conf;
  345. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  346. dol_syslog(get_class($this)."::valid begin");
  347. $this->db->begin();
  348. $error = 0;
  349. if ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('expedition', 'delivery', 'creer'))
  350. || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('expedition', 'delivery_advance', 'validate'))) {
  351. if (getDolGlobalString('DELIVERY_ADDON_NUMBER')) {
  352. // Setting the command numbering module name
  353. $modName = $conf->global->DELIVERY_ADDON_NUMBER;
  354. if (is_readable(DOL_DOCUMENT_ROOT.'/core/modules/delivery/'.$modName.'.php')) {
  355. require_once DOL_DOCUMENT_ROOT.'/core/modules/delivery/'.$modName.'.php';
  356. $now = dol_now();
  357. // Retrieving the new reference
  358. $objMod = new $modName($this->db);
  359. $soc = new Societe($this->db);
  360. $soc->fetch($this->socid);
  361. if (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref)) { // empty should not happened, but when it occurs, the test save life
  362. $numref = $objMod->delivery_get_num($soc, $this);
  363. } else {
  364. $numref = $this->ref;
  365. }
  366. $this->newref = dol_sanitizeFileName($numref);
  367. // Test if is not already in valid status. If so, we stop to avoid decrementing the stock twice.
  368. $sql = "SELECT ref";
  369. $sql .= " FROM ".MAIN_DB_PREFIX."delivery";
  370. $sql .= " WHERE ref = '".$this->db->escape($numref)."'";
  371. $sql .= " AND fk_statut <> 0";
  372. $sql .= " AND entity = ".((int) $conf->entity);
  373. $resql = $this->db->query($sql);
  374. if ($resql) {
  375. $num = $this->db->num_rows($resql);
  376. if ($num > 0) {
  377. return 0;
  378. }
  379. }
  380. $sql = "UPDATE ".MAIN_DB_PREFIX."delivery SET";
  381. $sql .= " ref='".$this->db->escape($numref)."'";
  382. $sql .= ", fk_statut = 1";
  383. $sql .= ", date_valid = '".$this->db->idate($now)."'";
  384. $sql .= ", fk_user_valid = ".$user->id;
  385. $sql .= " WHERE rowid = ".((int) $this->id);
  386. $sql .= " AND fk_statut = 0";
  387. $resql = $this->db->query($sql);
  388. if (!$resql) {
  389. dol_print_error($this->db);
  390. $this->error = $this->db->lasterror();
  391. $error++;
  392. }
  393. if (!$error && !$notrigger) {
  394. // Call trigger
  395. $result = $this->call_trigger('DELIVERY_VALIDATE', $user);
  396. if ($result < 0) {
  397. $error++;
  398. }
  399. // End call triggers
  400. }
  401. if (!$error) {
  402. $this->oldref = $this->ref;
  403. // Rename directory if dir was a temporary ref
  404. if (preg_match('/^[\(]?PROV/i', $this->ref)) {
  405. // Now we rename also files into index
  406. $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'expedition/receipt/".$this->db->escape($this->newref)."'";
  407. $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'expedition/receipt/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
  408. $resql = $this->db->query($sql);
  409. if (!$resql) {
  410. $error++;
  411. $this->error = $this->db->lasterror();
  412. }
  413. $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'expedition/receipt/".$this->db->escape($this->newref)."'";
  414. $sql .= " WHERE filepath = 'expedition/receipt/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
  415. $resql = $this->db->query($sql);
  416. if (!$resql) {
  417. $error++;
  418. $this->error = $this->db->lasterror();
  419. }
  420. // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
  421. $oldref = dol_sanitizeFileName($this->ref);
  422. $newref = dol_sanitizeFileName($numref);
  423. $dirsource = $conf->expedition->dir_output.'/receipt/'.$oldref;
  424. $dirdest = $conf->expedition->dir_output.'/receipt/'.$newref;
  425. if (!$error && file_exists($dirsource)) {
  426. dol_syslog(get_class($this)."::valid rename dir ".$dirsource." into ".$dirdest);
  427. if (@rename($dirsource, $dirdest)) {
  428. dol_syslog("Rename ok");
  429. // Rename docs starting with $oldref with $newref
  430. $listoffiles = dol_dir_list($conf->expedition->dir_output.'/receipt/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
  431. foreach ($listoffiles as $fileentry) {
  432. $dirsource = $fileentry['name'];
  433. $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
  434. $dirsource = $fileentry['path'].'/'.$dirsource;
  435. $dirdest = $fileentry['path'].'/'.$dirdest;
  436. @rename($dirsource, $dirdest);
  437. }
  438. }
  439. }
  440. }
  441. // Set new ref and current status
  442. if (!$error) {
  443. $this->ref = $numref;
  444. $this->statut = 1;
  445. }
  446. dol_syslog(get_class($this)."::valid ok");
  447. }
  448. if (!$error) {
  449. $this->db->commit();
  450. return 1;
  451. } else {
  452. $this->db->rollback();
  453. return -1;
  454. }
  455. }
  456. }
  457. return -1;
  458. } else {
  459. $this->error = "NotAllowed";
  460. dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
  461. return -1;
  462. }
  463. }
  464. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  465. /**
  466. * Creating the delivery slip from an existing shipment
  467. *
  468. * @param User $user User who creates
  469. * @param int $sending_id Id of the expedition that serves as a model
  470. * @return integer Return integer <=0 if KO, >0 if OK
  471. */
  472. public function create_from_sending($user, $sending_id)
  473. {
  474. // phpcs:enable
  475. global $conf;
  476. $expedition = new Expedition($this->db);
  477. $result = $expedition->fetch($sending_id);
  478. if ($result <= 0) {
  479. return $result;
  480. }
  481. $this->lines = array();
  482. $num = count($expedition->lines);
  483. for ($i = 0; $i < $num; $i++) {
  484. $line = new DeliveryLine($this->db);
  485. $line->origin_line_id = $expedition->lines[$i]->origin_line_id;
  486. $line->label = $expedition->lines[$i]->label;
  487. $line->description = $expedition->lines[$i]->description;
  488. $line->qty = $expedition->lines[$i]->qty_shipped;
  489. $line->fk_product = $expedition->lines[$i]->fk_product;
  490. if (!getDolGlobalString('MAIN_EXTRAFIELDS_DISABLED') && is_array($expedition->lines[$i]->array_options) && count($expedition->lines[$i]->array_options) > 0) { // For avoid conflicts if trigger used
  491. $line->array_options = $expedition->lines[$i]->array_options;
  492. }
  493. $this->lines[$i] = $line;
  494. }
  495. $this->origin = $expedition->element;
  496. $this->origin_id = $expedition->id;
  497. $this->note_private = $expedition->note_private;
  498. $this->note_public = $expedition->note_public;
  499. $this->fk_project = $expedition->fk_project;
  500. $this->date_delivery = $expedition->date_delivery;
  501. $this->fk_delivery_address = $expedition->fk_delivery_address;
  502. $this->socid = $expedition->socid;
  503. $this->ref_customer = $expedition->ref_customer;
  504. //Incoterms
  505. $this->fk_incoterms = $expedition->fk_incoterms;
  506. $this->location_incoterms = $expedition->location_incoterms;
  507. return $this->create($user);
  508. }
  509. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  510. /**
  511. * Update a livraison line (only extrafields)
  512. *
  513. * @param int $id Id of line (livraison line)
  514. * @param array $array_options extrafields array
  515. * @return int Return integer <0 if KO, >0 if OK
  516. */
  517. public function update_line($id, $array_options = 0)
  518. {
  519. // phpcs:enable
  520. global $conf;
  521. $error = 0;
  522. if ($id > 0 && !$error && !getDolGlobalString('MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) { // For avoid conflicts if trigger used
  523. $line = new DeliveryLine($this->db);
  524. $line->array_options = $array_options;
  525. $line->id = $id;
  526. $result = $line->insertExtraFields();
  527. if ($result < 0) {
  528. $this->error[] = $line->error;
  529. $error++;
  530. }
  531. }
  532. if (!$error) {
  533. return 1;
  534. } else {
  535. return -1;
  536. }
  537. }
  538. /**
  539. * Add line
  540. *
  541. * @param int $origin_id Origin id
  542. * @param int $qty Qty
  543. * @param array $array_options Array options
  544. * @return void
  545. */
  546. public function addline($origin_id, $qty, $array_options = null)
  547. {
  548. global $conf;
  549. $num = count($this->lines);
  550. $line = new DeliveryLine($this->db);
  551. $line->origin_id = $origin_id;
  552. $line->qty = $qty;
  553. if (!getDolGlobalString('MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) { // For avoid conflicts if trigger used
  554. $line->array_options = $array_options;
  555. }
  556. $this->lines[$num] = $line;
  557. }
  558. /**
  559. * Delete line
  560. *
  561. * @param int $lineid Line id
  562. * @return integer Return integer <0 if KO, 0 if nothing done, >0 if OK
  563. */
  564. public function deleteline($lineid)
  565. {
  566. if ($this->statut == 0) {
  567. $sql = "DELETE FROM ".MAIN_DB_PREFIX."commandedet";
  568. $sql .= " WHERE rowid = ".((int) $lineid);
  569. if ($this->db->query($sql)) {
  570. $this->update_price(1);
  571. return 1;
  572. } else {
  573. return -1;
  574. }
  575. }
  576. return 0;
  577. }
  578. /**
  579. * Delete object
  580. *
  581. * @param User $user User making the deletion
  582. * @return integer
  583. */
  584. public function delete($user = null)
  585. {
  586. global $conf, $langs;
  587. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  588. $this->db->begin();
  589. $error = 0;
  590. $sql = "DELETE FROM ".MAIN_DB_PREFIX."deliverydet";
  591. $sql .= " WHERE fk_delivery = ".((int) $this->id);
  592. if ($this->db->query($sql)) {
  593. // Delete linked object
  594. $res = $this->deleteObjectLinked();
  595. if ($res < 0) {
  596. $error++;
  597. }
  598. if (!$error) {
  599. $sql = "DELETE FROM ".MAIN_DB_PREFIX."delivery";
  600. $sql .= " WHERE rowid = ".((int) $this->id);
  601. if ($this->db->query($sql)) {
  602. $this->db->commit();
  603. // Deleting pdf folder's draft On efface le repertoire de pdf provisoire
  604. $ref = dol_sanitizeFileName($this->ref);
  605. if (!empty($conf->expedition->dir_output)) {
  606. $dir = $conf->expedition->dir_output.'/receipt/'.$ref;
  607. $file = $dir.'/'.$ref.'.pdf';
  608. if (file_exists($file)) {
  609. if (!dol_delete_file($file)) {
  610. return 0;
  611. }
  612. }
  613. if (file_exists($dir)) {
  614. if (!dol_delete_dir($dir)) {
  615. $this->error = $langs->trans("ErrorCanNotDeleteDir", $dir);
  616. return 0;
  617. }
  618. }
  619. }
  620. // Call trigger
  621. $result = $this->call_trigger('DELIVERY_DELETE', $user);
  622. if ($result < 0) {
  623. $this->db->rollback();
  624. return -4;
  625. }
  626. // End call triggers
  627. return 1;
  628. } else {
  629. $this->error = $this->db->lasterror()." - sql=$sql";
  630. $this->db->rollback();
  631. return -3;
  632. }
  633. } else {
  634. $this->error = $this->db->lasterror()." - sql=$sql";
  635. $this->db->rollback();
  636. return -2;
  637. }
  638. } else {
  639. $this->error = $this->db->lasterror()." - sql=$sql";
  640. $this->db->rollback();
  641. return -1;
  642. }
  643. }
  644. /**
  645. * getTooltipContentArray
  646. * @param array $params params to construct tooltip data
  647. * @since v18
  648. * @return array
  649. */
  650. public function getTooltipContentArray($params)
  651. {
  652. global $langs;
  653. $langs->load('deliveries');
  654. $datas = [];
  655. $datas['picto'] = img_picto('', $this->picto).' <u>'.$langs->trans("ShowReceiving").'</u>:<br>';
  656. $datas['picto'] .= '<b>'.$langs->trans("Status").'</b>: '.$this->ref;
  657. return $datas;
  658. }
  659. /**
  660. * Return clicable name (with picto eventually)
  661. *
  662. * @param int $withpicto 0=No picto, 1=Include picto into link, 2=Only picto
  663. * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
  664. * @return string Chaine avec URL
  665. */
  666. public function getNomUrl($withpicto = 0, $save_lastsearch_value = -1)
  667. {
  668. global $langs, $hookmanager;
  669. $result = '';
  670. $params = [
  671. 'id' => $this->id,
  672. 'objecttype' => $this->element,
  673. ];
  674. $classfortooltip = 'classfortooltip';
  675. $dataparams = '';
  676. if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
  677. $classfortooltip = 'classforajaxtooltip';
  678. $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
  679. $label = '';
  680. } else {
  681. $label = implode($this->getTooltipContentArray($params));
  682. }
  683. $url = DOL_URL_ROOT.'/delivery/card.php?id='.$this->id;
  684. //if ($option !== 'nolink')
  685. //{
  686. // Add param to save lastsearch_values or not
  687. $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
  688. if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
  689. $add_save_lastsearch_values = 1;
  690. }
  691. if ($add_save_lastsearch_values) {
  692. $url .= '&save_lastsearch_values=1';
  693. }
  694. //}
  695. $linkstart = '<a href="'.$url.'"';
  696. $linkstart .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
  697. $linkstart .= $dataparams.' class="'.$classfortooltip.'">';
  698. $linkend = '</a>';
  699. if ($withpicto) {
  700. $result .= ($linkstart.img_object($label, $this->picto, $dataparams.' class="'.$classfortooltip.'"').$linkend);
  701. }
  702. if ($withpicto && $withpicto != 2) {
  703. $result .= ' ';
  704. }
  705. $result .= $linkstart.$this->ref.$linkend;
  706. global $action;
  707. $hookmanager->initHooks(array($this->element . 'dao'));
  708. $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
  709. $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
  710. if ($reshook > 0) {
  711. $result = $hookmanager->resPrint;
  712. } else {
  713. $result .= $hookmanager->resPrint;
  714. }
  715. return $result;
  716. }
  717. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  718. /**
  719. * Load lines insto $this->lines.
  720. *
  721. * @return int Return integer <0 if KO, >0 if OK
  722. */
  723. public function fetch_lines()
  724. {
  725. // phpcs:enable
  726. $this->lines = array();
  727. $sql = "SELECT ld.rowid, ld.fk_product, ld.description, ld.subprice, ld.total_ht, ld.qty as qty_shipped, ld.fk_origin_line, ";
  728. $sql .= " cd.qty as qty_asked, cd.label as custom_label, cd.fk_unit,";
  729. $sql .= " p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc,";
  730. $sql .= " p.weight, p.weight_units, p.width, p.width_units, p.length, p.length_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units, p.tobatch as product_tobatch";
  731. $sql .= " FROM ".MAIN_DB_PREFIX."commandedet as cd, ".MAIN_DB_PREFIX."deliverydet as ld";
  732. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p on p.rowid = ld.fk_product";
  733. $sql .= " WHERE ld.fk_origin_line = cd.rowid";
  734. $sql .= " AND ld.fk_delivery = ".((int) $this->id);
  735. dol_syslog(get_class($this)."::fetch_lines", LOG_DEBUG);
  736. $resql = $this->db->query($sql);
  737. if ($resql) {
  738. $num = $this->db->num_rows($resql);
  739. $i = 0;
  740. while ($i < $num) {
  741. $obj = $this->db->fetch_object($resql);
  742. $line = new DeliveryLine($this->db);
  743. $line->id = $obj->rowid;
  744. $line->label = $obj->custom_label;
  745. $line->description = $obj->description;
  746. $line->fk_product = $obj->fk_product;
  747. $line->qty_asked = $obj->qty_asked;
  748. $line->qty_shipped = $obj->qty_shipped;
  749. $line->product_label = $obj->product_label; // Product label
  750. $line->product_ref = $obj->product_ref; // Product ref
  751. $line->product_desc = $obj->product_desc; // Product description
  752. $line->product_type = $obj->fk_product_type;
  753. $line->fk_origin_line = $obj->fk_origin_line;
  754. $line->price = $obj->subprice;
  755. $line->total_ht = $obj->total_ht;
  756. // units
  757. $line->weight = $obj->weight;
  758. $line->weight_units = $obj->weight_units;
  759. $line->width = $obj->width;
  760. $line->width_units = $obj->width_units;
  761. $line->height = $obj->height;
  762. $line->height_units = $obj->height_units;
  763. $line->length = $obj->length;
  764. $line->length_units = $obj->length_units;
  765. $line->surface = $obj->surface;
  766. $line->surface_units = $obj->surface_units;
  767. $line->volume = $obj->volume;
  768. $line->volume_units = $obj->volume_units;
  769. $line->fk_unit = $obj->fk_unit;
  770. $line->fetch_optionals();
  771. $this->lines[$i] = $line;
  772. $i++;
  773. }
  774. $this->db->free($resql);
  775. return 1;
  776. } else {
  777. return -1;
  778. }
  779. }
  780. /**
  781. * Return the label of the status
  782. *
  783. * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
  784. * @return string Label of status
  785. */
  786. public function getLibStatut($mode = 0)
  787. {
  788. return $this->LibStatut($this->statut, $mode);
  789. }
  790. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  791. /**
  792. * Return the label of a given status
  793. *
  794. * @param int $status Id status
  795. * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
  796. * @return string Label of status
  797. */
  798. public function LibStatut($status, $mode)
  799. {
  800. // phpcs:enable
  801. global $langs;
  802. if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
  803. global $langs;
  804. //$langs->load("mymodule");
  805. $this->labelStatus[-1] = $langs->transnoentitiesnoconv('StatusDeliveryCanceled');
  806. $this->labelStatus[0] = $langs->transnoentitiesnoconv('StatusDeliveryDraft');
  807. $this->labelStatus[1] = $langs->transnoentitiesnoconv('StatusDeliveryValidated');
  808. $this->labelStatusShort[-1] = $langs->transnoentitiesnoconv('StatusDeliveryCanceled');
  809. $this->labelStatusShort[0] = $langs->transnoentitiesnoconv('StatusDeliveryDraft');
  810. $this->labelStatusShort[1] = $langs->transnoentitiesnoconv('StatusDeliveryValidated');
  811. }
  812. $statusType = 'status0';
  813. if ($status == -1) {
  814. $statusType = 'status5';
  815. }
  816. if ($status == 1) {
  817. $statusType = 'status4';
  818. }
  819. return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
  820. }
  821. /**
  822. * Initialise an instance with random values.
  823. * Used to build previews or test instances.
  824. * id must be 0 if object instance is a specimen.
  825. *
  826. * @return void
  827. */
  828. public function initAsSpecimen()
  829. {
  830. $now = dol_now();
  831. // Load array of products prodids
  832. $num_prods = 0;
  833. $prodids = array();
  834. $sql = "SELECT rowid";
  835. $sql .= " FROM ".MAIN_DB_PREFIX."product";
  836. $sql .= " WHERE entity IN (".getEntity('product').")";
  837. $sql .= " AND tosell = 1";
  838. $sql .= $this->db->plimit(100);
  839. $resql = $this->db->query($sql);
  840. if ($resql) {
  841. $num_prods = $this->db->num_rows($resql);
  842. $i = 0;
  843. while ($i < $num_prods) {
  844. $i++;
  845. $row = $this->db->fetch_row($resql);
  846. $prodids[$i] = $row[0];
  847. }
  848. }
  849. // Initialise parametres
  850. $this->id = 0;
  851. $this->ref = 'SPECIMEN';
  852. $this->specimen = 1;
  853. $this->socid = 1;
  854. $this->date_delivery = $now;
  855. $this->note_public = 'Public note';
  856. $this->note_private = 'Private note';
  857. $i = 0;
  858. $line = new DeliveryLine($this->db);
  859. $line->fk_product = reset($prodids);
  860. $line->qty_asked = 10;
  861. $line->qty_shipped = 9;
  862. $line->ref = 'REFPROD';
  863. $line->label = 'Specimen';
  864. $line->description = 'Description';
  865. $line->price = 100;
  866. $line->total_ht = 100;
  867. $this->lines[$i] = $line;
  868. }
  869. /**
  870. * Renvoie la quantite de produit restante a livrer pour une commande
  871. *
  872. * @return array|int Product remaining to be delivered or <0 if KO
  873. * TODO use new function
  874. */
  875. public function getRemainingDelivered()
  876. {
  877. // Get the linked object
  878. $this->fetchObjectLinked('', '', $this->id, $this->element);
  879. //var_dump($this->linkedObjectsIds);
  880. // Get the product ref and qty in source
  881. $sqlSourceLine = "SELECT st.rowid, st.description, st.qty";
  882. $sqlSourceLine .= ", p.ref, p.label";
  883. $sqlSourceLine .= " FROM ".MAIN_DB_PREFIX.$this->linkedObjectsIds[0]['type']."det as st";
  884. $sqlSourceLine .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON st.fk_product = p.rowid";
  885. $sqlSourceLine .= " WHERE fk_".$this->linked_objects[0]['type']." = ".((int) $this->linked_objects[0]['linkid']);
  886. $resultSourceLine = $this->db->query($sqlSourceLine);
  887. if ($resultSourceLine) {
  888. $num_lines = $this->db->num_rows($resultSourceLine);
  889. $i = 0;
  890. $array = array();
  891. while ($i < $num_lines) {
  892. $objSourceLine = $this->db->fetch_object($resultSourceLine);
  893. // Get lines of sources alread delivered
  894. $sql = "SELECT ld.fk_origin_line, sum(ld.qty) as qty";
  895. $sql .= " FROM ".MAIN_DB_PREFIX."deliverydet as ld, ".MAIN_DB_PREFIX."delivery as l,";
  896. $sql .= " ".MAIN_DB_PREFIX.$this->linked_objects[0]['type']." as c";
  897. $sql .= ", ".MAIN_DB_PREFIX.$this->linked_objects[0]['type']."det as cd";
  898. $sql .= " WHERE ld.fk_delivery = l.rowid";
  899. $sql .= " AND ld.fk_origin_line = cd.rowid";
  900. $sql .= " AND cd.fk_".$this->linked_objects[0]['type']." = c.rowid";
  901. $sql .= " AND cd.fk_".$this->linked_objects[0]['type']." = ".((int) $this->linked_objects[0]['linkid']);
  902. $sql .= " AND ld.fk_origin_line = ".((int) $objSourceLine->rowid);
  903. $sql .= " GROUP BY ld.fk_origin_line";
  904. $result = $this->db->query($sql);
  905. $row = $this->db->fetch_row($result);
  906. if ($objSourceLine->qty - $row[1] > 0) {
  907. if ($row[0] == $objSourceLine->rowid) {
  908. $array[$i]['qty'] = $objSourceLine->qty - $row[1];
  909. } else {
  910. $array[$i]['qty'] = $objSourceLine->qty;
  911. }
  912. $array[$i]['ref'] = $objSourceLine->ref;
  913. $array[$i]['label'] = $objSourceLine->label ? $objSourceLine->label : $objSourceLine->description;
  914. } elseif ($objSourceLine->qty - $row[1] < 0) {
  915. $array[$i]['qty'] = $objSourceLine->qty - $row[1]." Erreur livraison !";
  916. $array[$i]['ref'] = $objSourceLine->ref;
  917. $array[$i]['label'] = $objSourceLine->label ? $objSourceLine->label : $objSourceLine->description;
  918. }
  919. $i++;
  920. }
  921. return $array;
  922. } else {
  923. $this->error = $this->db->error()." - sql=$sqlSourceLine";
  924. return -1;
  925. }
  926. }
  927. /**
  928. * Set the planned delivery date
  929. *
  930. * @param User $user Objet utilisateur qui modifie
  931. * @param integer $delivery_date Delivery date
  932. * @return int Return integer <0 if KO, >0 if OK
  933. */
  934. public function setDeliveryDate($user, $delivery_date)
  935. {
  936. if ($user->hasRight('expedition', 'creer')) {
  937. $sql = "UPDATE ".MAIN_DB_PREFIX."delivery";
  938. $sql .= " SET date_delivery = ".($delivery_date ? "'".$this->db->idate($delivery_date)."'" : 'null');
  939. $sql .= " WHERE rowid = ".((int) $this->id);
  940. dol_syslog(get_class($this)."::setDeliveryDate", LOG_DEBUG);
  941. $resql = $this->db->query($sql);
  942. if ($resql) {
  943. $this->date_delivery = $delivery_date;
  944. return 1;
  945. } else {
  946. $this->error = $this->db->error();
  947. return -1;
  948. }
  949. } else {
  950. return -2;
  951. }
  952. }
  953. /**
  954. * Create object on disk
  955. *
  956. * @param string $modele force le modele a utiliser ('' to not force)
  957. * @param Translate $outputlangs Object langs to use for output
  958. * @param int $hidedetails Hide details of lines
  959. * @param int $hidedesc Hide description
  960. * @param int $hideref Hide ref
  961. * @return int 0 if KO, 1 if OK
  962. */
  963. public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
  964. {
  965. global $conf, $langs;
  966. $langs->load("deliveries");
  967. $outputlangs->load("products");
  968. if (!dol_strlen($modele)) {
  969. $modele = 'typhon';
  970. if ($this->model_pdf) {
  971. $modele = $this->model_pdf;
  972. } elseif (getDolGlobalString('DELIVERY_ADDON_PDF')) {
  973. $modele = $conf->global->DELIVERY_ADDON_PDF;
  974. }
  975. }
  976. $modelpath = "core/modules/delivery/doc/";
  977. return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
  978. }
  979. /**
  980. * Function used to replace a thirdparty id with another one.
  981. *
  982. * @param DoliDB $dbs Database handler, because function is static we name it $dbs not $db to avoid breaking coding test
  983. * @param int $origin_id Old thirdparty id
  984. * @param int $dest_id New thirdparty id
  985. * @return bool
  986. */
  987. public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
  988. {
  989. $tables = array(
  990. 'delivery'
  991. );
  992. return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
  993. }
  994. /**
  995. * Function used to replace a product id with another one.
  996. *
  997. * @param DoliDB $db Database handler
  998. * @param int $origin_id Old product id
  999. * @param int $dest_id New product id
  1000. * @return bool
  1001. */
  1002. public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
  1003. {
  1004. $tables = array(
  1005. 'deliverydet'
  1006. );
  1007. return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
  1008. }
  1009. }
  1010. /**
  1011. * Management class of delivery note lines
  1012. */
  1013. class DeliveryLine extends CommonObjectLine
  1014. {
  1015. /**
  1016. * @var DoliDB Database handler.
  1017. */
  1018. public $db;
  1019. /**
  1020. * @var string ID to identify managed object
  1021. */
  1022. public $element = 'deliverydet';
  1023. /**
  1024. * @var string Name of table without prefix where object is stored
  1025. */
  1026. public $table_element = 'deliverydet';
  1027. /**
  1028. * @var string delivery note lines label
  1029. */
  1030. public $label;
  1031. /**
  1032. * @var string product description
  1033. */
  1034. public $description;
  1035. /**
  1036. * @deprecated
  1037. * @see $product_ref
  1038. */
  1039. public $ref;
  1040. /**
  1041. * @deprecated
  1042. * @see product_label;
  1043. */
  1044. public $libelle;
  1045. // From llx_expeditiondet
  1046. public $qty;
  1047. public $qty_asked;
  1048. public $qty_shipped;
  1049. public $fk_product;
  1050. public $product_desc;
  1051. public $product_type;
  1052. public $product_ref;
  1053. public $product_label;
  1054. public $price;
  1055. public $fk_origin_line;
  1056. public $origin_id;
  1057. /**
  1058. * @var int origin line ID
  1059. */
  1060. public $origin_line_id;
  1061. /**
  1062. * @var int origin line ID
  1063. * @deprecated
  1064. * @see $origin_line_id
  1065. */
  1066. public $commande_ligne_id;
  1067. /**
  1068. * Constructor
  1069. *
  1070. * @param DoliDB $db Database handler
  1071. */
  1072. public function __construct($db)
  1073. {
  1074. $this->db = $db;
  1075. }
  1076. }