dolibarr  19.0.0-dev
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  // Clear fields
377  $object->ref = empty($this->fields['ref']['default']) ? "copy_of_".$object->ref : $this->fields['ref']['default'];
378  $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
379  $object->status = self::STATUS_DRAFT;
380  // ...
381  // Clear extrafields that are unique
382  if (is_array($object->array_options) && count($object->array_options) > 0) {
383  $extrafields->fetch_name_optionals_label($this->table_element);
384  foreach ($object->array_options as $key => $option) {
385  $shortkey = preg_replace('/options_/', '', $key);
386  if (!empty($extrafields->attributes[$this->element]['unique'][$shortkey])) {
387  //var_dump($key);
388  //var_dump($clonedObj->array_options[$key]); exit;
389  unset($object->array_options[$key]);
390  }
391  }
392  }
393 
394  // Create clone
395  $object->context['createfromclone'] = 'createfromclone';
396  $result = $object->createCommon($user);
397  if ($result < 0) {
398  $error++;
399  $this->error = $object->error;
400  $this->errors = $object->errors;
401  }
402 
403  if (!$error) {
404  // copy internal contacts
405  if ($this->copy_linked_contact($object, 'internal') < 0) {
406  $error++;
407  }
408  }
409 
410  if (!$error) {
411  // copy external contacts if same company
412  if (property_exists($this, 'socid') && $this->socid == $object->socid) {
413  if ($this->copy_linked_contact($object, 'external') < 0) {
414  $error++;
415  }
416  }
417  }
418 
419  unset($object->context['createfromclone']);
420 
421  // End
422  if (!$error) {
423  $this->db->commit();
424  return $object;
425  } else {
426  $this->db->rollback();
427  return -1;
428  }
429  }
430 
438  public function fetch($id, $ref = null)
439  {
440  $result = $this->fetchCommon($id, $ref);
441  if ($result > 0 && !empty($this->table_element_line)) {
442  $this->fetchLines();
443  }
444 
445  $this->socid = $this->fk_soc;
446 
447  return $result;
448  }
449 
455  public function fetchLines()
456  {
457  $this->lines = array();
458 
459  $result = $this->fetchLinesCommon();
460  return $result;
461  }
462 
463 
475  public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
476  {
477  global $conf;
478 
479  dol_syslog(__METHOD__, LOG_DEBUG);
480 
481  $records = array();
482 
483  $sql = 'SELECT ';
484  $sql .= $this->getFieldList();
485  $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
486  if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
487  $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
488  } else {
489  $sql .= ' WHERE 1 = 1';
490  }
491  // Manage filter
492  $sqlwhere = array();
493  if (count($filter) > 0) {
494  foreach ($filter as $key => $value) {
495  if ($key == 't.rowid') {
496  $sqlwhere[] = $key." = ".((int) $value);
497  } elseif (strpos($key, 'date') !== false) {
498  $sqlwhere[] = $key." = '".$this->db->idate($value)."'";
499  } elseif ($key == 'customsql') {
500  $sqlwhere[] = $value;
501  } else {
502  $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'";
503  }
504  }
505  }
506  if (count($sqlwhere) > 0) {
507  $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')';
508  }
509 
510  if (!empty($sortfield)) {
511  $sql .= $this->db->order($sortfield, $sortorder);
512  }
513  if (!empty($limit)) {
514  $sql .= $this->db->plimit($limit, $offset);
515  }
516 
517  $resql = $this->db->query($sql);
518  if ($resql) {
519  $num = $this->db->num_rows($resql);
520  $i = 0;
521  while ($i < min($limit, $num)) {
522  $obj = $this->db->fetch_object($resql);
523 
524  $record = new self($this->db);
525  $record->setVarsFromFetchObj($obj);
526 
527  $records[$record->id] = $record;
528 
529  $i++;
530  }
531  $this->db->free($resql);
532 
533  return $records;
534  } else {
535  $this->errors[] = 'Error '.$this->db->lasterror();
536  dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
537 
538  return -1;
539  }
540  }
541 
549  public function fetchLinesLinked($role, $lineid = 0)
550  {
551  $resarray = array();
552  $mostatic = new MoLine($this->db);
553 
554  $sql = 'SELECT ';
555  $sql .= $mostatic->getFieldList();
556  $sql .= ' FROM '.MAIN_DB_PREFIX.$mostatic->table_element.' as t';
557  $sql .= " WHERE t.role = '".$this->db->escape($role)."'";
558  if ($lineid > 0) {
559  $sql .= ' AND t.fk_mrp_production = '.((int) $lineid);
560  } else {
561  $sql .= 'AND t.fk_mo = '.((int) $this->id);
562  }
563 
564  $resql = $this->db->query($sql);
565  if ($resql) {
566  $num = $this->db->num_rows($resql);
567 
568  $i = 0;
569  while ($i < $num) {
570  $obj = $this->db->fetch_object($resql);
571  if ($obj) {
572  $resarray[] = array(
573  'rowid'=> $obj->rowid,
574  'date'=> $this->db->jdate($obj->date_creation),
575  'qty' => $obj->qty,
576  'role' => $obj->role,
577  'fk_product' => $obj->fk_product,
578  'fk_warehouse' => $obj->fk_warehouse,
579  'batch' => $obj->batch,
580  'fk_stock_movement' => $obj->fk_stock_movement
581  );
582  }
583 
584  $i++;
585  }
586 
587  return $resarray;
588  } else {
589  $this->error = $this->db->lasterror();
590  return array();
591  }
592  }
593 
594 
600  public function countMovements()
601  {
602  $result = 0;
603 
604  $sql = 'SELECT COUNT(rowid) as nb FROM '.MAIN_DB_PREFIX.'stock_mouvement as sm';
605  $sql .= " WHERE sm.origintype = 'mo' and sm.fk_origin = ".((int) $this->id);
606 
607  $resql = $this->db->query($sql);
608  if ($resql) {
609  $num = $this->db->num_rows($resql);
610 
611  $i = 0;
612  while ($i < $num) {
613  $obj = $this->db->fetch_object($resql);
614  if ($obj) {
615  $result = $obj->nb;
616  }
617 
618  $i++;
619  }
620  } else {
621  $this->error = $this->db->lasterror();
622  }
623 
624  return $result;
625  }
626 
627 
635  public function update(User $user, $notrigger = false)
636  {
637  global $langs;
638 
639  $error = 0;
640 
641  $this->db->begin();
642 
643  $result = $this->updateCommon($user, $notrigger);
644  if ($result <= 0) {
645  $error++;
646  }
647 
648  // Update the lines (the qty) to consume or to produce
649  $result = $this->updateProduction($user, $notrigger);
650  if ($result <= 0) {
651  $error++;
652  }
653 
654  if (!$error) {
655  $this->db->commit();
656  return 1;
657  } else {
658  $this->db->rollback();
659  return -1;
660  }
661  }
662 
663 
671  public function createProduction(User $user, $notrigger = true)
672  {
673  $error = 0;
674  $role = "";
675 
676  if ($this->status != self::STATUS_DRAFT) {
677  return -1;
678  }
679 
680  $this->db->begin();
681 
682  // Insert lines in mrp_production table from BOM data
683  if (!$error) {
684  $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'mrp_production WHERE fk_mo = '.((int) $this->id);
685  $this->db->query($sql);
686 
687  $moline = new MoLine($this->db);
688 
689  // Line to produce
690  $moline->fk_mo = $this->id;
691  $moline->qty = $this->qty;
692  $moline->fk_product = $this->fk_product;
693  $moline->position = 1;
694 
695  if ($this->fk_bom > 0) { // If a BOM is defined, we know what to produce.
696  include_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php';
697  $bom = new BOM($this->db);
698  $bom->fetch($this->fk_bom);
699  if ($bom->bomtype == 1) {
700  $role = 'toproduce';
701  $moline->role = 'toconsume';
702  } else {
703  $role = 'toconsume';
704  $moline->role = 'toproduce';
705  }
706  } else {
707  if ($this->mrptype == 1) {
708  $moline->role = 'toconsume';
709  } else {
710  $moline->role = 'toproduce';
711  }
712  }
713 
714  $resultline = $moline->create($user, false); // Never use triggers here
715  if ($resultline <= 0) {
716  $error++;
717  $this->error = $moline->error;
718  $this->errors = $moline->errors;
719  dol_print_error($this->db, $moline->error, $moline->errors);
720  }
721 
722  if ($this->fk_bom > 0) { // If a BOM is defined, we know what to consume.
723  if ($bom->id > 0) {
724  // Lines to consume
725  if (!$error) {
726  foreach ($bom->lines as $line) {
727  $moline = new MoLine($this->db);
728 
729  $moline->fk_mo = $this->id;
730  $moline->origin_id = $line->id;
731  $moline->origin_type = 'bomline';
732  if ($line->qty_frozen) {
733  $moline->qty = $line->qty; // Qty to consume does not depends on quantity to produce
734  } else {
735  $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
736  }
737  if ($moline->qty <= 0) {
738  $error++;
739  $this->error = "BadValueForquantityToConsume";
740  break;
741  } else {
742  $moline->fk_product = $line->fk_product;
743  $moline->role = $role;
744  $moline->position = $line->position;
745  $moline->qty_frozen = $line->qty_frozen;
746  $moline->disable_stock_change = $line->disable_stock_change;
747  if (!empty($line->fk_default_workstation)) $moline->fk_default_workstation = $line->fk_default_workstation;
748 
749  $resultline = $moline->create($user, false); // Never use triggers here
750  if ($resultline <= 0) {
751  $error++;
752  $this->error = $moline->error;
753  $this->errors = $moline->errors;
754  dol_print_error($this->db, $moline->error, $moline->errors);
755  break;
756  }
757  }
758  }
759  }
760  }
761  }
762  }
763 
764  if (!$error) {
765  $this->db->commit();
766  return 1;
767  } else {
768  $this->db->rollback();
769  return -1;
770  }
771  }
772 
780  public function updateProduction(User $user, $notrigger = true)
781  {
782  $error = 0;
783 
784  if ($this->status != self::STATUS_DRAFT) return 1;
785 
786  $this->db->begin();
787 
788  $oldQty = $this->oldQty;
789  $newQty = $this->qty;
790  if ($newQty != $oldQty && !empty($this->oldQty)) {
791  $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "mrp_production WHERE fk_mo = " . (int) $this->id;
792  $resql = $this->db->query($sql);
793  if ($resql) {
794  while ($obj = $this->db->fetch_object($resql)) {
795  $moLine = new MoLine($this->db);
796  $res = $moLine->fetch($obj->rowid);
797  if (!$res) $error++;
798 
799  if ($moLine->role == 'toconsume' || $moLine->role == 'toproduce') {
800  if (empty($moLine->qty_frozen)) {
801  $qty = $newQty * $moLine->qty / $oldQty;
802  $moLine->qty = price2num($qty * (!empty($line->efficiency) ? $line->efficiency : 1 ), 'MS'); // Calculate with Qty to produce and more presition
803  $res = $moLine->update($user);
804  if (!$res) $error++;
805  }
806  }
807  }
808  }
809  }
810 
811  if (!$error) {
812  $this->db->commit();
813  return 1;
814  } else {
815  $this->db->rollback();
816  return -1;
817  }
818  }
819 
820 
828  public function delete(User $user, $notrigger = false)
829  {
830  return $this->deleteCommon($user, $notrigger);
831  //return $this->deleteCommon($user, $notrigger, 1);
832  }
833 
842  public function deleteLine(User $user, $idline, $notrigger = false)
843  {
844  global $langs;
845  $langs->loadLangs(array('stocks', 'mrp'));
846 
847  if ($this->status < 0) {
848  $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
849  return -2;
850  }
851 
852  $productstatic = new Product($this->db);
853  $fk_movement = GETPOST('fk_movement', 'int');
854  $arrayoflines = $this->fetchLinesLinked('consumed', $idline);
855 
856  if (!empty($arrayoflines)) {
857  $this->db->begin();
858 
859  $stockmove = new MouvementStock($this->db);
860  $stockmove->setOrigin($this->element, $this->id);
861 
862  if (!empty($fk_movement)) {
863  $moline = new MoLine($this->db);
864  $TArrayMoLine = $moline->fetchAll('', '', 1, 0, array('customsql' => 'fk_stock_movement ='.$fk_movement));
865  $moline = array_shift($TArrayMoLine);
866 
867  $movement = new MouvementStock($this->db);
868  $movement->fetch($fk_movement);
869  $productstatic->fetch($movement->product_id);
870  $qtytoprocess = $movement->qty;
871 
872  // Reverse stock movement
873  $labelmovementCancel = $langs->trans("CancelProductionForRef", $productstatic->ref);
874  $codemovementCancel = $langs->trans("StockIncrease");
875 
876  if (($qtytoprocess >= 0)) {
877  $idstockmove = $stockmove->reception($user, $movement->product_id, $movement->warehouse_id, $qtytoprocess, 0, $labelmovementCancel, '', '', $movement->batch, dol_now(), 0, $codemovementCancel);
878  } else {
879  $idstockmove = $stockmove->livraison($user, $movement->product_id, $movement->warehouse_id, $qtytoprocess, 0, $labelmovementCancel, dol_now(), '', '', $movement->batch, 0, $codemovementCancel);
880  }
881  if ($idstockmove < 0) {
882  $this->error++;
883  $this->db->rollback();
884  setEventMessages($stockmove->error, $stockmove->errors, 'errors');
885  } else {
886  $this->db->commit();
887  }
888  return $moline->delete($user, $notrigger);
889  } else {
890  foreach ($arrayoflines as $key => $arrayofline) {
891  $lineDetails = $arrayoflines[$key];
892  $productstatic->fetch($lineDetails['fk_product']);
893  $qtytoprocess = $lineDetails['qty'];
894 
895  // Reverse stock movement
896  $labelmovementCancel = $langs->trans("CancelProductionForRef", $productstatic->ref);
897  $codemovementCancel = $langs->trans("StockIncrease");
898 
899  if ($qtytoprocess >= 0) {
900  $idstockmove = $stockmove->reception($user, $lineDetails['fk_product'], $lineDetails['fk_warehouse'], $qtytoprocess, 0, $labelmovementCancel, '', '', $lineDetails['batch'], dol_now(), 0, $codemovementCancel);
901  } else {
902  $idstockmove = $stockmove->livraison($user, $lineDetails['fk_product'], $lineDetails['fk_warehouse'], $qtytoprocess, 0, $labelmovementCancel, dol_now(), '', '', $lineDetails['batch'], 0, $codemovementCancel);
903  }
904  if ($idstockmove < 0) {
905  $this->error++;
906  $this->db->rollback();
907  setEventMessages($stockmove->error, $stockmove->errors, 'errors');
908  } else {
909  $this->db->commit();
910  }
911  }
912  return $this->deleteLineCommon($user, $idline, $notrigger);
913  }
914  } else {
915  return $this->deleteLineCommon($user, $idline, $notrigger);
916  }
917  }
918 
919 
927  public function getNextNumRef($prod)
928  {
929  global $langs, $conf;
930  $langs->load("mrp");
931 
932  if (!empty($conf->global->MRP_MO_ADDON)) {
933  $mybool = false;
934 
935  $file = $conf->global->MRP_MO_ADDON.".php";
936  $classname = $conf->global->MRP_MO_ADDON;
937 
938  // Include file with class
939  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
940  foreach ($dirmodels as $reldir) {
941  $dir = dol_buildpath($reldir."core/modules/mrp/");
942 
943  // Load file with numbering class (if found)
944  $mybool |= @include_once $dir.$file;
945  }
946 
947  if ($mybool === false) {
948  dol_print_error('', "Failed to include file ".$file);
949  return '';
950  }
951 
952  $obj = new $classname();
953  $numref = $obj->getNextValue($prod, $this);
954 
955  if ($numref != "") {
956  return $numref;
957  } else {
958  $this->error = $obj->error;
959  //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
960  return "";
961  }
962  } else {
963  print $langs->trans("Error")." ".$langs->trans("Error_MRP_MO_ADDON_NotDefined");
964  return "";
965  }
966  }
967 
975  public function validate($user, $notrigger = 0)
976  {
977  global $conf, $langs;
978 
979  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
980 
981  $error = 0;
982 
983  // Protection
984  if ($this->status == self::STATUS_VALIDATED) {
985  dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING);
986  return 0;
987  }
988 
989  /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mrp->create))
990  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mrp->mrp_advance->validate))))
991  {
992  $this->error='NotEnoughPermissions';
993  dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
994  return -1;
995  }*/
996 
997  $now = dol_now();
998 
999  $this->db->begin();
1000 
1001  // Define new ref
1002  if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
1003  $this->fetch_product();
1004  $num = $this->getNextNumRef($this->product);
1005  } else {
1006  $num = $this->ref;
1007  }
1008  $this->newref = $num;
1009 
1010  // Validate
1011  $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
1012  $sql .= " SET ref = '".$this->db->escape($num)."',";
1013  $sql .= " status = ".self::STATUS_VALIDATED.",";
1014  $sql .= " date_valid='".$this->db->idate($now)."',";
1015  $sql .= " fk_user_valid = ".$user->id;
1016  $sql .= " WHERE rowid = ".((int) $this->id);
1017 
1018  dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
1019  $resql = $this->db->query($sql);
1020  if (!$resql) {
1021  dol_print_error($this->db);
1022  $this->error = $this->db->lasterror();
1023  $error++;
1024  }
1025 
1026  if (!$error && !$notrigger) {
1027  // Call trigger
1028  $result = $this->call_trigger('MRP_MO_VALIDATE', $user);
1029  if ($result < 0) {
1030  $error++;
1031  }
1032  // End call triggers
1033  }
1034 
1035  if (!$error) {
1036  $this->oldref = $this->ref;
1037 
1038  // Rename directory if dir was a temporary ref
1039  if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
1040  // Now we rename also files into index
1041  $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)."'";
1042  $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'mrp/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
1043  $resql = $this->db->query($sql);
1044  if (!$resql) {
1045  $error++; $this->error = $this->db->lasterror();
1046  }
1047 
1048  // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
1049  $oldref = dol_sanitizeFileName($this->ref);
1050  $newref = dol_sanitizeFileName($num);
1051  $dirsource = $conf->mrp->dir_output.'/'.$oldref;
1052  $dirdest = $conf->mrp->dir_output.'/'.$newref;
1053  if (!$error && file_exists($dirsource)) {
1054  dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
1055 
1056  if (@rename($dirsource, $dirdest)) {
1057  dol_syslog("Rename ok");
1058  // Rename docs starting with $oldref with $newref
1059  $listoffiles = dol_dir_list($conf->mrp->dir_output.'/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
1060  foreach ($listoffiles as $fileentry) {
1061  $dirsource = $fileentry['name'];
1062  $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
1063  $dirsource = $fileentry['path'].'/'.$dirsource;
1064  $dirdest = $fileentry['path'].'/'.$dirdest;
1065  @rename($dirsource, $dirdest);
1066  }
1067  }
1068  }
1069  }
1070  }
1071 
1072  // Set new ref and current status
1073  if (!$error) {
1074  $this->ref = $num;
1075  $this->status = self::STATUS_VALIDATED;
1076  }
1077 
1078  if (!$error) {
1079  $this->db->commit();
1080  return 1;
1081  } else {
1082  $this->db->rollback();
1083  return -1;
1084  }
1085  }
1086 
1094  public function setDraft($user, $notrigger = 0)
1095  {
1096  // Protection
1097  if ($this->status <= self::STATUS_DRAFT) {
1098  return 0;
1099  }
1100 
1101  /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mymodule->write))
1102  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mymodule->mymodule_advance->validate))))
1103  {
1104  $this->error='Permission denied';
1105  return -1;
1106  }*/
1107 
1108  return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'MRP_MO_UNVALIDATE');
1109  }
1110 
1118  public function cancel($user, $notrigger = 0)
1119  {
1120  // Protection
1121  if ($this->status != self::STATUS_VALIDATED && $this->status != self::STATUS_INPROGRESS) {
1122  return 0;
1123  }
1124 
1125  /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mymodule->write))
1126  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mymodule->mymodule_advance->validate))))
1127  {
1128  $this->error='Permission denied';
1129  return -1;
1130  }*/
1131 
1132  return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'MRP_MO_CANCEL');
1133  }
1134 
1142  public function reopen($user, $notrigger = 0)
1143  {
1144  // Protection
1145  if ($this->status != self::STATUS_PRODUCED && $this->status != self::STATUS_CANCELED) {
1146  return 0;
1147  }
1148 
1149  /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mymodule->write))
1150  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->mymodule->mymodule_advance->validate))))
1151  {
1152  $this->error='Permission denied';
1153  return -1;
1154  }*/
1155 
1156  return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'MRP_MO_REOPEN');
1157  }
1158 
1166  public function getTooltipContentArray($params)
1167  {
1168  global $conf, $langs;
1169 
1170  $langs->loadLangs(['mrp', 'products']);
1171  $nofetch = isset($params['nofetch']) ? true : false;
1172 
1173  $datas = [];
1174 
1175  $datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("ManufacturingOrder").'</u>';
1176  if (isset($this->status)) {
1177  $datas['picto'] .= ' '.$this->getLibStatut(5);
1178  }
1179  $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1180  if (isset($this->label)) {
1181  $datas['label'] = '<br><b>'.$langs->trans('Label').':</b> '.$this->label;
1182  }
1183  if (isset($this->mrptype)) {
1184  $datas['type'] = '<br><b>'.$langs->trans('Type').':</b> '.$this->fields['mrptype']['arrayofkeyval'][$this->mrptype];
1185  }
1186  if (isset($this->qty)) {
1187  $datas['qty'] = '<br><b>'.$langs->trans('QtyToProduce').':</b> '.$this->qty;
1188  }
1189  if (!$nofetch && isset($this->fk_product)) {
1190  require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
1191  $product = new Product($this->db);
1192  $product->fetch($this->fk_product);
1193  $datas['product'] = '<br><b>'.$langs->trans('Product').':</b> '.$product->getNomUrl(1, '', 0, -1, 1);
1194  }
1195  if (!$nofetch && isset($this->fk_warehouse)) {
1196  require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
1197  $warehouse = new Entrepot($this->db);
1198  $warehouse->fetch($this->fk_warehouse);
1199  $datas['warehouse'] = '<br><b>'.$langs->trans('WarehouseForProduction').':</b> '.$warehouse->getNomUrl(1, '', 0, 1);
1200  }
1201 
1202  return $datas;
1203  }
1204 
1215  public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1216  {
1217  global $conf, $langs, $hookmanager;
1218 
1219  if (!empty($conf->dol_no_mouse_hover)) {
1220  $notooltip = 1; // Force disable tooltips
1221  }
1222 
1223  $result = '';
1224  $params = [
1225  'id' => $this->id,
1226  'objecttype' => $this->element,
1227  'option' => $option,
1228  'nofetch' => 1,
1229  ];
1230  $classfortooltip = 'classfortooltip';
1231  $dataparams = '';
1232  if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1233  $classfortooltip = 'classforajaxtooltip';
1234  $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1235  $label = '';
1236  } else {
1237  $label = implode($this->getTooltipContentArray($params));
1238  }
1239 
1240  $url = DOL_URL_ROOT.'/mrp/mo_card.php?id='.$this->id;
1241  if ($option == 'production') {
1242  $url = DOL_URL_ROOT.'/mrp/mo_production.php?id='.$this->id;
1243  }
1244 
1245  if ($option != 'nolink') {
1246  // Add param to save lastsearch_values or not
1247  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1248  if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1249  $add_save_lastsearch_values = 1;
1250  }
1251  if ($add_save_lastsearch_values) {
1252  $url .= '&save_lastsearch_values=1';
1253  }
1254  }
1255 
1256  $linkclose = '';
1257  if (empty($notooltip)) {
1258  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
1259  $label = $langs->trans("ShowMo");
1260  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1261  }
1262  $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
1263  $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
1264  } else {
1265  $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1266  }
1267 
1268  $linkstart = '<a href="'.$url.'"';
1269  $linkstart .= $linkclose.'>';
1270  $linkend = '</a>';
1271 
1272  $result .= $linkstart;
1273  if ($withpicto) {
1274  $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1);
1275  }
1276  if ($withpicto != 2) {
1277  $result .= $this->ref;
1278  }
1279  $result .= $linkend;
1280  //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
1281 
1282  global $action, $hookmanager;
1283  $hookmanager->initHooks(array('modao'));
1284  $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
1285  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1286  if ($reshook > 0) {
1287  $result = $hookmanager->resPrint;
1288  } else {
1289  $result .= $hookmanager->resPrint;
1290  }
1291 
1292  return $result;
1293  }
1294 
1301  public function getLibStatut($mode = 0)
1302  {
1303  return $this->LibStatut($this->status, $mode);
1304  }
1305 
1306  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1314  public function LibStatut($status, $mode = 0)
1315  {
1316  // phpcs:enable
1317  if (empty($this->labelStatus)) {
1318  global $langs;
1319  //$langs->load("mrp");
1320  $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1321  $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('ValidatedToProduce');
1322  $this->labelStatus[self::STATUS_INPROGRESS] = $langs->transnoentitiesnoconv('InProgress');
1323  $this->labelStatus[self::STATUS_PRODUCED] = $langs->transnoentitiesnoconv('StatusMOProduced');
1324  $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
1325 
1326  $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1327  $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
1328  $this->labelStatusShort[self::STATUS_INPROGRESS] = $langs->transnoentitiesnoconv('InProgress');
1329  $this->labelStatusShort[self::STATUS_PRODUCED] = $langs->transnoentitiesnoconv('StatusMOProduced');
1330  $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
1331  }
1332 
1333  $statusType = 'status'.$status;
1334  if ($status == self::STATUS_VALIDATED) {
1335  $statusType = 'status1';
1336  }
1337  if ($status == self::STATUS_INPROGRESS) {
1338  $statusType = 'status4';
1339  }
1340  if ($status == self::STATUS_PRODUCED) {
1341  $statusType = 'status6';
1342  }
1343  if ($status == self::STATUS_CANCELED) {
1344  $statusType = 'status9';
1345  }
1346 
1347  return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
1348  }
1349 
1356  public function info($id)
1357  {
1358  $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
1359  $sql .= ' fk_user_creat, fk_user_modif';
1360  $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
1361  $sql .= ' WHERE t.rowid = '.((int) $id);
1362  $result = $this->db->query($sql);
1363  if ($result) {
1364  if ($this->db->num_rows($result)) {
1365  $obj = $this->db->fetch_object($result);
1366  $this->id = $obj->rowid;
1367 
1368  $this->user_creation_id = $obj->fk_user_creat;
1369  $this->user_modification_id = $obj->fk_user_modif;
1370  $this->date_creation = $this->db->jdate($obj->datec);
1371  $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1372  }
1373 
1374  $this->db->free($result);
1375  } else {
1376  dol_print_error($this->db);
1377  }
1378  }
1379 
1386  public function initAsSpecimen()
1387  {
1388  $this->initAsSpecimenCommon();
1389 
1390  $this->lines = array();
1391  }
1392 
1399  public function getLinesArray($rolefilter = '')
1400  {
1401  $this->lines = array();
1402 
1403  $objectline = new MoLine($this->db);
1404 
1405  $TFilters = array('customsql'=>'fk_mo = '.((int) $this->id));
1406  if (!empty($rolefilter)) $TFilters['role'] = $rolefilter;
1407  $result = $objectline->fetchAll('ASC', 'position', 0, 0, $TFilters);
1408 
1409  if (is_numeric($result)) {
1410  $this->error = $objectline->error;
1411  $this->errors = $objectline->errors;
1412  return $result;
1413  } else {
1414  $this->lines = $result;
1415  return $this->lines;
1416  }
1417  }
1418 
1430  public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1431  {
1432  global $conf, $langs;
1433 
1434  $langs->load("mrp");
1435 
1436  if (!dol_strlen($modele)) {
1437  //$modele = 'standard';
1438  $modele = ''; // Remove this once a pdf_standard.php exists.
1439 
1440  if ($this->model_pdf) {
1441  $modele = $this->model_pdf;
1442  } elseif (!empty($conf->global->MO_ADDON_PDF)) {
1443  $modele = $conf->global->MO_ADDON_PDF;
1444  }
1445  }
1446 
1447  $modelpath = "core/modules/mrp/doc/";
1448 
1449  if (empty($modele)) {
1450  return 1; // Remove this once a pdf_standard.php exists.
1451  }
1452 
1453  return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1454  }
1455 
1463  public function doScheduledJob()
1464  {
1465  global $conf, $langs;
1466 
1467  //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1468 
1469  $error = 0;
1470  $this->output = '';
1471  $this->error = '';
1472 
1473  dol_syslog(__METHOD__, LOG_DEBUG);
1474 
1475  $now = dol_now();
1476 
1477  $this->db->begin();
1478 
1479  // ...
1480 
1481  $this->db->commit();
1482 
1483  return $error;
1484  }
1485 
1496  public function printOriginLinesList($restrictlist = '', $selectedLines = array())
1497  {
1498  global $langs, $hookmanager, $conf, $form;
1499 
1500  $langs->load('stocks');
1501  $text_stock_options = $langs->trans("RealStockDesc").'<br>';
1502  $text_stock_options .= $langs->trans("RealStockWillAutomaticallyWhen").'<br>';
1503  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE) ? '- '.$langs->trans("DeStockOnShipment").'<br>' : '');
1504  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) ? '- '.$langs->trans("DeStockOnValidateOrder").'<br>' : '');
1505  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_BILL) ? '- '.$langs->trans("DeStockOnBill").'<br>' : '');
1506  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL) ? '- '.$langs->trans("ReStockOnBill").'<br>' : '');
1507  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER) ? '- '.$langs->trans("ReStockOnValidateOrder").'<br>' : '');
1508  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) ? '- '.$langs->trans("ReStockOnDispatchOrder").'<br>' : '');
1509  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE) ? '- '.$langs->trans("StockOnReception").'<br>' : '');
1510 
1511  print '<tr class="liste_titre">';
1512  // Product or sub-bom
1513  print '<td class="linecoldescription">'.$langs->trans('Ref');
1514  if (!empty($conf->global->BOM_SUB_BOM)) {
1515  print ' &nbsp; <a id="show_all" href="#">'.img_picto('', 'folder-open', 'class="paddingright"').$langs->trans("ExpandAll").'</a>&nbsp;&nbsp;';
1516  print '<a id="hide_all" href="#">'.img_picto('', 'folder', 'class="paddingright"').$langs->trans("UndoExpandAll").'</a>&nbsp;';
1517  }
1518  print '</td>';
1519  // Qty
1520  print '<td class="right">'.$langs->trans('Qty');
1521  if ($this->bom->bomtype == 0) {
1522  print ' <span class="opacitymedium">('.$langs->trans("ForAQuantityOf", $this->bom->qty).')</span>';
1523  } else {
1524  print ' <span class="opacitymedium">('.$langs->trans("ForAQuantityToConsumeOf", $this->bom->qty).')</span>';
1525  }
1526  print '</td>';
1527  print '<td class="center">'.$form->textwithpicto($langs->trans("PhysicalStock"), $text_stock_options, 1).'</td>';
1528  print '<td class="center">'.$form->textwithpicto($langs->trans("VirtualStock"), $langs->trans("VirtualStockDesc")).'</td>';
1529  print '<td class="center">'.$langs->trans('QtyFrozen').'</td>';
1530  print '<td class="center">'.$langs->trans('DisableStockChange').'</td>';
1531  print '<td class="center">'.$langs->trans('MoChildGenerate').'</td>';
1532  //print '<td class="center">'.$form->showCheckAddButtons('checkforselect', 1).'</td>';
1533  //print '<td class="center"></td>';
1534  print '</tr>';
1535  $i = 0;
1536 
1537  if (!empty($this->lines)) {
1538  foreach ($this->lines as $line) {
1539  $reshook = 0;
1540  if (is_object($hookmanager)) {
1541  $parameters = array('line'=>$line, 'i'=>$i, 'restrictlist'=>$restrictlist, 'selectedLines'=> $selectedLines);
1542  if (!empty($line->fk_parent_line)) { $parameters['fk_parent_line'] = $line->fk_parent_line; }
1543  $reshook = $hookmanager->executeHooks('printOriginObjectLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1544  }
1545  if (empty($reshook)) {
1546  $this->printOriginLine($line, '', $restrictlist, '/core/tpl', $selectedLines);
1547  }
1548 
1549  $i++;
1550  }
1551  }
1552  }
1553 
1554 
1568  public function printOriginLine($line, $var, $restrictlist = '', $defaulttpldir = '/core/tpl', $selectedLines = array())
1569  {
1570  global $langs, $conf;
1571 
1572  $this->tpl['id'] = $line->id;
1573 
1574  $this->tpl['label'] = '';
1575  if (!empty($line->fk_product)) {
1576  $productstatic = new Product($this->db);
1577  $productstatic->fetch($line->fk_product);
1578  $productstatic->load_virtual_stock();
1579  $this->tpl['label'] .= $productstatic->getNomUrl(1);
1580  //$this->tpl['label'].= ' - '.$productstatic->label;
1581  } else {
1582  // If origin MRP line is not a product, but another MRP
1583  // TODO
1584  }
1585 
1586  $this->tpl['qty_bom'] = 1;
1587  if (is_object($this->bom) && $this->bom->qty > 1) {
1588  $this->tpl['qty_bom'] = $this->bom->qty;
1589  }
1590 
1591  $this->tpl['stock'] = $productstatic->stock_reel;
1592  $this->tpl['seuil_stock_alerte'] = $productstatic->seuil_stock_alerte;
1593  $this->tpl['virtual_stock'] = $productstatic->stock_theorique;
1594  $this->tpl['qty'] = $line->qty;
1595  $this->tpl['qty_frozen'] = $line->qty_frozen;
1596  $this->tpl['disable_stock_change'] = $line->disable_stock_change;
1597  $this->tpl['efficiency'] = $line->efficiency;
1598 
1599  $tpl = DOL_DOCUMENT_ROOT.'/mrp/tpl/originproductline.tpl.php';
1600  $res = include $tpl;
1601  }
1602 
1611  public static function replaceThirdparty($db, $origin_id, $dest_id)
1612  {
1613  $tables = array('mrp_mo');
1614 
1615  return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
1616  }
1617 
1618 
1624  public function getMoChilds()
1625  {
1626 
1627  $TMoChilds = array();
1628  $error = 0;
1629 
1630  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."mrp_mo as mo_child";
1631  $sql.= " WHERE fk_parent_line IN ";
1632  $sql.= " (SELECT rowid FROM ".MAIN_DB_PREFIX."mrp_production as line_parent";
1633  $sql.= " WHERE fk_mo=".((int) $this->id).")";
1634 
1635  $resql = $this->db->query($sql);
1636 
1637  if ($resql) {
1638  if ($this->db->num_rows($resql) > 0) {
1639  while ($obj = $this->db->fetch_object($resql)) {
1640  $MoChild = new Mo($this->db);
1641  $res = $MoChild->fetch($obj->rowid);
1642  if ($res > 0) $TMoChilds[$MoChild->id] = $MoChild;
1643  else $error++;
1644  }
1645  }
1646  } else {
1647  $error++;
1648  }
1649 
1650  if ($error) {
1651  return -1;
1652  } else {
1653  return $TMoChilds;
1654  }
1655  }
1656 
1662  public function getMoParent()
1663  {
1664  $MoParent = new Mo($this->db);
1665  $error = 0;
1666 
1667  $sql = "SELECT lineparent.fk_mo as id_moparent FROM ".MAIN_DB_PREFIX."mrp_mo as mo";
1668  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."mrp_production lineparent ON mo.fk_parent_line = lineparent.rowid";
1669  $sql.= " WHERE mo.rowid = ".((int) $this->id);
1670 
1671  $resql = $this->db->query($sql);
1672 
1673  if ($resql) {
1674  if ($this->db->num_rows($resql) > 0) {
1675  $obj = $this->db->fetch_object($resql);
1676  $res = $MoParent->fetch($obj->id_moparent);
1677  if ($res < 0) $error++;
1678  } else {
1679  return 0;
1680  }
1681  } else {
1682  $error++;
1683  }
1684 
1685  if ($error) {
1686  return -1;
1687  } else {
1688  return $MoParent;
1689  }
1690  }
1691 
1699  public function getKanbanView($option = '', $arraydata = null)
1700  {
1701  global $langs;
1702 
1703  $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1704 
1705  $return = '<div class="box-flex-item box-flex-grow-zero">';
1706  $return .= '<div class="info-box info-box-sm">';
1707  $return .= '<span class="info-box-icon bg-infobox-action">';
1708  $return .= img_picto('', $this->picto);
1709  //$return .= '<i class="fa fa-dol-action"></i>'; // Can be image
1710  $return .= '</span>';
1711  $return .= '<div class="info-box-content">';
1712  $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
1713  $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1714  if (!empty($arraydata['bom'])) {
1715  $return .= '<br><span class="info-box-label">'.$arraydata['bom']->getNomUrl(1).'</span>';
1716  }
1717  if (!empty($arraydata['product'])) {
1718  $return .= '<br><span class="info-box-label">'.$arraydata['product']->getNomUrl(1).'</span>';
1719  }
1720  if (property_exists($this, 'qty')) {
1721  $return .= '<br><span class="info-box-label">'.$langs->trans('Quantity').' : '.$this->qty.'</span>';
1722  }
1723  if (method_exists($this, 'getLibStatut')) {
1724  $return .= '<br><div class="info-box-status margintoponly">'.$this->getLibStatut(3).'</div>';
1725  }
1726  $return .= '</div>';
1727  $return .= '</div>';
1728  $return .= '</div>';
1729  return $return;
1730  }
1731 }
1732 
1737 {
1741  public $element = 'mrp_production';
1742 
1746  public $table_element = 'mrp_production';
1747 
1751  public $ismultientitymanaged = 0;
1752 
1756  public $isextrafieldmanaged = 0;
1757 
1758  public $fields = array(
1759  'rowid' =>array('type'=>'integer', 'label'=>'ID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>10),
1760  'fk_mo' =>array('type'=>'integer', 'label'=>'Mo', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>15),
1761  'origin_id' =>array('type'=>'integer', 'label'=>'Origin', 'enabled'=>1, 'visible'=>-1, 'notnull'=>0, 'position'=>17),
1762  'origin_type' =>array('type'=>'varchar(10)', 'label'=>'Origin type', 'enabled'=>1, 'visible'=>-1, 'notnull'=>0, 'position'=>18),
1763  'position' =>array('type'=>'integer', 'label'=>'Position', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>20),
1764  'fk_product' =>array('type'=>'integer', 'label'=>'Product', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>25),
1765  'fk_warehouse' =>array('type'=>'integer', 'label'=>'Warehouse', 'enabled'=>1, 'visible'=>-1, 'position'=>30),
1766  'qty' =>array('type'=>'real', 'label'=>'Qty', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>35),
1767  'qty_frozen' => array('type'=>'smallint', 'label'=>'QuantityFrozen', 'enabled'=>1, 'visible'=>1, 'default'=>0, 'position'=>105, 'css'=>'maxwidth50imp', 'help'=>'QuantityConsumedInvariable'),
1768  'disable_stock_change' => array('type'=>'smallint', 'label'=>'DisableStockChange', 'enabled'=>1, 'visible'=>1, 'default'=>0, 'position'=>108, 'css'=>'maxwidth50imp', 'help'=>'DisableStockChangeHelp'),
1769  'batch' =>array('type'=>'varchar(30)', 'label'=>'Batch', 'enabled'=>1, 'visible'=>-1, 'position'=>140),
1770  'role' =>array('type'=>'varchar(10)', 'label'=>'Role', 'enabled'=>1, 'visible'=>-1, 'position'=>145),
1771  'fk_mrp_production' =>array('type'=>'integer', 'label'=>'Fk mrp production', 'enabled'=>1, 'visible'=>-1, 'position'=>150),
1772  'fk_stock_movement' =>array('type'=>'integer', 'label'=>'StockMovement', 'enabled'=>1, 'visible'=>-1, 'position'=>155),
1773  'date_creation' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>160),
1774  'tms' =>array('type'=>'timestamp', 'label'=>'Tms', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>165),
1775  'fk_user_creat' =>array('type'=>'integer', 'label'=>'UserCreation', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>170),
1776  'fk_user_modif' =>array('type'=>'integer', 'label'=>'UserModification', 'enabled'=>1, 'visible'=>-1, 'position'=>175),
1777  'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-1, 'position'=>180),
1778  'fk_default_workstation' =>array('type'=>'integer', 'label'=>'DefaultWorkstation', 'enabled'=>1, 'visible'=>1, 'notnull'=>0, 'position'=>185)
1779  );
1780 
1781  public $rowid;
1782  public $fk_mo;
1783  public $origin_id;
1784  public $origin_type;
1785  public $position;
1786  public $fk_product;
1787  public $fk_warehouse;
1788  public $qty;
1789  public $qty_frozen;
1790  public $disable_stock_change;
1791  public $efficiency;
1792  public $batch;
1793  public $role;
1794  public $fk_mrp_production;
1795  public $fk_stock_movement;
1796  public $date_creation;
1797  public $tms;
1798  public $fk_user_creat;
1799  public $fk_user_modif;
1800  public $import_key;
1801  public $fk_parent_line;
1802 
1806  public $fk_default_workstation;
1807 
1813  public function __construct(DoliDB $db)
1814  {
1815  global $conf, $langs;
1816 
1817  $this->db = $db;
1818 
1819  if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) {
1820  $this->fields['rowid']['visible'] = 0;
1821  }
1822  if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
1823  $this->fields['entity']['enabled'] = 0;
1824  }
1825 
1826  // Unset fields that are disabled
1827  foreach ($this->fields as $key => $val) {
1828  if (isset($val['enabled']) && empty($val['enabled'])) {
1829  unset($this->fields[$key]);
1830  }
1831  }
1832 
1833  // Translate some data of arrayofkeyval
1834  if (is_object($langs)) {
1835  foreach ($this->fields as $key => $val) {
1836  if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
1837  foreach ($val['arrayofkeyval'] as $key2 => $val2) {
1838  $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
1839  }
1840  }
1841  }
1842  }
1843  }
1844 
1852  public function create(User $user, $notrigger = false)
1853  {
1854  if (empty($this->qty)) {
1855  $this->error = 'BadValueForQty';
1856  return -1;
1857  }
1858 
1859  return $this->createCommon($user, $notrigger);
1860  }
1861 
1869  public function fetch($id, $ref = null)
1870  {
1871  $result = $this->fetchCommon($id, $ref);
1872  return $result;
1873  }
1874 
1886  public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
1887  {
1888  global $conf;
1889 
1890  dol_syslog(__METHOD__, LOG_DEBUG);
1891 
1892  $records = array();
1893 
1894  $sql = 'SELECT ';
1895  $sql .= $this->getFieldList();
1896  $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
1897  if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
1898  $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
1899  } else {
1900  $sql .= ' WHERE 1 = 1';
1901  }
1902  // Manage filter
1903  $sqlwhere = array();
1904  if (count($filter) > 0) {
1905  foreach ($filter as $key => $value) {
1906  if ($key == 't.rowid') {
1907  $sqlwhere[] = $key." = ".((int) $value);
1908  } elseif (strpos($key, 'date') !== false) {
1909  $sqlwhere[] = $key." = '".$this->db->idate($value)."'";
1910  } elseif ($key == 'customsql') {
1911  $sqlwhere[] = $value;
1912  } else {
1913  $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'";
1914  }
1915  }
1916  }
1917  if (count($sqlwhere) > 0) {
1918  $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')';
1919  }
1920 
1921  if (!empty($sortfield)) {
1922  $sql .= $this->db->order($sortfield, $sortorder);
1923  }
1924  if (!empty($limit)) {
1925  $sql .= $this->db->plimit($limit, $offset);
1926  }
1927 
1928  $resql = $this->db->query($sql);
1929  if ($resql) {
1930  $num = $this->db->num_rows($resql);
1931  $i = 0;
1932  while ($i < ($limit ? min($limit, $num) : $num)) {
1933  $obj = $this->db->fetch_object($resql);
1934 
1935  $record = new self($this->db);
1936  $record->setVarsFromFetchObj($obj);
1937 
1938  $records[$record->id] = $record;
1939 
1940  $i++;
1941  }
1942  $this->db->free($resql);
1943 
1944  return $records;
1945  } else {
1946  $this->errors[] = 'Error '.$this->db->lasterror();
1947  dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
1948 
1949  return -1;
1950  }
1951  }
1952 
1960  public function update(User $user, $notrigger = false)
1961  {
1962  return $this->updateCommon($user, $notrigger);
1963  }
1964 
1972  public function delete(User $user, $notrigger = false)
1973  {
1974  return $this->deleteCommon($user, $notrigger);
1975  //return $this->deleteCommon($user, $notrigger, 1);
1976  }
1977 }
$object ref
Definition: info.php:78
Class for BOM.
Definition: bom.class.php:43
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.
getFieldList($alias='')
Function to concat keys of fields.
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.
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:635
fetchLinesLinked($role, $lineid=0)
Get list of lines linked to current line for a defined role.
Definition: mo.class.php:549
getMoChilds()
Function used to return childs of Mo.
Definition: mo.class.php:1624
static replaceThirdparty($db, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
Definition: mo.class.php:1611
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:1496
fetchLines()
Load object lines in memory from the database.
Definition: mo.class.php:455
getNextNumRef($prod)
Returns the reference to the following non used MO depending on the active numbering module defined i...
Definition: mo.class.php:927
deleteLine(User $user, $idline, $notrigger=false)
Delete a line of object in database.
Definition: mo.class.php:842
cancel($user, $notrigger=0)
Set cancel status.
Definition: mo.class.php:1118
fetch($id, $ref=null)
Load object in memory from the database.
Definition: mo.class.php:438
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
Definition: mo.class.php:1386
reopen($user, $notrigger=0)
Set back to validated status.
Definition: mo.class.php:1142
updateProduction(User $user, $notrigger=true)
Update quantities in lines to consume and to produce.
Definition: mo.class.php:780
getMoParent()
Function used to return childs of Mo.
Definition: mo.class.php:1662
getLinesArray($rolefilter='')
Create an array of lines.
Definition: mo.class.php:1399
LibStatut($status, $mode=0)
Return the status.
Definition: mo.class.php:1314
setDraft($user, $notrigger=0)
Set draft status.
Definition: mo.class.php:1094
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:1568
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:475
getKanbanView($option='', $arraydata=null)
Return clicable link of object (with eventually picto)
Definition: mo.class.php:1699
validate($user, $notrigger=0)
Validate Mo.
Definition: mo.class.php:975
doScheduledJob()
Action executed by scheduler CAN BE A CRON TASK.
Definition: mo.class.php:1463
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
Definition: mo.class.php:1430
getTooltipContentArray($params)
getTooltipContentArray
Definition: mo.class.php:1166
createProduction(User $user, $notrigger=true)
Erase and update the line to consume and to produce.
Definition: mo.class.php:671
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:1215
getLibStatut($mode=0)
Return label of the status.
Definition: mo.class.php:1301
info($id)
Load the info information in the object.
Definition: mo.class.php:1356
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:600
createFromClone(User $user, $fromid)
Clone an object into another one.
Definition: mo.class.php:350
Class MoLine.
Definition: mo.class.php:1737
create(User $user, $notrigger=false)
Create object into database.
Definition: mo.class.php:1852
update(User $user, $notrigger=false)
Update object into database.
Definition: mo.class.php:1960
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:1886
__construct(DoliDB $db)
Constructor.
Definition: mo.class.php:1813
fetch($id, $ref=null)
Load object in memory from the database.
Definition: mo.class.php:1869
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.