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
27require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
28require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
29
33class 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.
static replaceThirdparty($db, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
printOriginLinesList($restrictlist='', $selectedLines=array())
Return HTML table table of source object lines TODO Move this and previous function into output html ...
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.
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.
reopen($user, $notrigger=0)
Set back to validated status.
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.
getLinesArray($rolefilter='')
Create an array of lines.
LibStatut($status, $mode=0)
Return the status.
setDraft($user, $notrigger=0)
Set draft status.
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...
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)
validate($user, $notrigger=0)
Validate Mo.
Definition mo.class.php:989
doScheduledJob()
Action executed by scheduler CAN BE A CRON TASK.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
getTooltipContentArray($params)
getTooltipContentArray
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)
getLibStatut($mode=0)
Return label of the status.
info($id)
Load the info information in the object.
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.
create(User $user, $notrigger=false)
Create object into database.
update(User $user, $notrigger=false)
Update object into database.
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, array $filter=array(), $filtermode='AND')
Load list of objects in memory from the database.
__construct(DoliDB $db)
Constructor.
fetch($id, $ref=null)
Load object in memory from the database.
Class to manage stock movements.
Class to manage products or services.
Class to manage Dolibarr users.
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)
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.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.