dolibarr  18.0.6
mo.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2020 Lenin Rivas <lenin@leninrivas.com>
4  * Copyright (C) 2023 Frédéric France <frederic.france@free.fr>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
26 // Put here all includes required by your class file
27 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
28 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
29 
33 class Mo extends CommonObject
34 {
38  public $element = 'mo';
39 
43  public $table_element = 'mrp_mo';
44 
48  public $ismultientitymanaged = 1;
49 
53  public $isextrafieldmanaged = 1;
54 
58  public $picto = 'mrp';
59 
60 
61  const STATUS_DRAFT = 0;
62  const STATUS_VALIDATED = 1; // To produce
63  const STATUS_INPROGRESS = 2;
64  const STATUS_PRODUCED = 3;
65  const STATUS_CANCELED = 9;
66 
67 
97  public $fields = array(
98  'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-2, 'position'=>1, 'notnull'=>1, 'index'=>1, 'comment'=>"Id",),
99  'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'position'=>5, 'notnull'=>1, 'default'=>'1', 'index'=>1),
100  'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>4, 'position'=>10, 'notnull'=>1, 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'comment'=>"Reference of object", 'showoncombobox'=>'1', 'noteditable'=>1),
101  'fk_bom' => array('type'=>'integer:Bom:bom/class/bom.class.php:0:(t.status:=:1)', 'filter'=>'active=1', 'label'=>'BOM', 'enabled'=>'$conf->bom->enabled', 'visible'=>1, 'position'=>33, 'notnull'=>-1, 'index'=>1, 'comment'=>"Original BOM", 'css'=>'minwidth100 maxwidth500', 'csslist'=>'tdoverflowmax150', 'picto'=>'bom'),
102  'mrptype' => array('type'=>'integer', 'label'=>'Type', 'enabled'=>1, 'visible'=>1, 'position'=>34, 'notnull'=>1, 'default'=>'0', 'arrayofkeyval'=>array(0=>'Manufacturing', 1=>'Disassemble'), 'css'=>'minwidth150', 'csslist'=>'minwidth150 center'),
103  'fk_product' => array('type'=>'integer:Product:product/class/product.class.php:0', 'label'=>'Product', 'enabled'=>'isModEnabled("product")', 'visible'=>1, 'position'=>35, 'notnull'=>1, 'index'=>1, 'comment'=>"Product to produce", 'css'=>'maxwidth300', 'csslist'=>'tdoverflowmax100', 'picto'=>'product'),
104  'qty' => array('type'=>'real', 'label'=>'QtyToProduce', 'enabled'=>1, 'visible'=>1, 'position'=>40, 'notnull'=>1, 'comment'=>"Qty to produce", 'css'=>'width75', 'default'=>1, 'isameasure'=>1),
105  'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>42, 'notnull'=>-1, 'searchall'=>1, 'showoncombobox'=>'2', 'css'=>'maxwidth300', 'csslist'=>'tdoverflowmax200', 'alwayseditable'=>1),
106  'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1', 'label'=>'ThirdParty', 'picto'=>'company', 'enabled'=>'isModEnabled("societe")', 'visible'=>-1, 'position'=>50, 'notnull'=>-1, 'index'=>1, 'css'=>'maxwidth400', 'csslist'=>'tdoverflowmax150'),
107  'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)', 'label'=>'Project', 'picto'=>'project', 'enabled'=>'$conf->project->enabled', 'visible'=>-1, 'position'=>51, 'notnull'=>-1, 'index'=>1, 'css'=>'minwidth200 maxwidth400', 'csslist'=>'tdoverflowmax100'),
108  'fk_warehouse' => array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php:0', 'label'=>'WarehouseForProduction', 'picto'=>'stock', 'enabled'=>'isModEnabled("stock")', 'visible'=>1, 'position'=>52, 'css'=>'maxwidth400', 'csslist'=>'tdoverflowmax200'),
109  'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>61, 'notnull'=>-1,),
110  'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>62, 'notnull'=>-1,),
111  'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'position'=>500, 'notnull'=>1,),
112  'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'position'=>501, 'notnull'=>1,),
113  'date_valid' => array('type'=>'datetime', 'label'=>'DateValidation', 'enabled'=>1, 'visible'=>-2, 'position'=>502,),
114  'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-2, 'position'=>510, 'notnull'=>1, 'foreignkey'=>'user.rowid', 'csslist'=>'tdoverflowmax100'),
115  'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'position'=>511, 'notnull'=>-1, 'csslist'=>'tdoverflowmax100'),
116  'date_start_planned' => array('type'=>'datetime', 'label'=>'DateStartPlannedMo', 'enabled'=>1, 'visible'=>1, 'position'=>55, 'notnull'=>-1, 'index'=>1, 'help'=>'KeepEmptyForAsap', 'alwayseditable'=>1),
117  'date_end_planned' => array('type'=>'datetime', 'label'=>'DateEndPlannedMo', 'enabled'=>1, 'visible'=>1, 'position'=>56, 'notnull'=>-1, 'index'=>1, 'alwayseditable'=>1),
118  'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>1000, 'notnull'=>-1,),
119  'model_pdf' =>array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>1, 'visible'=>0, 'position'=>1010),
120  'status' => array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>2, 'position'=>1000, 'default'=>0, 'notnull'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Draft', '1'=>'Validated', '2'=>'InProgress', '3'=>'StatusMOProduced', '9'=>'Canceled')),
121  'fk_parent_line' => array('type'=>'integer:MoLine:mrp/class/mo.class.php', 'label'=>'ParentMo', 'enabled'=>1, 'visible'=>0, 'position'=>1020, 'default'=>0, 'notnull'=>0, 'index'=>1,'showoncombobox'=>0),
122  );
123  public $rowid;
124  public $entity;
125  public $ref;
126 
130  public $mrptype;
131  public $label;
132  public $qty;
133  public $fk_warehouse;
134  public $fk_soc;
135  public $socid;
136 
140  public $note_public;
141 
145  public $note_private;
146 
150  public $date_creation;
151 
155  public $date_valid;
156 
160  public $tms;
161 
162  public $fk_user_creat;
163  public $fk_user_modif;
164  public $import_key;
165  public $status;
166 
170  public $fk_product;
171 
175  public $product;
176 
180  public $date_start_planned;
181 
185  public $date_end_planned;
186 
187 
191  public $fk_bom;
192 
196  public $bom;
197 
201  public $fk_project;
202 
203  // If this object has a subtable with lines
204 
208  public $table_element_line = 'mrp_production';
209 
213  public $fk_element = 'fk_mo';
214 
218  public $class_element_line = 'MoLine';
219 
223  protected $childtables = array();
224 
228  protected $childtablesoncascade = array('mrp_production');
229 
233  public $lines = array();
234 
238  public $line = array();
239 
243  public $fk_parent_line;
244 
248  public $tpl = array();
249 
255  public function __construct(DoliDB $db)
256  {
257  global $conf, $langs;
258 
259  $this->db = $db;
260 
261  if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) {
262  $this->fields['rowid']['visible'] = 0;
263  }
264  if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
265  $this->fields['entity']['enabled'] = 0;
266  }
267 
268  // Unset fields that are disabled
269  foreach ($this->fields as $key => $val) {
270  if (isset($val['enabled']) && empty($val['enabled'])) {
271  unset($this->fields[$key]);
272  }
273  }
274 
275  // Translate some data of arrayofkeyval
276  foreach ($this->fields as $key => $val) {
277  if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
278  foreach ($val['arrayofkeyval'] as $key2 => $val2) {
279  $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
280  }
281  }
282  }
283  }
284 
292  public function create(User $user, $notrigger = false)
293  {
294  $error = 0;
295  $idcreated = 0;
296 
297  // If kits feature is enabled and we don't allow kits into BOM and MO, we check that the product is not a kit/virtual product
298  if (getDolGlobalString('PRODUIT_SOUSPRODUITS') && !getDolGlobalString('ALLOW_USE_KITS_INTO_BOM_AND_MO') && $this->fk_product > 0) {
299  include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
300  $tmpproduct = new Product($this->db);
301  $tmpproduct->fetch($this->fk_product);
302  if ($tmpproduct->hasFatherOrChild(1) > 0) {
303  $this->error = 'ErrorAVirtualProductCantBeUsedIntoABomOrMo';
304  $this->errors[] = $this->error;
305  return -1;
306  }
307  }
308 
309  $this->db->begin();
310 
311  if ($this->fk_bom > 0) {
312  // If there is a nown BOM, we force the type of MO to the type of BOM
313  include_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php';
314  $tmpbom = new BOM($this->db);
315  $tmpbom->fetch($this->fk_bom);
316 
317  $this->mrptype = $tmpbom->bomtype;
318  }
319 
320  if (!$error) {
321  $idcreated = $this->createCommon($user, $notrigger);
322  if ($idcreated <= 0) {
323  $error++;
324  }
325  }
326 
327  if (!$error) {
328  $result = $this->createProduction($user, $notrigger); // Insert lines from BOM
329  if ($result <= 0) {
330  $error++;
331  }
332  }
333 
334  if (!$error) {
335  $this->db->commit();
336  } else {
337  $this->db->rollback();
338  }
339 
340  return $idcreated;
341  }
342 
350  public function createFromClone(User $user, $fromid)
351  {
352  global $langs, $extrafields;
353  $error = 0;
354 
355  dol_syslog(__METHOD__, LOG_DEBUG);
356 
357  $object = new self($this->db);
358 
359  $this->db->begin();
360 
361  // Load source object
362  $result = $object->fetchCommon($fromid);
363  if ($result > 0 && !empty($object->table_element_line)) {
364  $object->fetchLines();
365  }
366 
367  // get lines so they will be clone
368  //foreach($this->lines as $line)
369  // $line->fetch_optionals();
370 
371  // Reset some properties
372  unset($object->id);
373  unset($object->fk_user_creat);
374  unset($object->import_key);
375 
376  // We make $object->lines empty to sort it without produced and consumed lines
377  $TLines = $object->lines;
378  $object->lines = array();
379 
380  // Remove produced and consumed lines
381  foreach ($TLines as $key => $line) {
382  if (in_array($line->role, array('consumed', 'produced'))) {
383  unset($object->lines[$key]);
384  } else {
385  $object->lines[] = $line;
386  }
387  }
388 
389 
390  // Clear fields
391  $object->ref = empty($this->fields['ref']['default']) ? "copy_of_".$object->ref : $this->fields['ref']['default'];
392  $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
393  $object->status = self::STATUS_DRAFT;
394  // ...
395  // Clear extrafields that are unique
396  if (is_array($object->array_options) && count($object->array_options) > 0) {
397  $extrafields->fetch_name_optionals_label($this->table_element);
398  foreach ($object->array_options as $key => $option) {
399  $shortkey = preg_replace('/options_/', '', $key);
400  if (!empty($extrafields->attributes[$this->element]['unique'][$shortkey])) {
401  //var_dump($key);
402  //var_dump($clonedObj->array_options[$key]); exit;
403  unset($object->array_options[$key]);
404  }
405  }
406  }
407 
408  // Create clone
409  $object->context['createfromclone'] = 'createfromclone';
410  $result = $object->createCommon($user);
411  if ($result < 0) {
412  $error++;
413  $this->error = $object->error;
414  $this->errors = $object->errors;
415  }
416 
417  if (!$error) {
418  // copy internal contacts
419  if ($this->copy_linked_contact($object, 'internal') < 0) {
420  $error++;
421  }
422  }
423 
424  if (!$error) {
425  // copy external contacts if same company
426  if (property_exists($this, 'socid') && $this->socid == $object->socid) {
427  if ($this->copy_linked_contact($object, 'external') < 0) {
428  $error++;
429  }
430  }
431  }
432 
433  unset($object->context['createfromclone']);
434 
435  // End
436  if (!$error) {
437  $this->db->commit();
438  return $object;
439  } else {
440  $this->db->rollback();
441  return -1;
442  }
443  }
444 
452  public function fetch($id, $ref = null)
453  {
454  $result = $this->fetchCommon($id, $ref);
455  if ($result > 0 && !empty($this->table_element_line)) {
456  $this->fetchLines();
457  }
458 
459  $this->socid = $this->fk_soc;
460 
461  return $result;
462  }
463 
469  public function fetchLines()
470  {
471  $this->lines = array();
472 
473  $result = $this->fetchLinesCommon();
474  return $result;
475  }
476 
477 
489  public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
490  {
491  global $conf;
492 
493  dol_syslog(__METHOD__, LOG_DEBUG);
494 
495  $records = array();
496 
497  $sql = 'SELECT ';
498  $sql .= $this->getFieldList();
499  $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
500  if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
501  $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
502  } else {
503  $sql .= ' WHERE 1 = 1';
504  }
505  // Manage filter
506  $sqlwhere = array();
507  if (count($filter) > 0) {
508  foreach ($filter as $key => $value) {
509  if ($key == 't.rowid') {
510  $sqlwhere[] = $key." = ".((int) $value);
511  } elseif (strpos($key, 'date') !== false) {
512  $sqlwhere[] = $key." = '".$this->db->idate($value)."'";
513  } elseif ($key == 'customsql') {
514  $sqlwhere[] = $value;
515  } else {
516  $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'";
517  }
518  }
519  }
520  if (count($sqlwhere) > 0) {
521  $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')';
522  }
523 
524  if (!empty($sortfield)) {
525  $sql .= $this->db->order($sortfield, $sortorder);
526  }
527  if (!empty($limit)) {
528  $sql .= $this->db->plimit($limit, $offset);
529  }
530 
531  $resql = $this->db->query($sql);
532  if ($resql) {
533  $num = $this->db->num_rows($resql);
534  $i = 0;
535  while ($i < min($limit, $num)) {
536  $obj = $this->db->fetch_object($resql);
537 
538  $record = new self($this->db);
539  $record->setVarsFromFetchObj($obj);
540 
541  $records[$record->id] = $record;
542 
543  $i++;
544  }
545  $this->db->free($resql);
546 
547  return $records;
548  } else {
549  $this->errors[] = 'Error '.$this->db->lasterror();
550  dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
551 
552  return -1;
553  }
554  }
555 
563  public function fetchLinesLinked($role, $lineid = 0)
564  {
565  $resarray = array();
566  $mostatic = new MoLine($this->db);
567 
568  $sql = 'SELECT ';
569  $sql .= $mostatic->getFieldList();
570  $sql .= ' FROM '.MAIN_DB_PREFIX.$mostatic->table_element.' as t';
571  $sql .= " WHERE t.role = '".$this->db->escape($role)."'";
572  if ($lineid > 0) {
573  $sql .= ' AND t.fk_mrp_production = '.((int) $lineid);
574  } else {
575  $sql .= 'AND t.fk_mo = '.((int) $this->id);
576  }
577 
578  $resql = $this->db->query($sql);
579  if ($resql) {
580  $num = $this->db->num_rows($resql);
581 
582  $i = 0;
583  while ($i < $num) {
584  $obj = $this->db->fetch_object($resql);
585  if ($obj) {
586  $resarray[] = array(
587  'rowid'=> $obj->rowid,
588  'date'=> $this->db->jdate($obj->date_creation),
589  'qty' => $obj->qty,
590  'role' => $obj->role,
591  'fk_product' => $obj->fk_product,
592  'fk_warehouse' => $obj->fk_warehouse,
593  'batch' => $obj->batch,
594  'fk_stock_movement' => $obj->fk_stock_movement
595  );
596  }
597 
598  $i++;
599  }
600 
601  return $resarray;
602  } else {
603  $this->error = $this->db->lasterror();
604  return array();
605  }
606  }
607 
608 
614  public function countMovements()
615  {
616  $result = 0;
617 
618  $sql = 'SELECT COUNT(rowid) as nb FROM '.MAIN_DB_PREFIX.'stock_mouvement as sm';
619  $sql .= " WHERE sm.origintype = 'mo' and sm.fk_origin = ".((int) $this->id);
620 
621  $resql = $this->db->query($sql);
622  if ($resql) {
623  $num = $this->db->num_rows($resql);
624 
625  $i = 0;
626  while ($i < $num) {
627  $obj = $this->db->fetch_object($resql);
628  if ($obj) {
629  $result = $obj->nb;
630  }
631 
632  $i++;
633  }
634  } else {
635  $this->error = $this->db->lasterror();
636  }
637 
638  return $result;
639  }
640 
641 
649  public function update(User $user, $notrigger = false)
650  {
651  global $langs;
652 
653  $error = 0;
654 
655  $this->db->begin();
656 
657  $result = $this->updateCommon($user, $notrigger);
658  if ($result <= 0) {
659  $error++;
660  }
661 
662  // Update the lines (the qty) to consume or to produce
663  $result = $this->updateProduction($user, $notrigger);
664  if ($result <= 0) {
665  $error++;
666  }
667 
668  if (!$error) {
669  $this->db->commit();
670  return 1;
671  } else {
672  $this->db->rollback();
673  return -1;
674  }
675  }
676 
677 
685  public function createProduction(User $user, $notrigger = true)
686  {
687  $error = 0;
688  $role = "";
689 
690  if ($this->status != self::STATUS_DRAFT) {
691  return -1;
692  }
693 
694  $this->db->begin();
695 
696  // Insert lines in mrp_production table from BOM data
697  if (!$error) {
698  $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'mrp_production WHERE fk_mo = '.((int) $this->id);
699  $this->db->query($sql);
700 
701  $moline = new MoLine($this->db);
702 
703  // Line to produce
704  $moline->fk_mo = $this->id;
705  $moline->qty = $this->qty;
706  $moline->fk_product = $this->fk_product;
707  $moline->position = 1;
708 
709  if ($this->fk_bom > 0) { // If a BOM is defined, we know what to produce.
710  include_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php';
711  $bom = new BOM($this->db);
712  $bom->fetch($this->fk_bom);
713  if ($bom->bomtype == 1) {
714  $role = 'toproduce';
715  $moline->role = 'toconsume';
716  } else {
717  $role = 'toconsume';
718  $moline->role = 'toproduce';
719  }
720  } else {
721  if ($this->mrptype == 1) {
722  $moline->role = 'toconsume';
723  } else {
724  $moline->role = 'toproduce';
725  }
726  }
727 
728  $resultline = $moline->create($user, false); // Never use triggers here
729  if ($resultline <= 0) {
730  $error++;
731  $this->error = $moline->error;
732  $this->errors = $moline->errors;
733  dol_print_error($this->db, $moline->error, $moline->errors);
734  }
735 
736  if ($this->fk_bom > 0) { // If a BOM is defined, we know what to consume.
737  if ($bom->id > 0) {
738  // Lines to consume
739  if (!$error) {
740  foreach ($bom->lines as $line) {
741  $moline = new MoLine($this->db);
742 
743  $moline->fk_mo = $this->id;
744  $moline->origin_id = $line->id;
745  $moline->origin_type = 'bomline';
746  if ($line->qty_frozen) {
747  $moline->qty = $line->qty; // Qty to consume does not depends on quantity to produce
748  } else {
749  $moline->qty = price2num(($line->qty / ( !empty($bom->qty) ? $bom->qty : 1 ) ) * $this->qty / ( !empty($line->efficiency) ? $line->efficiency : 1 ), 'MS'); // Calculate with Qty to produce and more presition
750  }
751  if ($moline->qty <= 0) {
752  $error++;
753  $this->error = "BadValueForquantityToConsume";
754  break;
755  } else {
756  $moline->fk_product = $line->fk_product;
757  $moline->role = $role;
758  $moline->position = $line->position;
759  $moline->qty_frozen = $line->qty_frozen;
760  $moline->disable_stock_change = $line->disable_stock_change;
761  if (!empty($line->fk_default_workstation)) $moline->fk_default_workstation = $line->fk_default_workstation;
762 
763  $resultline = $moline->create($user, false); // Never use triggers here
764  if ($resultline <= 0) {
765  $error++;
766  $this->error = $moline->error;
767  $this->errors = $moline->errors;
768  dol_print_error($this->db, $moline->error, $moline->errors);
769  break;
770  }
771  }
772  }
773  }
774  }
775  }
776  }
777 
778  if (!$error) {
779  $this->db->commit();
780  return 1;
781  } else {
782  $this->db->rollback();
783  return -1;
784  }
785  }
786 
794  public function updateProduction(User $user, $notrigger = true)
795  {
796  $error = 0;
797 
798  if ($this->status != self::STATUS_DRAFT) return 1;
799 
800  $this->db->begin();
801 
802  $oldQty = $this->oldQty;
803  $newQty = $this->qty;
804  if ($newQty != $oldQty && !empty($this->oldQty)) {
805  $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "mrp_production WHERE fk_mo = " . (int) $this->id;
806  $resql = $this->db->query($sql);
807  if ($resql) {
808  while ($obj = $this->db->fetch_object($resql)) {
809  $moLine = new MoLine($this->db);
810  $res = $moLine->fetch($obj->rowid);
811  if (!$res) $error++;
812 
813  if ($moLine->role == 'toconsume' || $moLine->role == 'toproduce') {
814  if (empty($moLine->qty_frozen)) {
815  $qty = $newQty * $moLine->qty / $oldQty;
816  $moLine->qty = price2num($qty * (!empty($line->efficiency) ? $line->efficiency : 1 ), 'MS'); // Calculate with Qty to produce and efficiency
817  $res = $moLine->update($user);
818  if (!$res) $error++;
819  }
820  }
821  }
822  }
823  }
824 
825  if (!$error) {
826  $this->db->commit();
827  return 1;
828  } else {
829  $this->db->rollback();
830  return -1;
831  }
832  }
833 
834 
842  public function delete(User $user, $notrigger = false)
843  {
844  return $this->deleteCommon($user, $notrigger);
845  //return $this->deleteCommon($user, $notrigger, 1);
846  }
847 
856  public function deleteLine(User $user, $idline, $notrigger = false)
857  {
858  global $langs;
859  $langs->loadLangs(array('stocks', 'mrp'));
860 
861  if ($this->status < 0) {
862  $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
863  return -2;
864  }
865 
866  $productstatic = new Product($this->db);
867  $fk_movement = GETPOST('fk_movement', 'int');
868  $arrayoflines = $this->fetchLinesLinked('consumed', $idline);
869 
870  if (!empty($arrayoflines)) {
871  $this->db->begin();
872 
873  $stockmove = new MouvementStock($this->db);
874  $stockmove->setOrigin($this->element, $this->id);
875 
876  if (!empty($fk_movement)) {
877  $moline = new MoLine($this->db);
878  $TArrayMoLine = $moline->fetchAll('', '', 1, 0, array('customsql' => 'fk_stock_movement ='.$fk_movement));
879  $moline = array_shift($TArrayMoLine);
880 
881  $movement = new MouvementStock($this->db);
882  $movement->fetch($fk_movement);
883  $productstatic->fetch($movement->product_id);
884  $qtytoprocess = $movement->qty;
885 
886  // Reverse stock movement
887  $labelmovementCancel = $langs->trans("CancelProductionForRef", $productstatic->ref);
888  $codemovementCancel = $langs->trans("StockIncrease");
889 
890  if (($qtytoprocess >= 0)) {
891  $idstockmove = $stockmove->reception($user, $movement->product_id, $movement->warehouse_id, $qtytoprocess, 0, $labelmovementCancel, '', '', $movement->batch, dol_now(), 0, $codemovementCancel);
892  } else {
893  $idstockmove = $stockmove->livraison($user, $movement->product_id, $movement->warehouse_id, $qtytoprocess, 0, $labelmovementCancel, dol_now(), '', '', $movement->batch, 0, $codemovementCancel);
894  }
895  if ($idstockmove < 0) {
896  $this->error++;
897  $this->db->rollback();
898  setEventMessages($stockmove->error, $stockmove->errors, 'errors');
899  } else {
900  $this->db->commit();
901  }
902  return $moline->delete($user, $notrigger);
903  } else {
904  foreach ($arrayoflines as $key => $arrayofline) {
905  $lineDetails = $arrayoflines[$key];
906  $productstatic->fetch($lineDetails['fk_product']);
907  $qtytoprocess = $lineDetails['qty'];
908 
909  // Reverse stock movement
910  $labelmovementCancel = $langs->trans("CancelProductionForRef", $productstatic->ref);
911  $codemovementCancel = $langs->trans("StockIncrease");
912 
913  if ($qtytoprocess >= 0) {
914  $idstockmove = $stockmove->reception($user, $lineDetails['fk_product'], $lineDetails['fk_warehouse'], $qtytoprocess, 0, $labelmovementCancel, '', '', $lineDetails['batch'], dol_now(), 0, $codemovementCancel);
915  } else {
916  $idstockmove = $stockmove->livraison($user, $lineDetails['fk_product'], $lineDetails['fk_warehouse'], $qtytoprocess, 0, $labelmovementCancel, dol_now(), '', '', $lineDetails['batch'], 0, $codemovementCancel);
917  }
918  if ($idstockmove < 0) {
919  $this->error++;
920  $this->db->rollback();
921  setEventMessages($stockmove->error, $stockmove->errors, 'errors');
922  } else {
923  $this->db->commit();
924  }
925  }
926  return $this->deleteLineCommon($user, $idline, $notrigger);
927  }
928  } else {
929  return $this->deleteLineCommon($user, $idline, $notrigger);
930  }
931  }
932 
933 
941  public function getNextNumRef($prod)
942  {
943  global $langs, $conf;
944  $langs->load("mrp");
945 
946  if (!empty($conf->global->MRP_MO_ADDON)) {
947  $mybool = false;
948 
949  $file = $conf->global->MRP_MO_ADDON.".php";
950  $classname = $conf->global->MRP_MO_ADDON;
951 
952  // Include file with class
953  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
954  foreach ($dirmodels as $reldir) {
955  $dir = dol_buildpath($reldir."core/modules/mrp/");
956 
957  // Load file with numbering class (if found)
958  $mybool |= @include_once $dir.$file;
959  }
960 
961  if ($mybool === false) {
962  dol_print_error('', "Failed to include file ".$file);
963  return '';
964  }
965 
966  $obj = new $classname();
967  $numref = $obj->getNextValue($prod, $this);
968 
969  if ($numref != "") {
970  return $numref;
971  } else {
972  $this->error = $obj->error;
973  //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
974  return "";
975  }
976  } else {
977  print $langs->trans("Error")." ".$langs->trans("Error_MRP_MO_ADDON_NotDefined");
978  return "";
979  }
980  }
981 
989  public function validate($user, $notrigger = 0)
990  {
991  global $conf, $langs;
992 
993  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
994 
995  $error = 0;
996 
997  // Protection
998  if ($this->status == self::STATUS_VALIDATED) {
999  dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING);
1000  return 0;
1001  }
1002 
1003  /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mrp->create))
1004  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mrp->mrp_advance->validate))))
1005  {
1006  $this->error='NotEnoughPermissions';
1007  dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
1008  return -1;
1009  }*/
1010 
1011  $now = dol_now();
1012 
1013  $this->db->begin();
1014 
1015  // Define new ref
1016  if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
1017  $this->fetch_product();
1018  $num = $this->getNextNumRef($this->product);
1019  } else {
1020  $num = $this->ref;
1021  }
1022  $this->newref = $num;
1023 
1024  // Validate
1025  $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
1026  $sql .= " SET ref = '".$this->db->escape($num)."',";
1027  $sql .= " status = ".self::STATUS_VALIDATED.",";
1028  $sql .= " date_valid='".$this->db->idate($now)."',";
1029  $sql .= " fk_user_valid = ".$user->id;
1030  $sql .= " WHERE rowid = ".((int) $this->id);
1031 
1032  dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
1033  $resql = $this->db->query($sql);
1034  if (!$resql) {
1035  dol_print_error($this->db);
1036  $this->error = $this->db->lasterror();
1037  $error++;
1038  }
1039 
1040  if (!$error && !$notrigger) {
1041  // Call trigger
1042  $result = $this->call_trigger('MRP_MO_VALIDATE', $user);
1043  if ($result < 0) {
1044  $error++;
1045  }
1046  // End call triggers
1047  }
1048 
1049  if (!$error) {
1050  $this->oldref = $this->ref;
1051 
1052  // Rename directory if dir was a temporary ref
1053  if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
1054  // Now we rename also files into index
1055  $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'mrp/".$this->db->escape($this->newref)."'";
1056  $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'mrp/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
1057  $resql = $this->db->query($sql);
1058  if (!$resql) {
1059  $error++; $this->error = $this->db->lasterror();
1060  }
1061  $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'mrp/".$this->db->escape($this->newref)."'";
1062  $sql .= " WHERE filepath = 'mrp/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
1063  $resql = $this->db->query($sql);
1064  if (!$resql) {
1065  $error++; $this->error = $this->db->lasterror();
1066  }
1067 
1068  // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
1069  $oldref = dol_sanitizeFileName($this->ref);
1070  $newref = dol_sanitizeFileName($num);
1071  $dirsource = $conf->mrp->dir_output.'/'.$oldref;
1072  $dirdest = $conf->mrp->dir_output.'/'.$newref;
1073  if (!$error && file_exists($dirsource)) {
1074  dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
1075 
1076  if (@rename($dirsource, $dirdest)) {
1077  dol_syslog("Rename ok");
1078  // Rename docs starting with $oldref with $newref
1079  $listoffiles = dol_dir_list($conf->mrp->dir_output.'/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
1080  foreach ($listoffiles as $fileentry) {
1081  $dirsource = $fileentry['name'];
1082  $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
1083  $dirsource = $fileentry['path'].'/'.$dirsource;
1084  $dirdest = $fileentry['path'].'/'.$dirdest;
1085  @rename($dirsource, $dirdest);
1086  }
1087  }
1088  }
1089  }
1090  }
1091 
1092  // Set new ref and current status
1093  if (!$error) {
1094  $this->ref = $num;
1095  $this->status = self::STATUS_VALIDATED;
1096  }
1097 
1098  if (!$error) {
1099  $this->db->commit();
1100  return 1;
1101  } else {
1102  $this->db->rollback();
1103  return -1;
1104  }
1105  }
1106 
1114  public function setDraft($user, $notrigger = 0)
1115  {
1116  // Protection
1117  if ($this->status <= self::STATUS_DRAFT) {
1118  return 0;
1119  }
1120 
1121  /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mymodule->write))
1122  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mymodule->mymodule_advance->validate))))
1123  {
1124  $this->error='Permission denied';
1125  return -1;
1126  }*/
1127 
1128  return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'MRP_MO_UNVALIDATE');
1129  }
1130 
1138  public function cancel($user, $notrigger = 0)
1139  {
1140  // Protection
1141  if ($this->status != self::STATUS_VALIDATED && $this->status != self::STATUS_INPROGRESS) {
1142  return 0;
1143  }
1144 
1145  /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mymodule->write))
1146  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mymodule->mymodule_advance->validate))))
1147  {
1148  $this->error='Permission denied';
1149  return -1;
1150  }*/
1151 
1152  return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'MRP_MO_CANCEL');
1153  }
1154 
1162  public function reopen($user, $notrigger = 0)
1163  {
1164  // Protection
1165  if ($this->status != self::STATUS_PRODUCED && $this->status != self::STATUS_CANCELED) {
1166  return 0;
1167  }
1168 
1169  /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mymodule->write))
1170  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mymodule->mymodule_advance->validate))))
1171  {
1172  $this->error='Permission denied';
1173  return -1;
1174  }*/
1175 
1176  return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'MRP_MO_REOPEN');
1177  }
1178 
1186  public function getTooltipContentArray($params)
1187  {
1188  global $conf, $langs;
1189 
1190  $langs->loadLangs(['mrp', 'products']);
1191  $nofetch = isset($params['nofetch']) ? true : false;
1192 
1193  $datas = [];
1194 
1195  $datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("ManufacturingOrder").'</u>';
1196  if (isset($this->status)) {
1197  $datas['picto'] .= ' '.$this->getLibStatut(5);
1198  }
1199  $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1200  if (isset($this->label)) {
1201  $datas['label'] = '<br><b>'.$langs->trans('Label').':</b> '.$this->label;
1202  }
1203  if (isset($this->mrptype)) {
1204  $datas['type'] = '<br><b>'.$langs->trans('Type').':</b> '.$this->fields['mrptype']['arrayofkeyval'][$this->mrptype];
1205  }
1206  if (isset($this->qty)) {
1207  $datas['qty'] = '<br><b>'.$langs->trans('QtyToProduce').':</b> '.$this->qty;
1208  }
1209  if (!$nofetch && isset($this->fk_product)) {
1210  require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
1211  $product = new Product($this->db);
1212  $product->fetch($this->fk_product);
1213  $datas['product'] = '<br><b>'.$langs->trans('Product').':</b> '.$product->getNomUrl(1, '', 0, -1, 1);
1214  }
1215  if (!$nofetch && isset($this->fk_warehouse)) {
1216  require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
1217  $warehouse = new Entrepot($this->db);
1218  $warehouse->fetch($this->fk_warehouse);
1219  $datas['warehouse'] = '<br><b>'.$langs->trans('WarehouseForProduction').':</b> '.$warehouse->getNomUrl(1, '', 0, 1);
1220  }
1221 
1222  return $datas;
1223  }
1224 
1235  public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1236  {
1237  global $conf, $langs, $hookmanager;
1238 
1239  if (!empty($conf->dol_no_mouse_hover)) {
1240  $notooltip = 1; // Force disable tooltips
1241  }
1242 
1243  $result = '';
1244  $params = [
1245  'id' => $this->id,
1246  'objecttype' => $this->element,
1247  'option' => $option,
1248  'nofetch' => 1,
1249  ];
1250  $classfortooltip = 'classfortooltip';
1251  $dataparams = '';
1252  if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1253  $classfortooltip = 'classforajaxtooltip';
1254  $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1255  $label = '';
1256  } else {
1257  $label = implode($this->getTooltipContentArray($params));
1258  }
1259 
1260  $url = DOL_URL_ROOT.'/mrp/mo_card.php?id='.$this->id;
1261  if ($option == 'production') {
1262  $url = DOL_URL_ROOT.'/mrp/mo_production.php?id='.$this->id;
1263  }
1264 
1265  if ($option != 'nolink') {
1266  // Add param to save lastsearch_values or not
1267  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1268  if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1269  $add_save_lastsearch_values = 1;
1270  }
1271  if ($add_save_lastsearch_values) {
1272  $url .= '&save_lastsearch_values=1';
1273  }
1274  }
1275 
1276  $linkclose = '';
1277  if (empty($notooltip)) {
1278  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
1279  $label = $langs->trans("ShowMo");
1280  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1281  }
1282  $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
1283  $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
1284  } else {
1285  $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1286  }
1287 
1288  $linkstart = '<a href="'.$url.'"';
1289  $linkstart .= $linkclose.'>';
1290  $linkend = '</a>';
1291 
1292  $result .= $linkstart;
1293  if ($withpicto) {
1294  $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1);
1295  }
1296  if ($withpicto != 2) {
1297  $result .= $this->ref;
1298  }
1299  $result .= $linkend;
1300  //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
1301 
1302  global $action, $hookmanager;
1303  $hookmanager->initHooks(array('modao'));
1304  $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
1305  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1306  if ($reshook > 0) {
1307  $result = $hookmanager->resPrint;
1308  } else {
1309  $result .= $hookmanager->resPrint;
1310  }
1311 
1312  return $result;
1313  }
1314 
1321  public function getLibStatut($mode = 0)
1322  {
1323  return $this->LibStatut($this->status, $mode);
1324  }
1325 
1326  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1334  public function LibStatut($status, $mode = 0)
1335  {
1336  // phpcs:enable
1337  if (empty($this->labelStatus)) {
1338  global $langs;
1339  //$langs->load("mrp");
1340  $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1341  $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('ValidatedToProduce');
1342  $this->labelStatus[self::STATUS_INPROGRESS] = $langs->transnoentitiesnoconv('InProgress');
1343  $this->labelStatus[self::STATUS_PRODUCED] = $langs->transnoentitiesnoconv('StatusMOProduced');
1344  $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
1345 
1346  $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1347  $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
1348  $this->labelStatusShort[self::STATUS_INPROGRESS] = $langs->transnoentitiesnoconv('InProgress');
1349  $this->labelStatusShort[self::STATUS_PRODUCED] = $langs->transnoentitiesnoconv('StatusMOProduced');
1350  $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
1351  }
1352 
1353  $statusType = 'status'.$status;
1354  if ($status == self::STATUS_VALIDATED) {
1355  $statusType = 'status1';
1356  }
1357  if ($status == self::STATUS_INPROGRESS) {
1358  $statusType = 'status4';
1359  }
1360  if ($status == self::STATUS_PRODUCED) {
1361  $statusType = 'status6';
1362  }
1363  if ($status == self::STATUS_CANCELED) {
1364  $statusType = 'status9';
1365  }
1366 
1367  return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
1368  }
1369 
1376  public function info($id)
1377  {
1378  $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
1379  $sql .= ' fk_user_creat, fk_user_modif';
1380  $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
1381  $sql .= ' WHERE t.rowid = '.((int) $id);
1382  $result = $this->db->query($sql);
1383  if ($result) {
1384  if ($this->db->num_rows($result)) {
1385  $obj = $this->db->fetch_object($result);
1386  $this->id = $obj->rowid;
1387 
1388  $this->user_creation_id = $obj->fk_user_creat;
1389  $this->user_modification_id = $obj->fk_user_modif;
1390  $this->date_creation = $this->db->jdate($obj->datec);
1391  $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1392  }
1393 
1394  $this->db->free($result);
1395  } else {
1396  dol_print_error($this->db);
1397  }
1398  }
1399 
1406  public function initAsSpecimen()
1407  {
1408  $this->initAsSpecimenCommon();
1409 
1410  $this->lines = array();
1411  }
1412 
1419  public function getLinesArray($rolefilter = '')
1420  {
1421  $this->lines = array();
1422 
1423  $objectline = new MoLine($this->db);
1424 
1425  $TFilters = array('customsql'=>'fk_mo = '.((int) $this->id));
1426  if (!empty($rolefilter)) $TFilters['role'] = $rolefilter;
1427  $result = $objectline->fetchAll('ASC', 'position', 0, 0, $TFilters);
1428 
1429  if (is_numeric($result)) {
1430  $this->error = $objectline->error;
1431  $this->errors = $objectline->errors;
1432  return $result;
1433  } else {
1434  $this->lines = $result;
1435  return $this->lines;
1436  }
1437  }
1438 
1450  public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1451  {
1452  global $conf, $langs;
1453 
1454  $langs->load("mrp");
1455 
1456  if (!dol_strlen($modele)) {
1457  //$modele = 'standard';
1458  $modele = ''; // Remove this once a pdf_standard.php exists.
1459 
1460  if ($this->model_pdf) {
1461  $modele = $this->model_pdf;
1462  } elseif (!empty($conf->global->MO_ADDON_PDF)) {
1463  $modele = $conf->global->MO_ADDON_PDF;
1464  }
1465  }
1466 
1467  $modelpath = "core/modules/mrp/doc/";
1468 
1469  if (empty($modele)) {
1470  return 1; // Remove this once a pdf_standard.php exists.
1471  }
1472 
1473  return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1474  }
1475 
1483  public function doScheduledJob()
1484  {
1485  global $conf, $langs;
1486 
1487  //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1488 
1489  $error = 0;
1490  $this->output = '';
1491  $this->error = '';
1492 
1493  dol_syslog(__METHOD__, LOG_DEBUG);
1494 
1495  $now = dol_now();
1496 
1497  $this->db->begin();
1498 
1499  // ...
1500 
1501  $this->db->commit();
1502 
1503  return $error;
1504  }
1505 
1516  public function printOriginLinesList($restrictlist = '', $selectedLines = array())
1517  {
1518  global $langs, $hookmanager, $conf, $form;
1519 
1520  $langs->load('stocks');
1521  $text_stock_options = $langs->trans("RealStockDesc").'<br>';
1522  $text_stock_options .= $langs->trans("RealStockWillAutomaticallyWhen").'<br>';
1523  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE) ? '- '.$langs->trans("DeStockOnShipment").'<br>' : '');
1524  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) ? '- '.$langs->trans("DeStockOnValidateOrder").'<br>' : '');
1525  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_BILL) ? '- '.$langs->trans("DeStockOnBill").'<br>' : '');
1526  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL) ? '- '.$langs->trans("ReStockOnBill").'<br>' : '');
1527  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER) ? '- '.$langs->trans("ReStockOnValidateOrder").'<br>' : '');
1528  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) ? '- '.$langs->trans("ReStockOnDispatchOrder").'<br>' : '');
1529  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE) ? '- '.$langs->trans("StockOnReception").'<br>' : '');
1530 
1531  print '<tr class="liste_titre">';
1532  // Product or sub-bom
1533  print '<td class="linecoldescription">'.$langs->trans('Ref');
1534  if (!empty($conf->global->BOM_SUB_BOM)) {
1535  print ' &nbsp; <a id="show_all" href="#">'.img_picto('', 'folder-open', 'class="paddingright"').$langs->trans("ExpandAll").'</a>&nbsp;&nbsp;';
1536  print '<a id="hide_all" href="#">'.img_picto('', 'folder', 'class="paddingright"').$langs->trans("UndoExpandAll").'</a>&nbsp;';
1537  }
1538  print '</td>';
1539  // Qty
1540  print '<td class="right">'.$langs->trans('Qty');
1541  if ($this->bom->bomtype == 0) {
1542  print ' <span class="opacitymedium">('.$langs->trans("ForAQuantityOf", $this->bom->qty).')</span>';
1543  } else {
1544  print ' <span class="opacitymedium">('.$langs->trans("ForAQuantityToConsumeOf", $this->bom->qty).')</span>';
1545  }
1546  print '</td>';
1547  print '<td class="center">'.$form->textwithpicto($langs->trans("PhysicalStock"), $text_stock_options, 1).'</td>';
1548  print '<td class="center">'.$form->textwithpicto($langs->trans("VirtualStock"), $langs->trans("VirtualStockDesc")).'</td>';
1549  print '<td class="center">'.$langs->trans('QtyFrozen').'</td>';
1550  print '<td class="center">'.$langs->trans('DisableStockChange').'</td>';
1551  print '<td class="center">'.$langs->trans('MoChildGenerate').'</td>';
1552  //print '<td class="center">'.$form->showCheckAddButtons('checkforselect', 1).'</td>';
1553  //print '<td class="center"></td>';
1554  print '</tr>';
1555  $i = 0;
1556 
1557  if (!empty($this->lines)) {
1558  foreach ($this->lines as $line) {
1559  $reshook = 0;
1560  if (is_object($hookmanager)) {
1561  $parameters = array('line'=>$line, 'i'=>$i, 'restrictlist'=>$restrictlist, 'selectedLines'=> $selectedLines);
1562  if (!empty($line->fk_parent_line)) { $parameters['fk_parent_line'] = $line->fk_parent_line; }
1563  $reshook = $hookmanager->executeHooks('printOriginObjectLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1564  }
1565  if (empty($reshook)) {
1566  $this->printOriginLine($line, '', $restrictlist, '/core/tpl', $selectedLines);
1567  }
1568 
1569  $i++;
1570  }
1571  }
1572  }
1573 
1574 
1588  public function printOriginLine($line, $var, $restrictlist = '', $defaulttpldir = '/core/tpl', $selectedLines = array())
1589  {
1590  global $langs, $conf;
1591 
1592  $this->tpl['id'] = $line->id;
1593 
1594  $this->tpl['label'] = '';
1595  if (!empty($line->fk_product)) {
1596  $productstatic = new Product($this->db);
1597  $productstatic->fetch($line->fk_product);
1598  $productstatic->load_virtual_stock();
1599  $this->tpl['label'] .= $productstatic->getNomUrl(1);
1600  //$this->tpl['label'].= ' - '.$productstatic->label;
1601  } else {
1602  // If origin MRP line is not a product, but another MRP
1603  // TODO
1604  }
1605 
1606  $this->tpl['qty_bom'] = 1;
1607  if (is_object($this->bom) && $this->bom->qty > 1) {
1608  $this->tpl['qty_bom'] = $this->bom->qty;
1609  }
1610 
1611  $this->tpl['stock'] = $productstatic->stock_reel;
1612  $this->tpl['seuil_stock_alerte'] = $productstatic->seuil_stock_alerte;
1613  $this->tpl['virtual_stock'] = $productstatic->stock_theorique;
1614  $this->tpl['qty'] = $line->qty;
1615  $this->tpl['qty_frozen'] = $line->qty_frozen;
1616  $this->tpl['disable_stock_change'] = $line->disable_stock_change;
1617  $this->tpl['efficiency'] = $line->efficiency;
1618 
1619  $tpl = DOL_DOCUMENT_ROOT.'/mrp/tpl/originproductline.tpl.php';
1620  $res = include $tpl;
1621  }
1622 
1631  public static function replaceThirdparty($db, $origin_id, $dest_id)
1632  {
1633  $tables = array('mrp_mo');
1634 
1635  return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
1636  }
1637 
1638 
1644  public function getMoChilds()
1645  {
1646 
1647  $TMoChilds = array();
1648  $error = 0;
1649 
1650  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."mrp_mo as mo_child";
1651  $sql.= " WHERE fk_parent_line IN ";
1652  $sql.= " (SELECT rowid FROM ".MAIN_DB_PREFIX."mrp_production as line_parent";
1653  $sql.= " WHERE fk_mo=".((int) $this->id).")";
1654 
1655  $resql = $this->db->query($sql);
1656 
1657  if ($resql) {
1658  if ($this->db->num_rows($resql) > 0) {
1659  while ($obj = $this->db->fetch_object($resql)) {
1660  $MoChild = new Mo($this->db);
1661  $res = $MoChild->fetch($obj->rowid);
1662  if ($res > 0) $TMoChilds[$MoChild->id] = $MoChild;
1663  else $error++;
1664  }
1665  }
1666  } else {
1667  $error++;
1668  }
1669 
1670  if ($error) {
1671  return -1;
1672  } else {
1673  return $TMoChilds;
1674  }
1675  }
1676 
1682  public function getMoParent()
1683  {
1684  $MoParent = new Mo($this->db);
1685  $error = 0;
1686 
1687  $sql = "SELECT lineparent.fk_mo as id_moparent FROM ".MAIN_DB_PREFIX."mrp_mo as mo";
1688  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."mrp_production lineparent ON mo.fk_parent_line = lineparent.rowid";
1689  $sql.= " WHERE mo.rowid = ".((int) $this->id);
1690 
1691  $resql = $this->db->query($sql);
1692 
1693  if ($resql) {
1694  if ($this->db->num_rows($resql) > 0) {
1695  $obj = $this->db->fetch_object($resql);
1696  $res = $MoParent->fetch($obj->id_moparent);
1697  if ($res < 0) $error++;
1698  } else {
1699  return 0;
1700  }
1701  } else {
1702  $error++;
1703  }
1704 
1705  if ($error) {
1706  return -1;
1707  } else {
1708  return $MoParent;
1709  }
1710  }
1711 
1719  public function getKanbanView($option = '', $arraydata = null)
1720  {
1721  global $langs;
1722 
1723  $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1724 
1725  $return = '<div class="box-flex-item box-flex-grow-zero">';
1726  $return .= '<div class="info-box info-box-sm">';
1727  $return .= '<span class="info-box-icon bg-infobox-action">';
1728  $return .= img_picto('', $this->picto);
1729  //$return .= '<i class="fa fa-dol-action"></i>'; // Can be image
1730  $return .= '</span>';
1731  $return .= '<div class="info-box-content">';
1732  $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
1733  $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1734  if (!empty($arraydata['bom'])) {
1735  $return .= '<br><span class="info-box-label">'.$arraydata['bom']->getNomUrl(1).'</span>';
1736  }
1737  if (!empty($arraydata['product'])) {
1738  $return .= '<br><span class="info-box-label">'.$arraydata['product']->getNomUrl(1).'</span>';
1739  }
1740  if (property_exists($this, 'qty')) {
1741  $return .= '<br><span class="info-box-label">'.$langs->trans('Quantity').' : '.$this->qty.'</span>';
1742  }
1743  if (method_exists($this, 'getLibStatut')) {
1744  $return .= '<br><div class="info-box-status margintoponly">'.$this->getLibStatut(3).'</div>';
1745  }
1746  $return .= '</div>';
1747  $return .= '</div>';
1748  $return .= '</div>';
1749  return $return;
1750  }
1751 }
1752 
1757 {
1761  public $element = 'mrp_production';
1762 
1766  public $table_element = 'mrp_production';
1767 
1771  public $ismultientitymanaged = 0;
1772 
1776  public $isextrafieldmanaged = 0;
1777 
1778  public $fields = array(
1779  'rowid' =>array('type'=>'integer', 'label'=>'ID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>10),
1780  'fk_mo' =>array('type'=>'integer', 'label'=>'Mo', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>15),
1781  'origin_id' =>array('type'=>'integer', 'label'=>'Origin', 'enabled'=>1, 'visible'=>-1, 'notnull'=>0, 'position'=>17),
1782  'origin_type' =>array('type'=>'varchar(10)', 'label'=>'Origin type', 'enabled'=>1, 'visible'=>-1, 'notnull'=>0, 'position'=>18),
1783  'position' =>array('type'=>'integer', 'label'=>'Position', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>20),
1784  'fk_product' =>array('type'=>'integer', 'label'=>'Product', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>25),
1785  'fk_warehouse' =>array('type'=>'integer', 'label'=>'Warehouse', 'enabled'=>1, 'visible'=>-1, 'position'=>30),
1786  'qty' =>array('type'=>'real', 'label'=>'Qty', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>35),
1787  'qty_frozen' => array('type'=>'smallint', 'label'=>'QuantityFrozen', 'enabled'=>1, 'visible'=>1, 'default'=>0, 'position'=>105, 'css'=>'maxwidth50imp', 'help'=>'QuantityConsumedInvariable'),
1788  'disable_stock_change' => array('type'=>'smallint', 'label'=>'DisableStockChange', 'enabled'=>1, 'visible'=>1, 'default'=>0, 'position'=>108, 'css'=>'maxwidth50imp', 'help'=>'DisableStockChangeHelp'),
1789  'batch' =>array('type'=>'varchar(30)', 'label'=>'Batch', 'enabled'=>1, 'visible'=>-1, 'position'=>140),
1790  'role' =>array('type'=>'varchar(10)', 'label'=>'Role', 'enabled'=>1, 'visible'=>-1, 'position'=>145),
1791  'fk_mrp_production' =>array('type'=>'integer', 'label'=>'Fk mrp production', 'enabled'=>1, 'visible'=>-1, 'position'=>150),
1792  'fk_stock_movement' =>array('type'=>'integer', 'label'=>'StockMovement', 'enabled'=>1, 'visible'=>-1, 'position'=>155),
1793  'date_creation' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>160),
1794  'tms' =>array('type'=>'timestamp', 'label'=>'Tms', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>165),
1795  'fk_user_creat' =>array('type'=>'integer', 'label'=>'UserCreation', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>170),
1796  'fk_user_modif' =>array('type'=>'integer', 'label'=>'UserModification', 'enabled'=>1, 'visible'=>-1, 'position'=>175),
1797  'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-1, 'position'=>180),
1798  'fk_default_workstation' =>array('type'=>'integer', 'label'=>'DefaultWorkstation', 'enabled'=>1, 'visible'=>1, 'notnull'=>0, 'position'=>185)
1799  );
1800 
1801  public $rowid;
1802  public $fk_mo;
1803  public $origin_id;
1804  public $origin_type;
1805  public $position;
1806  public $fk_product;
1807  public $fk_warehouse;
1808  public $qty;
1809  public $qty_frozen;
1810  public $disable_stock_change;
1811  public $efficiency;
1812  public $batch;
1813  public $role;
1814  public $fk_mrp_production;
1815  public $fk_stock_movement;
1816  public $date_creation;
1817  public $tms;
1818  public $fk_user_creat;
1819  public $fk_user_modif;
1820  public $import_key;
1821  public $fk_parent_line;
1822 
1826  public $fk_default_workstation;
1827 
1833  public function __construct(DoliDB $db)
1834  {
1835  global $conf, $langs;
1836 
1837  $this->db = $db;
1838 
1839  if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) {
1840  $this->fields['rowid']['visible'] = 0;
1841  }
1842  if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
1843  $this->fields['entity']['enabled'] = 0;
1844  }
1845 
1846  // Unset fields that are disabled
1847  foreach ($this->fields as $key => $val) {
1848  if (isset($val['enabled']) && empty($val['enabled'])) {
1849  unset($this->fields[$key]);
1850  }
1851  }
1852 
1853  // Translate some data of arrayofkeyval
1854  if (is_object($langs)) {
1855  foreach ($this->fields as $key => $val) {
1856  if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
1857  foreach ($val['arrayofkeyval'] as $key2 => $val2) {
1858  $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
1859  }
1860  }
1861  }
1862  }
1863  }
1864 
1872  public function create(User $user, $notrigger = false)
1873  {
1874  if (empty($this->qty)) {
1875  $this->error = 'BadValueForQty';
1876  return -1;
1877  }
1878 
1879  return $this->createCommon($user, $notrigger);
1880  }
1881 
1889  public function fetch($id, $ref = null)
1890  {
1891  $result = $this->fetchCommon($id, $ref);
1892  return $result;
1893  }
1894 
1906  public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
1907  {
1908  global $conf;
1909 
1910  dol_syslog(__METHOD__, LOG_DEBUG);
1911 
1912  $records = array();
1913 
1914  $sql = 'SELECT ';
1915  $sql .= $this->getFieldList();
1916  $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
1917  if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
1918  $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
1919  } else {
1920  $sql .= ' WHERE 1 = 1';
1921  }
1922  // Manage filter
1923  $sqlwhere = array();
1924  if (count($filter) > 0) {
1925  foreach ($filter as $key => $value) {
1926  if ($key == 't.rowid') {
1927  $sqlwhere[] = $key." = ".((int) $value);
1928  } elseif (strpos($key, 'date') !== false) {
1929  $sqlwhere[] = $key." = '".$this->db->idate($value)."'";
1930  } elseif ($key == 'customsql') {
1931  $sqlwhere[] = $value;
1932  } else {
1933  $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'";
1934  }
1935  }
1936  }
1937  if (count($sqlwhere) > 0) {
1938  $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')';
1939  }
1940 
1941  if (!empty($sortfield)) {
1942  $sql .= $this->db->order($sortfield, $sortorder);
1943  }
1944  if (!empty($limit)) {
1945  $sql .= $this->db->plimit($limit, $offset);
1946  }
1947 
1948  $resql = $this->db->query($sql);
1949  if ($resql) {
1950  $num = $this->db->num_rows($resql);
1951  $i = 0;
1952  while ($i < ($limit ? min($limit, $num) : $num)) {
1953  $obj = $this->db->fetch_object($resql);
1954 
1955  $record = new self($this->db);
1956  $record->setVarsFromFetchObj($obj);
1957 
1958  $records[$record->id] = $record;
1959 
1960  $i++;
1961  }
1962  $this->db->free($resql);
1963 
1964  return $records;
1965  } else {
1966  $this->errors[] = 'Error '.$this->db->lasterror();
1967  dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
1968 
1969  return -1;
1970  }
1971  }
1972 
1980  public function update(User $user, $notrigger = false)
1981  {
1982  return $this->updateCommon($user, $notrigger);
1983  }
1984 
1992  public function delete(User $user, $notrigger = false)
1993  {
1994  return $this->deleteCommon($user, $notrigger);
1995  //return $this->deleteCommon($user, $notrigger, 1);
1996  }
1997 }
$object ref
Definition: info.php:78
Class for BOM.
Definition: bom.class.php:39
Parent class of all other business classes (invoices, contracts, proposals, orders,...
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
deleteLineCommon(User $user, $idline, $notrigger=false)
Delete a line of object in database.
fetchCommon($id, $ref=null, $morewhere='')
Load object in memory from the database.
createCommon(User $user, $notrigger=false)
Create object into database.
deleteCommon(User $user, $notrigger=false, $forcechilddeletion=0)
Delete object in database.
getFieldList($alias='', $excludefields=array())
Function to concat keys of fields.
setStatusCommon($user, $status, $notrigger=0, $triggercode='')
Set to a status.
initAsSpecimenCommon()
Initialise object with example values Id must be 0 if object instance is a specimen.
copy_linked_contact($objFrom, $source='internal')
Copy contact from one element to current.
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
fetch_product()
Load the product with id $this->fk_product into this->product.
updateCommon(User $user, $notrigger=false)
Update object into database.
fetchLinesCommon($morewhere='')
Load object in memory from the database.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage Dolibarr database access.
Class to manage warehouses.
Class for Mo.
Definition: mo.class.php:34
__construct(DoliDB $db)
Constructor.
Definition: mo.class.php:255
update(User $user, $notrigger=false)
Update object into database.
Definition: mo.class.php:649
fetchLinesLinked($role, $lineid=0)
Get list of lines linked to current line for a defined role.
Definition: mo.class.php:563
getMoChilds()
Function used to return childs of Mo.
Definition: mo.class.php:1644
static replaceThirdparty($db, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
Definition: mo.class.php:1631
printOriginLinesList($restrictlist='', $selectedLines=array())
Return HTML table table of source object lines TODO Move this and previous function into output html ...
Definition: mo.class.php:1516
fetchLines()
Load object lines in memory from the database.
Definition: mo.class.php:469
getNextNumRef($prod)
Returns the reference to the following non used MO depending on the active numbering module defined i...
Definition: mo.class.php:941
deleteLine(User $user, $idline, $notrigger=false)
Delete a line of object in database.
Definition: mo.class.php:856
cancel($user, $notrigger=0)
Set cancel status.
Definition: mo.class.php:1138
fetch($id, $ref=null)
Load object in memory from the database.
Definition: mo.class.php:452
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
Definition: mo.class.php:1406
reopen($user, $notrigger=0)
Set back to validated status.
Definition: mo.class.php:1162
updateProduction(User $user, $notrigger=true)
Update quantities in lines to consume and/or lines to produce.
Definition: mo.class.php:794
getMoParent()
Function used to return childs of Mo.
Definition: mo.class.php:1682
getLinesArray($rolefilter='')
Create an array of lines.
Definition: mo.class.php:1419
LibStatut($status, $mode=0)
Return the status.
Definition: mo.class.php:1334
setDraft($user, $notrigger=0)
Set draft status.
Definition: mo.class.php:1114
printOriginLine($line, $var, $restrictlist='', $defaulttpldir='/core/tpl', $selectedLines=array())
Return HTML with a line of table array of source object lines TODO Move this and previous function in...
Definition: mo.class.php:1588
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, array $filter=array(), $filtermode='AND')
Load list of objects in memory from the database.
Definition: mo.class.php:489
getKanbanView($option='', $arraydata=null)
Return clicable link of object (with eventually picto)
Definition: mo.class.php:1719
validate($user, $notrigger=0)
Validate Mo.
Definition: mo.class.php:989
doScheduledJob()
Action executed by scheduler CAN BE A CRON TASK.
Definition: mo.class.php:1483
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
Definition: mo.class.php:1450
getTooltipContentArray($params)
getTooltipContentArray
Definition: mo.class.php:1186
createProduction(User $user, $notrigger=true)
Erase and update the line to consume and to produce.
Definition: mo.class.php:685
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionaly the picto)
Definition: mo.class.php:1235
getLibStatut($mode=0)
Return label of the status.
Definition: mo.class.php:1321
info($id)
Load the info information in the object.
Definition: mo.class.php:1376
create(User $user, $notrigger=false)
Create object into database.
Definition: mo.class.php:292
countMovements()
Count number of movement with origin of MO.
Definition: mo.class.php:614
createFromClone(User $user, $fromid)
Clone an object into another one.
Definition: mo.class.php:350
Class MoLine.
Definition: mo.class.php:1757
create(User $user, $notrigger=false)
Create object into database.
Definition: mo.class.php:1872
update(User $user, $notrigger=false)
Update object into database.
Definition: mo.class.php:1980
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, array $filter=array(), $filtermode='AND')
Load list of objects in memory from the database.
Definition: mo.class.php:1906
__construct(DoliDB $db)
Constructor.
Definition: mo.class.php:1833
fetch($id, $ref=null)
Load object in memory from the database.
Definition: mo.class.php:1889
Class to manage stock movements.
Class to manage products or services.
Class to manage Dolibarr users.
Definition: user.class.php:48
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:62
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.