dolibarr 19.0.3
stocktransfer.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2021 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
4 * Copyright (C) 2022 Frédéric France <frederic.france@netlogic.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/commonincoterm.class.php';
29
30//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
31//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
32
37{
42 public $element = 'stocktransfer';
43
47 public $table_element = 'stocktransfer_stocktransfer';
48
52 public $table_element_line = 'stocktransfer_stocktransferline';
53
58 public $ismultientitymanaged = 0;
59
63 public $isextrafieldmanaged = 1;
64
68 public $fk_element = 'fk_stocktransfer';
69
75 protected $childtablesoncascade = array('stocktransfer_stocktransferline');
76
82 public $ref_client;
83
87 public $ref_customer;
88
89
93 public $picto = 'stock';
94
95 public $date_prevue_depart;
96 public $date_prevue_arrivee;
97 public $date_reelle_depart;
98 public $date_reelle_arrivee;
99 public $origin_type;
100
101
102 const STATUS_DRAFT = 0;
103 const STATUS_VALIDATED = 1;
104 const STATUS_TRANSFERED = 2;
105 const STATUS_CLOSED = 3;
106
107
133 // BEGIN MODULEBUILDER PROPERTIES
137 public $fields=array(
138 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'comment'=>"Id"),
139 'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>'1', 'position'=>1, 'default'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'comment'=>"Id"),
140 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>4, 'noteditable'=>'1', 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'comment'=>"Reference of object"),
141 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>0, 'visible'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'css'=>'minwidth100', 'csslist'=>'tdoverflowmax125', 'autofocusoncreate'=>1),
142 'description' => array('type'=>'text', 'label'=>'Description', 'enabled'=>'1', 'position'=>31, 'notnull'=>0, 'visible'=>3,),
143 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1', 'label'=>'Project', 'enabled'=>'$conf->project->enabled', 'position'=>32, 'notnull'=>-1, 'visible'=>-1, 'index'=>1, 'picto'=>'project', 'css'=>'maxwidth500 widthcentpercentminusxx', 'csslist'=>'tdoverflowmax125'),
144 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))', 'label'=>'ThirdParty', 'enabled'=>'1', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1/*, 'help'=>"LinkToThirdparty"*/, 'picto'=>'company', 'css'=>'maxwidth500 widthcentpercentminusxx', 'csslist'=>'tdoverflowmax125'),
145 'fk_warehouse_source' => array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php', 'label'=>'Entrepôt source', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1, 'help'=>'HelpWarehouseStockTransferSource', 'picto'=>'stock', 'css'=>'maxwidth500 widthcentpercentminusxx', 'csslist'=>'tdoverflowmax150'),
146 'fk_warehouse_destination' => array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php', 'label'=>'Entrepôt de destination', 'enabled'=>'1', 'position'=>51, 'notnull'=>0, 'visible'=>1, 'help'=>'HelpWarehouseStockTransferDestination', 'picto'=>'stock', 'css'=>'maxwidth500 widthcentpercentminusxx', 'csslist'=>'tdoverflowmax150'),
147 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>61, 'notnull'=>0, 'visible'=>0,),
148 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>0,),
149 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,),
150 'date_prevue_depart' => array('type'=>'date', 'label'=>'DatePrevueDepart', 'enabled'=>'1', 'position'=>100, 'notnull'=>0, 'visible'=>1,),
151 'date_reelle_depart' => array('type'=>'date', 'label'=>'DateReelleDepart', 'enabled'=>'1', 'position'=>101, 'notnull'=>0, 'visible'=>5,),
152 'date_prevue_arrivee' => array('type'=>'date', 'label'=>'DatePrevueArrivee', 'enabled'=>'1', 'position'=>102, 'notnull'=>0, 'visible'=>1,),
153 'date_reelle_arrivee' => array('type'=>'date', 'label'=>'DateReelleArrivee', 'enabled'=>'1', 'position'=>103, 'notnull'=>0, 'visible'=>5,),
154 'lead_time_for_warning' => array('type'=>'integer', 'label'=>'LeadTimeForWarning', 'enabled'=>'1', 'position'=>200, 'default'=>0, 'notnull'=>0, 'visible'=>1),
155 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,),
156 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid',),
157 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'ChangedBy', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,),
158 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,),
159 'model_pdf' => array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>'1', 'position'=>1010, 'notnull'=>-1, 'visible'=>0,),
160 'fk_incoterms' => array('type'=>'integer', 'label'=>'IncotermCode', 'enabled'=>'$conf->incoterm->enabled', 'visible'=>-2, 'position'=>220),
161 'location_incoterms' => array('type'=>'varchar(255)', 'label'=>'IncotermLabel', 'enabled'=>'$conf->incoterm->enabled', 'visible'=>-2, 'position'=>225),
162 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'notnull'=>1, 'visible'=>5, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Draft', '1'=>'Validated', '2'=>'StockStransferDecremented', '3'=>'StockStransferIncremented'),),
163 );
164 public $rowid;
165 public $ref;
166 public $label;
167 public $socid;
168 public $fk_soc; // deprecated
169 public $fk_project;
170 public $description;
171 public $note_public;
172 public $note_private;
173 public $date_creation;
174 public $tms;
175 public $lead_time_for_warning;
176 public $fk_user_creat;
177 public $fk_user_modif;
178 public $import_key;
179 public $model_pdf;
180 public $status;
181
185 public $lines;
186
187 public $fk_warehouse_source;
188 public $fk_warehouse_destination;
189 // END MODULEBUILDER PROPERTIES
190
191
197 public function __construct(DoliDB $db)
198 {
199 global $conf, $langs;
200
201 $this->db = $db;
202 $this->origin_type = 'StockTransfer@product/stock/stocktransfer';
203
204 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
205 $this->fields['rowid']['visible'] = 0;
206 }
207 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
208 $this->fields['entity']['enabled'] = 0;
209 }
210
211 // Example to show how to set values of fields definition dynamically
212 /*if ($user->rights->stocktransfer->stocktransfer->read) {
213 $this->fields['myfield']['visible'] = 1;
214 $this->fields['myfield']['noteditable'] = 0;
215 }*/
216
217 // Unset fields that are disabled
218 foreach ($this->fields as $key => $val) {
219 if (isset($val['enabled']) && empty($val['enabled'])) {
220 unset($this->fields[$key]);
221 }
222 }
223
224 // Translate some data of arrayofkeyval
225 if (is_object($langs)) {
226 foreach ($this->fields as $key => $val) {
227 if (isset($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
228 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
229 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
230 }
231 }
232 }
233 }
234 }
235
243 public function create(User $user, $notrigger = false)
244 {
245 $model_pdf = GETPOST('model');
246 if (!empty($model_pdf)) {
247 $this->model_pdf = $model_pdf;
248 }
249 $this->status = (int) $this->status;
250 if ($this->fk_warehouse_source <= 0) {
251 $this->fk_warehouse_source = 0;
252 }
253 if ($this->fk_warehouse_destination <= 0) {
254 $this->fk_warehouse_destination = 0;
255 }
256 return $this->createCommon($user, $notrigger);
257 }
258
266 public function createFromClone(User $user, $fromid)
267 {
268 global $langs, $extrafields;
269 $error = 0;
270
271 dol_syslog(__METHOD__, LOG_DEBUG);
272
273 $object = new self($this->db);
274
275 $this->db->begin();
276
277 // Load source object
278 $result = $object->fetchCommon($fromid);
279 if ($result > 0 && !empty($object->table_element_line)) {
280 $object->fetchLines();
281 }
282
283 // get lines so they will be clone
284 //foreach($this->lines as $line)
285 // $line->fetch_optionals();
286
287 // Reset some properties
288 unset($object->id);
289 unset($object->fk_user_creat);
290 unset($object->import_key);
291 unset($object->date_prevue_depart);
292 unset($object->date_prevue_arrivee);
293 unset($object->date_reelle_depart);
294 unset($object->date_reelle_arrivee);
295
296
297 // Clear fields
298 $object->ref = empty($this->fields['ref']['default']) ? "copy_of_".$object->ref : $this->fields['ref']['default'];
299 $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
300 $object->status = self::STATUS_DRAFT;
301 // ...
302 // Clear extrafields that are unique
303 if (is_array($object->array_options) && count($object->array_options) > 0) {
304 $extrafields->fetch_name_optionals_label($this->table_element);
305 foreach ($object->array_options as $key => $option) {
306 $shortkey = preg_replace('/options_/', '', $key);
307 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
308 //var_dump($key); var_dump($clonedObj->array_options[$key]); exit;
309 unset($object->array_options[$key]);
310 }
311 }
312 }
313
314 // Create clone
315 $object->context['createfromclone'] = 'createfromclone';
316 $result = $object->createCommon($user);
317 if ($result < 0) {
318 $error++;
319 $this->error = $object->error;
320 $this->errors = $object->errors;
321 }
322
323 if (!$error) {
324 // copy internal contacts
325 if ($this->copy_linked_contact($object, 'internal') < 0) {
326 $error++;
327 }
328 }
329
330 if (!$error) {
331 // copy external contacts if same company
332 if (property_exists($this, 'socid') && $this->socid == $object->socid) {
333 if ($this->copy_linked_contact($object, 'external') < 0) {
334 $error++;
335 }
336 }
337 }
338
339 unset($object->context['createfromclone']);
340
341 // End
342 if (!$error) {
343 $this->db->commit();
344 return $object;
345 } else {
346 $this->db->rollback();
347 return -1;
348 }
349 }
350
358 public function fetch($id, $ref = null)
359 {
360 $result = $this->fetchCommon($id, $ref);
361
362 $this->socid = $this->fk_soc;
363
364 if ($result > 0 && !empty($this->table_element_line)) {
365 $this->fetchLines();
366 }
367 return $result;
368 }
369
375 public function fetchLines()
376 {
377 require_once DOL_DOCUMENT_ROOT . '/product/stock/stocktransfer/class/stocktransferline.class.php';
378 $this->lines = array();
379
380 $result = $this->fetchLinesCommon();
381 usort($this->lines, array('StockTransfer', 'stocktransferCmpRank'));
382 return $result;
383 }
384
392 public static function stocktransferCmpRank($a, $b)
393 {
394 if ($a->rang == $b->rang) {
395 return 0;
396 }
397 return ($a->rang < $b->rang) ? -1 : 1;
398 }
399
405 public function getValorisationTotale()
406 {
407 $total_pmp = 0;
408
409 if (empty($this->lines)) {
410 $this->fetchLines();
411 }
412 if (!empty($this->lines)) {
413 foreach ($this->lines as $l) {
414 $total_pmp+= ($l->pmp * $l->qty);
415 }
416 }
417
418 return $total_pmp;
419 }
420
432 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
433 {
434 global $conf;
435
436 dol_syslog(__METHOD__, LOG_DEBUG);
437
438 $records = array();
439
440 $sql = 'SELECT ';
441 $sql .= $this->getFieldList();
442 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
443 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
444 $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
445 } else {
446 $sql .= ' WHERE 1 = 1';
447 }
448 // Manage filter
449 $sqlwhere = array();
450 if (count($filter) > 0) {
451 foreach ($filter as $key => $value) {
452 if ($key == 't.rowid') {
453 $sqlwhere[] = $key.'='.$value;
454 } elseif (strpos($key, 'date') !== false) {
455 $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\'';
456 } elseif ($key == 'customsql') {
457 $sqlwhere[] = $value;
458 } else {
459 $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\'';
460 }
461 }
462 }
463 if (count($sqlwhere) > 0) {
464 $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")";
465 }
466
467 if (!empty($sortfield)) {
468 $sql .= $this->db->order($sortfield, $sortorder);
469 }
470 if (!empty($limit)) {
471 $sql .= ' '.$this->db->plimit($limit, $offset);
472 }
473
474 $resql = $this->db->query($sql);
475 if ($resql) {
476 $num = $this->db->num_rows($resql);
477 $i = 0;
478 while ($i < ($limit ? min($limit, $num) : $num)) {
479 $obj = $this->db->fetch_object($resql);
480
481 $record = new self($this->db);
482 $record->setVarsFromFetchObj($obj);
483
484 $records[$record->id] = $record;
485
486 $i++;
487 }
488 $this->db->free($resql);
489
490 return $records;
491 } else {
492 $this->errors[] = 'Error '.$this->db->lasterror();
493 dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
494
495 return -1;
496 }
497 }
498
506 public function update(User $user, $notrigger = false)
507 {
508 $this->tms = ''; // Will be done automatically because tms field is on update cascade
509 $res = $this->updateCommon($user, $notrigger);
510 if (($this->socid > 0 || $this->fk_soc > 0) && empty($this->thirdparty)) {
511 $this->fetch_thirdparty();
512 }
513 if (empty($this->socid) && empty($this->fk_soc)) {
514 unset($this->thirdparty);
515 }
516 return $res;
517 }
518
526 public function delete(User $user, $notrigger = false)
527 {
528 if ($this->status > self::STATUS_VALIDATED) {
529 return 0;
530 } else {
531 return $this->deleteCommon($user, $notrigger);
532 }
533 }
534
543 public function deleteLine(User $user, $idline, $notrigger = false)
544 {
545 if ($this->status < 0) {
546 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
547 return -2;
548 }
549
550 $res = $this->deleteLineCommon($user, $idline, $notrigger);
551 $this->line_order(true);
552 return $res;
553 }
554
555
563 public function validate($user, $notrigger = 0)
564 {
565 global $conf, $langs;
566
567 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
568
569 $error = 0;
570
571 // Protection
572 if ($this->status == self::STATUS_VALIDATED) {
573 dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING);
574 return 0;
575 }
576
577 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer->write))
578 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer->stocktransfer_advance->validate))))
579 {
580 $this->error='NotEnoughPermissions';
581 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
582 return -1;
583 }*/
584
585 $now = dol_now();
586
587 $this->db->begin();
588
589 // Define new ref
590 if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
591 $num = $this->getNextNumRef();
592 } else {
593 $num = $this->ref;
594 }
595 $this->newref = $num;
596
597 if (!empty($num)) {
598 // Validate
599 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
600 $sql .= " SET ref = '".$this->db->escape($num)."',";
601 $sql .= " status = ".self::STATUS_VALIDATED;
602 if (!empty($this->fields['date_validation'])) {
603 $sql .= ", date_validation = '".$this->db->idate($now)."',";
604 }
605 if (!empty($this->fields['fk_user_valid'])) {
606 $sql .= ", fk_user_valid = ".((int) $user->id);
607 }
608 $sql .= " WHERE rowid = ".((int) $this->id);
609
610 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
611 $resql = $this->db->query($sql);
612 if (!$resql) {
613 dol_print_error($this->db);
614 $this->error = $this->db->lasterror();
615 $error++;
616 }
617
618 if (!$error && !$notrigger) {
619 // Call trigger
620 $result = $this->call_trigger('STOCKTRANSFER_VALIDATE', $user);
621 if ($result < 0) {
622 $error++;
623 }
624 // End call triggers
625 }
626 }
627
628 if (!$error) {
629 $this->oldref = $this->ref;
630
631 // Rename directory if dir was a temporary ref
632 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
633 // Now we rename also files into index
634 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'stocktransfer/".$this->db->escape($this->newref)."'";
635 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'stocktransfer/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
636 $resql = $this->db->query($sql);
637 if (!$resql) {
638 $error++;
639 $this->error = $this->db->lasterror();
640 }
641 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'stocktransfer/".$this->db->escape($this->newref)."'";
642 $sql .= " WHERE filepath = 'stocktransfer/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
643 $resql = $this->db->query($sql);
644 if (!$resql) {
645 $error++;
646 $this->error = $this->db->lasterror();
647 }
648
649 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
650 $oldref = dol_sanitizeFileName($this->ref);
651 $newref = dol_sanitizeFileName($num);
652 $dirsource = $conf->stocktransfer->dir_output.'/stocktransfer/'.$oldref;
653 $dirdest = $conf->stocktransfer->dir_output.'/stocktransfer/'.$newref;
654 if (!$error && file_exists($dirsource)) {
655 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
656
657 if (@rename($dirsource, $dirdest)) {
658 dol_syslog("Rename ok");
659 // Rename docs starting with $oldref with $newref
660 $listoffiles = dol_dir_list($conf->stocktransfer->dir_output.'/stocktransfer/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
661 foreach ($listoffiles as $fileentry) {
662 $dirsource = $fileentry['name'];
663 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
664 $dirsource = $fileentry['path'].'/'.$dirsource;
665 $dirdest = $fileentry['path'].'/'.$dirdest;
666 @rename($dirsource, $dirdest);
667 }
668 }
669 }
670 }
671 }
672
673 // Set new ref and current status
674 if (!$error) {
675 $this->ref = $num;
676 $this->status = self::STATUS_VALIDATED;
677 }
678
679 if (!$error) {
680 $this->db->commit();
681 return 1;
682 } else {
683 $this->db->rollback();
684 return -1;
685 }
686 }
687
688
696 public function setDraft($user, $notrigger = 0)
697 {
698 // Protection
699 if ($this->status <= self::STATUS_DRAFT) {
700 return 0;
701 }
702
703 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->write))
704 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer_advance->validate))))
705 {
706 $this->error='Permission denied';
707 return -1;
708 }*/
709
710 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'STOCKTRANSFER_UNVALIDATE');
711 }
712
720 public function cancel($user, $notrigger = 0)
721 {
722 // Protection
723 if ($this->status != self::STATUS_VALIDATED) {
724 return 0;
725 }
726
727 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->write))
728 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer_advance->validate))))
729 {
730 $this->error='Permission denied';
731 return -1;
732 }*/
733
734 return $this->setStatusCommon($user, self::STATUS_CLOSED, $notrigger, 'STOCKTRANSFER_CLOSE');
735 }
736
744 public function reopen($user, $notrigger = 0)
745 {
746 // Protection
747 if ($this->status != self::STATUS_CLOSED) {
748 return 0;
749 }
750
751 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->write))
752 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer_advance->validate))))
753 {
754 $this->error='Permission denied';
755 return -1;
756 }*/
757
758 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'STOCKTRANSFER_REOPEN');
759 }
760
771 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
772 {
773 global $conf, $langs, $hookmanager;
774
775 if (!empty($conf->dol_no_mouse_hover)) {
776 $notooltip = 1;
777 } // Force disable tooltips
778
779 $result = '';
780
781 $label = '<u>'.$langs->trans("StockTransfer").'</u>';
782 $label .= '<br>';
783 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
784 if (isset($this->status)) {
785 $label .= '<br><b>'.$langs->trans("Status").":</b> ".$this->getLibStatut(5);
786 }
787
788 $url = dol_buildpath('/product/stock/stocktransfer/stocktransfer_card.php', 1).'?id='.$this->id;
789
790 if ($option != 'nolink') {
791 // Add param to save lastsearch_values or not
792 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
793 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
794 $add_save_lastsearch_values = 1;
795 }
796 if ($add_save_lastsearch_values) {
797 $url .= '&save_lastsearch_values=1';
798 }
799 }
800
801 $linkclose = '';
802 if (empty($notooltip)) {
803 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
804 $label = $langs->trans("ShowStockTransfer");
805 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
806 }
807 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
808 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
809 } else {
810 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
811 }
812
813 $linkstart = '<a href="'.$url.'"';
814 $linkstart .= $linkclose.'>';
815 $linkend = '</a>';
816
817 $result .= $linkstart;
818
819 if (empty($this->showphoto_on_popup)) {
820 if ($withpicto) {
821 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
822 }
823 } else {
824 if ($withpicto) {
825 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
826
827 list($class, $module) = explode('@', $this->picto);
828 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
829 $filearray = dol_dir_list($upload_dir, "files");
830 $filename = $filearray[0]['name'];
831 if (!empty($filename)) {
832 $pospoint = strpos($filearray[0]['name'], '.');
833
834 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
835 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
836 $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo'.$module.'" alt="No photo" border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$module.'&entity='.$conf->entity.'&file='.urlencode($pathtophoto).'"></div></div>';
837 } else {
838 $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photouserphoto userphoto" alt="No photo" border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$module.'&entity='.$conf->entity.'&file='.urlencode($pathtophoto).'"></div>';
839 }
840
841 $result .= '</div>';
842 } else {
843 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
844 }
845 }
846 }
847
848 if ($withpicto != 2) {
849 $result .= $this->ref;
850 }
851
852 $result .= $linkend;
853 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
854
855 global $action, $hookmanager;
856 $hookmanager->initHooks(array('stocktransferdao'));
857 $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
858 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
859 if ($reshook > 0) {
860 $result = $hookmanager->resPrint;
861 } else {
862 $result .= $hookmanager->resPrint;
863 }
864
865 return $result;
866 }
867
874 public function getLibStatut($mode = 0)
875 {
876 return $this->LibStatut($this->status, $mode);
877 }
878
879 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
887 public function LibStatut($status, $mode = 0)
888 {
889 // phpcs:enable
890 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
891 global $langs;
892 //$langs->load("stocktransfer@stocktransfer");
893 $this->labelStatus[self::STATUS_DRAFT] = $langs->trans('Draft');
894 $this->labelStatus[self::STATUS_VALIDATED] = $langs->trans('Validated');
895 $this->labelStatus[self::STATUS_TRANSFERED] = $langs->trans('StockStransferDecremented');
896 $this->labelStatus[self::STATUS_CLOSED] = $langs->trans('StockStransferIncremented');
897 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->trans('Draft');
898 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->trans('Validated');
899 $this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->trans('StockStransferDecremented');
900 $this->labelStatusShort[self::STATUS_CLOSED] = $langs->trans('StockStransferIncremented');
901 }
902
903 $statusType = 'status'.$status;
904 //if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
905 if ($status == self::STATUS_CLOSED) {
906 $statusType = 'status6';
907 }
908
909 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
910 }
911
918 public function info($id)
919 {
920 $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
921 $sql .= ' fk_user_creat, fk_user_modif';
922 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
923 $sql .= ' WHERE t.rowid = '.((int) $id);
924 $result = $this->db->query($sql);
925 if ($result) {
926 if ($this->db->num_rows($result)) {
927 $obj = $this->db->fetch_object($result);
928 $this->id = $obj->rowid;
929
930 $this->user_creation_id = $obj->fk_user_creat;
931 $this->user_modification_id = $obj->fk_user_modif;
932 $this->date_creation = $this->db->jdate($obj->datec);
933 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
934 }
935
936 $this->db->free($result);
937 } else {
938 dol_print_error($this->db);
939 }
940 }
941
948 public function initAsSpecimen()
949 {
950 $this->initAsSpecimenCommon();
951 }
952
958 public function getLinesArray()
959 {
960 $this->lines = array();
961
962 $objectline = new StockTransferLine($this->db);
963 $result = $objectline->fetchAll('ASC', 'rang', 0, 0, array('customsql'=>'fk_stocktransfer = '.$this->id));
964
965 if (is_numeric($result)) {
966 $this->error = $objectline->error;
967 $this->errors = $objectline->errors;
968 return $result;
969 } else {
970 $this->lines = $result;
971 return $this->lines;
972 }
973 }
974
980 public function getNextNumRef()
981 {
982 global $langs, $conf;
983 $langs->load("stocks");
984
985 if (!getDolGlobalString('STOCKTRANSFER_STOCKTRANSFER_ADDON')) {
986 $conf->global->STOCKTRANSFER_STOCKTRANSFER_ADDON = 'mod_stocktransfer_standard';
987 }
988
989 if (getDolGlobalString('STOCKTRANSFER_STOCKTRANSFER_ADDON')) {
990 $mybool = false;
991
992 $file = getDolGlobalString('STOCKTRANSFER_STOCKTRANSFER_ADDON') . ".php";
993 $classname = $conf->global->STOCKTRANSFER_STOCKTRANSFER_ADDON;
994
995 // Include file with class
996 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
997 foreach ($dirmodels as $reldir) {
998 $dir = dol_buildpath($reldir."core/modules/stocktransfer/");
999
1000 // Load file with numbering class (if found)
1001 $mybool |= @include_once $dir.$file;
1002 }
1003
1004 if ($mybool === false) {
1005 dol_print_error('', "Failed to include file ".$file);
1006 return '';
1007 }
1008
1009 if (class_exists($classname)) {
1010 $obj = new $classname();
1011 $numref = $obj->getNextValue($this);
1012
1013 if ($numref != '' && $numref != '-1') {
1014 return $numref;
1015 } else {
1016 $this->error = $obj->error;
1017 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1018 return "";
1019 }
1020 } else {
1021 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1022 return "";
1023 }
1024 } else {
1025 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1026 return "";
1027 }
1028 }
1029
1041 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1042 {
1043 global $conf, $langs;
1044
1045 $result = 0;
1046 $includedocgeneration = 1;
1047
1048 $langs->load("stocks");
1049
1050 if (!dol_strlen($modele)) {
1051 $modele = 'eagle';
1052
1053 if ($this->model_pdf) {
1054 $modele = $this->model_pdf;
1055 } elseif (getDolGlobalString('STOCKTRANSFER_ADDON_PDF')) {
1056 $modele = $conf->global->STOCKTRANSFER_ADDON_PDF;
1057 }
1058 }
1059
1060 $modelpath = "core/modules/stocktransfer/doc/";
1061
1062 if ($includedocgeneration) {
1063 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1064 }
1065
1066 return $result;
1067 }
1068
1076 public function doScheduledJob()
1077 {
1078 global $conf, $langs;
1079
1080 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1081
1082 $error = 0;
1083 $this->output = '';
1084 $this->error = '';
1085
1086 dol_syslog(__METHOD__, LOG_DEBUG);
1087
1088 $now = dol_now();
1089
1090 $this->db->begin();
1091
1092 // ...
1093
1094 $this->db->commit();
1095
1096 return $error;
1097 }
1098}
1099
1103//class StockTransferLine
1104//{
1105// // To complete with content of an object StockTransferLine
1106// // We should have a field rowid, fk_stocktransfer and position
1107//
1108// /**
1109// * @var int Does object support extrafields ? 0=No, 1=Yes
1110// */
1111// public $isextrafieldmanaged = 0;
1112//
1113// /**
1114// * Constructor
1115// *
1116// * @param DoliDb $db Database handler
1117// */
1118// public function __construct(DoliDB $db)
1119// {
1120// $this->db = $db;
1121// }
1122//}
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Definition security.php:604
$object ref
Definition info.php:79
Parent class of all other business classes (invoices, contracts, proposals, orders,...
line_order($renum=false, $rowidorder='ASC', $fk_parent_line=true)
Save a new position (field rang) for details lines.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty.
deleteLineCommon(User $user, $idline, $notrigger=false)
Delete a line of object in 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.
updateCommon(User $user, $notrigger=false)
Update object into database.
fetchLinesCommon($morewhere='', $noextrafields=0)
Load object in memory from the database.
fetchCommon($id, $ref=null, $morewhere='', $noextrafields=0)
Load object in memory from the database.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage Dolibarr database access.
Class for StockTransfer.
getValorisationTotale()
Used to get total PMP amount of all quantities of products of Stock Transfer.
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, array $filter=array(), $filtermode='AND')
Load list of objects in memory from the database.
static stocktransferCmpRank($a, $b)
Used to sort lines by rank.
fetch($id, $ref=null)
Load object in memory from the database.
LibStatut($status, $mode=0)
Return the status.
deleteLine(User $user, $idline, $notrigger=false)
Delete a line of object in database.
fetchLines()
Load object lines in memory from the database.
validate($user, $notrigger=0)
Validate object.
create(User $user, $notrigger=false)
Create object into database.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
doScheduledJob()
Action executed by scheduler CAN BE A CRON TASK.
setDraft($user, $notrigger=0)
Set draft status.
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.
getLibStatut($mode=0)
Return label of the status.
info($id)
Load the info information in the object.
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionaly the picto)
getNextNumRef()
Returns the reference to the following non used object depending on the active numbering module.
__construct(DoliDB $db)
Constructor.
createFromClone(User $user, $fromid)
Clone an object into another one.
getLinesArray()
Create an array of lines.
cancel($user, $notrigger=0)
Set cancel status.
update(User $user, $notrigger=false)
Update object into database.
Class for StockTransferLine.
Class to manage Dolibarr users.
trait CommonIncoterm
Superclass for incoterm classes.
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
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.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
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.