dolibarr 21.0.0-alpha
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-2024 Frédéric France <frederic.france@free.fr>
5 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
27// Put here all includes required by your class file
28require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
29require_once DOL_DOCUMENT_ROOT.'/core/class/commonincoterm.class.php';
30
31//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
32//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
33
38{
39 use CommonIncoterm;
43 public $element = 'stocktransfer';
44
48 public $table_element = 'stocktransfer_stocktransfer';
49
53 public $table_element_line = 'stocktransfer_stocktransferline';
54
58 public $fk_element = 'fk_stocktransfer';
59
65 protected $childtablesoncascade = array('stocktransfer_stocktransferline');
66
72 public $ref_client;
73
77 public $ref_customer;
78
82 public $picto = 'stock';
83
87 public $date_prevue_depart;
88
92 public $date_prevue_arrivee;
93
97 public $date_reelle_depart;
98
102 public $date_reelle_arrivee;
103
107 public $origin_type;
108
109
110 const STATUS_DRAFT = 0;
111 const STATUS_VALIDATED = 1;
112 const STATUS_TRANSFERED = 2;
113 const STATUS_CLOSED = 3;
114
115
141 // BEGIN MODULEBUILDER PROPERTIES
145 public $fields = array(
146 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'comment' => "Id"),
147 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'position' => 1, 'default' => '1', 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'comment' => "Id"),
148 '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"),
149 '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),
150 'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'position' => 31, 'notnull' => 0, 'visible' => 3,),
151 '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'),
152 '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'),
153 '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'),
154 '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'),
155 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 61, 'notnull' => 0, 'visible' => 0,),
156 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 62, 'notnull' => 0, 'visible' => 0,),
157 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2,),
158 'date_prevue_depart' => array('type' => 'date', 'label' => 'DatePrevueDepart', 'enabled' => 1, 'position' => 100, 'notnull' => 0, 'visible' => 1,),
159 'date_reelle_depart' => array('type' => 'date', 'label' => 'DateReelleDepart', 'enabled' => 1, 'position' => 101, 'notnull' => 0, 'visible' => 5,),
160 'date_prevue_arrivee' => array('type' => 'date', 'label' => 'DatePrevueArrivee', 'enabled' => 1, 'position' => 102, 'notnull' => 0, 'visible' => 1,),
161 'date_reelle_arrivee' => array('type' => 'date', 'label' => 'DateReelleArrivee', 'enabled' => 1, 'position' => 103, 'notnull' => 0, 'visible' => 5,),
162 'lead_time_for_warning' => array('type' => 'integer', 'label' => 'LeadTimeForWarning', 'enabled' => 1, 'position' => 200, 'default' => '0', 'notnull' => 0, 'visible' => 1),
163 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2,),
164 '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',),
165 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'ChangedBy', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2,),
166 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,),
167 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0,),
168 'fk_incoterms' => array('type' => 'integer', 'label' => 'IncotermCode', 'enabled' => '$conf->incoterm->enabled', 'visible' => -2, 'position' => 220),
169 'location_incoterms' => array('type' => 'varchar(255)', 'label' => 'IncotermLabel', 'enabled' => '$conf->incoterm->enabled', 'visible' => -2, 'position' => 225),
170 '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'),),
171 );
175 public $rowid;
179 public $ref;
183 public $label;
184
188 public $description;
189
193 public $socid;
194
199 public $fk_soc;
203 public $lead_time_for_warning;
207 public $status;
208
212 public $lines;
213
217 public $fk_warehouse_source;
218
222 public $fk_warehouse_destination;
223 // END MODULEBUILDER PROPERTIES
224
225
231 public function __construct(DoliDB $db)
232 {
233 global $conf, $langs;
234
235 $this->db = $db;
236
237 $this->ismultientitymanaged = 0;
238 $this->isextrafieldmanaged = 1;
239
240 $this->origin_type = 'StockTransfer@product/stock/stocktransfer';
241
242 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
243 $this->fields['rowid']['visible'] = 0;
244 }
245 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
246 $this->fields['entity']['enabled'] = 0;
247 }
248
249 // Example to show how to set values of fields definition dynamically
250 /*if ($user->rights->stocktransfer->stocktransfer->read) {
251 $this->fields['myfield']['visible'] = 1;
252 $this->fields['myfield']['noteditable'] = 0;
253 }*/
254
255 // Unset fields that are disabled
256 foreach ($this->fields as $key => $val) {
257 if (isset($val['enabled']) && empty($val['enabled'])) {
258 unset($this->fields[$key]);
259 }
260 }
261
262 // Translate some data of arrayofkeyval
263 if (is_object($langs)) {
264 foreach ($this->fields as $key => $val) {
265 if (isset($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
266 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
267 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
268 }
269 }
270 }
271 }
272 }
273
281 public function create(User $user, $notrigger = 0)
282 {
283 $this->status = (int) $this->status;
284 if ($this->fk_warehouse_source <= 0) {
285 $this->fk_warehouse_source = 0;
286 }
287 if ($this->fk_warehouse_destination <= 0) {
288 $this->fk_warehouse_destination = 0;
289 }
290 return $this->createCommon($user, $notrigger);
291 }
292
300 public function createFromClone(User $user, $fromid)
301 {
302 global $langs, $extrafields;
303 $error = 0;
304
305 dol_syslog(__METHOD__, LOG_DEBUG);
306
307 $object = new self($this->db);
308
309 $this->db->begin();
310
311 // Load source object
312 $result = $object->fetchCommon($fromid);
313 if ($result > 0 && !empty($object->table_element_line)) {
314 $object->fetchLines();
315 }
316
317 // get lines so they will be clone
318 //foreach($this->lines as $line)
319 // $line->fetch_optionals();
320
321 // Reset some properties
322 unset($object->id);
323 unset($object->fk_user_creat);
324 unset($object->import_key);
325 unset($object->date_prevue_depart);
326 unset($object->date_prevue_arrivee);
327 unset($object->date_reelle_depart);
328 unset($object->date_reelle_arrivee);
329
330
331 // Clear fields
332 // @phan-suppress-next-line PhanTypeMismatchProperty
333 $object->ref = empty($this->fields['ref']['default']) ? "copy_of_".$object->ref : $this->fields['ref']['default'];
334 // @phan-suppress-next-line PhanTypeInvalidDimOffset
335 $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
336 $object->status = self::STATUS_DRAFT;
337 // ...
338 // Clear extrafields that are unique
339 if (is_array($object->array_options) && count($object->array_options) > 0) {
340 $extrafields->fetch_name_optionals_label($this->table_element);
341 foreach ($object->array_options as $key => $option) {
342 $shortkey = preg_replace('/options_/', '', $key);
343 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
344 //var_dump($key); var_dump($clonedObj->array_options[$key]); exit;
345 unset($object->array_options[$key]);
346 }
347 }
348 }
349
350 // Create clone
351 $object->context['createfromclone'] = 'createfromclone';
352 $result = $object->createCommon($user);
353 if ($result < 0) {
354 $error++;
356 }
357
358 if (!$error) {
359 // copy internal contacts
360 if ($this->copy_linked_contact($object, 'internal') < 0) {
361 $error++;
362 }
363 }
364
365 if (!$error) {
366 // copy external contacts if same company
367 if (property_exists($this, 'socid') && $this->socid == $object->socid) {
368 if ($this->copy_linked_contact($object, 'external') < 0) {
369 $error++;
370 }
371 }
372 }
373
374 unset($object->context['createfromclone']);
375
376 // End
377 if (!$error) {
378 $this->db->commit();
379 return $object;
380 } else {
381 $this->db->rollback();
382 return -1;
383 }
384 }
385
393 public function fetch($id, $ref = null)
394 {
395 $result = $this->fetchCommon($id, $ref);
396
397 $this->socid = $this->fk_soc;
398
399 if ($result > 0 && !empty($this->table_element_line)) {
400 $this->fetchLines();
401 }
402 return $result;
403 }
404
410 public function fetchLines()
411 {
412 require_once DOL_DOCUMENT_ROOT . '/product/stock/stocktransfer/class/stocktransferline.class.php';
413 $this->lines = array();
414
415 $result = $this->fetchLinesCommon();
416 usort($this->lines, array('StockTransfer', 'stocktransferCmpRank'));
417 return $result;
418 }
419
427 public static function stocktransferCmpRank($a, $b)
428 {
429 if ($a->rang == $b->rang) {
430 return 0;
431 }
432 return ($a->rang < $b->rang) ? -1 : 1;
433 }
434
440 public function getValorisationTotale()
441 {
442 $total_pmp = 0;
443
444 if (empty($this->lines)) {
445 $this->fetchLines();
446 }
447 if (!empty($this->lines)) {
448 foreach ($this->lines as $l) {
449 $total_pmp += ($l->pmp * $l->qty);
450 }
451 }
452
453 return $total_pmp;
454 }
455
468 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
469 {
470 dol_syslog(__METHOD__, LOG_DEBUG);
471
472 $records = array();
473
474 $sql = 'SELECT ';
475 $sql .= $this->getFieldList();
476 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
477 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
478 $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
479 } else {
480 $sql .= ' WHERE 1 = 1';
481 }
482
483 // Manage filter
484 $errormessage = '';
485 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
486 if ($errormessage) {
487 $this->errors[] = $errormessage;
488 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
489 return -1;
490 }
491
492 if (!empty($sortfield)) {
493 $sql .= $this->db->order($sortfield, $sortorder);
494 }
495 if (!empty($limit)) {
496 $sql .= ' '.$this->db->plimit($limit, $offset);
497 }
498
499 $resql = $this->db->query($sql);
500 if ($resql) {
501 $num = $this->db->num_rows($resql);
502 $i = 0;
503 while ($i < ($limit ? min($limit, $num) : $num)) {
504 $obj = $this->db->fetch_object($resql);
505
506 $record = new self($this->db);
507 $record->setVarsFromFetchObj($obj);
508
509 $records[$record->id] = $record;
510
511 $i++;
512 }
513 $this->db->free($resql);
514
515 return $records;
516 } else {
517 $this->errors[] = 'Error '.$this->db->lasterror();
518 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
519
520 return -1;
521 }
522 }
523
531 public function update(User $user, $notrigger = 0)
532 {
533 $this->tms = 0; // Will be done automatically because tms field is on update cascade
534 $res = $this->updateCommon($user, $notrigger);
535 if (($this->socid > 0 || $this->fk_soc > 0) && empty($this->thirdparty)) {
536 $this->fetch_thirdparty();
537 }
538 if (empty($this->socid) && empty($this->fk_soc)) {
539 unset($this->thirdparty);
540 }
541 return $res;
542 }
543
551 public function delete(User $user, $notrigger = 0)
552 {
553 if ($this->status > self::STATUS_VALIDATED) {
554 return 0;
555 } else {
556 return $this->deleteCommon($user, $notrigger);
557 }
558 }
559
568 public function deleteLine(User $user, $idline, $notrigger = 0)
569 {
570 if ($this->status < 0) {
571 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
572 return -2;
573 }
574
575 $res = $this->deleteLineCommon($user, $idline, $notrigger);
576 $this->line_order(true);
577 return $res;
578 }
579
580
588 public function validate($user, $notrigger = 0)
589 {
590 global $conf, $langs;
591
592 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
593
594 $error = 0;
595
596 // Protection
597 if ($this->status == self::STATUS_VALIDATED) {
598 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
599 return 0;
600 }
601
602 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer->write))
603 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer->stocktransfer_advance->validate))))
604 {
605 $this->error='NotEnoughPermissions';
606 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
607 return -1;
608 }*/
609
610 $now = dol_now();
611
612 $this->db->begin();
613
614 // Define new ref
615 if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
616 $num = $this->getNextNumRef();
617 } else {
618 $num = $this->ref;
619 }
620 $this->newref = $num;
621
622 if (!empty($num)) {
623 // Validate
624 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
625 $sql .= " SET ref = '".$this->db->escape($num)."',";
626 $sql .= " status = ".self::STATUS_VALIDATED;
627 if (!empty($this->fields['date_validation'])) {
628 $sql .= ", date_validation = '".$this->db->idate($now)."',";
629 }
630 if (!empty($this->fields['fk_user_valid'])) { // @phan-suppress-current-line PhanTypeMismatchProperty
631 $sql .= ", fk_user_valid = ".((int) $user->id);
632 }
633 $sql .= " WHERE rowid = ".((int) $this->id);
634
635 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
636 $resql = $this->db->query($sql);
637 if (!$resql) {
638 dol_print_error($this->db);
639 $this->error = $this->db->lasterror();
640 $error++;
641 }
642
643 if (!$error && !$notrigger) {
644 // Call trigger
645 $result = $this->call_trigger('STOCKTRANSFER_VALIDATE', $user);
646 if ($result < 0) {
647 $error++;
648 }
649 // End call triggers
650 }
651 }
652
653 if (!$error) {
654 $this->oldref = $this->ref;
655
656 // Rename directory if dir was a temporary ref
657 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
658 // Now we rename also files into index
659 $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)."'";
660 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'stocktransfer/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
661 $resql = $this->db->query($sql);
662 if (!$resql) {
663 $error++;
664 $this->error = $this->db->lasterror();
665 }
666 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'stocktransfer/".$this->db->escape($this->newref)."'";
667 $sql .= " WHERE filepath = 'stocktransfer/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
668 $resql = $this->db->query($sql);
669 if (!$resql) {
670 $error++;
671 $this->error = $this->db->lasterror();
672 }
673
674 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
675 $oldref = dol_sanitizeFileName($this->ref);
676 $newref = dol_sanitizeFileName($num);
677 $dirsource = $conf->stocktransfer->dir_output.'/stocktransfer/'.$oldref;
678 $dirdest = $conf->stocktransfer->dir_output.'/stocktransfer/'.$newref;
679 if (!$error && file_exists($dirsource)) {
680 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
681
682 if (@rename($dirsource, $dirdest)) {
683 dol_syslog("Rename ok");
684 // Rename docs starting with $oldref with $newref
685 $listoffiles = dol_dir_list($conf->stocktransfer->dir_output.'/stocktransfer/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
686 foreach ($listoffiles as $fileentry) {
687 $dirsource = $fileentry['name'];
688 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
689 $dirsource = $fileentry['path'].'/'.$dirsource;
690 $dirdest = $fileentry['path'].'/'.$dirdest;
691 @rename($dirsource, $dirdest);
692 }
693 }
694 }
695 }
696 }
697
698 // Set new ref and current status
699 if (!$error) {
700 $this->ref = $num;
701 $this->status = self::STATUS_VALIDATED;
702 }
703
704 if (!$error) {
705 $this->db->commit();
706 return 1;
707 } else {
708 $this->db->rollback();
709 return -1;
710 }
711 }
712
713
721 public function setDraft($user, $notrigger = 0)
722 {
723 // Protection
724 if ($this->status <= self::STATUS_DRAFT) {
725 return 0;
726 }
727
728 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->write))
729 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer_advance->validate))))
730 {
731 $this->error='Permission denied';
732 return -1;
733 }*/
734
735 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'STOCKTRANSFER_UNVALIDATE');
736 }
737
745 public function cancel($user, $notrigger = 0)
746 {
747 // Protection
748 if ($this->status != self::STATUS_VALIDATED) {
749 return 0;
750 }
751
752 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->write))
753 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer_advance->validate))))
754 {
755 $this->error='Permission denied';
756 return -1;
757 }*/
758
759 return $this->setStatusCommon($user, self::STATUS_CLOSED, $notrigger, 'STOCKTRANSFER_CLOSE');
760 }
761
769 public function reopen($user, $notrigger = 0)
770 {
771 // Protection
772 if ($this->status != self::STATUS_CLOSED) {
773 return 0;
774 }
775
776 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->write))
777 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer_advance->validate))))
778 {
779 $this->error='Permission denied';
780 return -1;
781 }*/
782
783 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'STOCKTRANSFER_REOPEN');
784 }
785
796 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
797 {
798 global $conf, $langs, $hookmanager;
799
800 if (!empty($conf->dol_no_mouse_hover)) {
801 $notooltip = 1;
802 } // Force disable tooltips
803
804 $result = '';
805
806 $label = '<u>'.$langs->trans("StockTransfer").'</u>';
807 $label .= '<br>';
808 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
809 if (isset($this->status)) {
810 $label .= '<br><b>'.$langs->trans("Status").":</b> ".$this->getLibStatut(5);
811 }
812
813 $url = dol_buildpath('/product/stock/stocktransfer/stocktransfer_card.php', 1).'?id='.$this->id;
814
815 if ($option != 'nolink') {
816 // Add param to save lastsearch_values or not
817 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
818 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
819 $add_save_lastsearch_values = 1;
820 }
821 if ($add_save_lastsearch_values) {
822 $url .= '&save_lastsearch_values=1';
823 }
824 }
825
826 $linkclose = '';
827 if (empty($notooltip)) {
828 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
829 $label = $langs->trans("ShowStockTransfer");
830 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
831 }
832 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
833 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
834 } else {
835 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
836 }
837
838 $linkstart = '<a href="'.$url.'"';
839 $linkstart .= $linkclose.'>';
840 $linkend = '</a>';
841
842 $result .= $linkstart;
843
844 if (empty($this->showphoto_on_popup)) {
845 if ($withpicto) {
846 $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);
847 }
848 } else {
849 if ($withpicto) {
850 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
851
852 list($class, $module) = explode('@', $this->picto);
853 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
854 $filearray = dol_dir_list($upload_dir, "files");
855 $filename = $filearray[0]['name'];
856 if (!empty($filename)) {
857 $pospoint = strpos($filearray[0]['name'], '.');
858
859 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
860 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
861 $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>';
862 } else {
863 $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>';
864 }
865
866 $result .= '</div>';
867 } else {
868 $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);
869 }
870 }
871 }
872
873 if ($withpicto != 2) {
874 $result .= $this->ref;
875 }
876
877 $result .= $linkend;
878 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
879
880 global $action, $hookmanager;
881 $hookmanager->initHooks(array('stocktransferdao'));
882 $parameters = array('id' => $this->id, 'getnomurl' => $result);
883 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
884 if ($reshook > 0) {
885 $result = $hookmanager->resPrint;
886 } else {
887 $result .= $hookmanager->resPrint;
888 }
889
890 return $result;
891 }
892
899 public function getLibStatut($mode = 0)
900 {
901 return $this->LibStatut($this->status, $mode);
902 }
903
904 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
912 public function LibStatut($status, $mode = 0)
913 {
914 // phpcs:enable
915 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
916 global $langs;
917 //$langs->load("stocktransfer@stocktransfer");
918 $this->labelStatus[self::STATUS_DRAFT] = $langs->trans('Draft');
919 $this->labelStatus[self::STATUS_VALIDATED] = $langs->trans('Validated');
920 $this->labelStatus[self::STATUS_TRANSFERED] = $langs->trans('StockStransferDecremented');
921 $this->labelStatus[self::STATUS_CLOSED] = $langs->trans('StockStransferIncremented');
922 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->trans('Draft');
923 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->trans('Validated');
924 $this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->trans('StockStransferDecremented');
925 $this->labelStatusShort[self::STATUS_CLOSED] = $langs->trans('StockStransferIncremented');
926 }
927
928 $statusType = 'status'.$status;
929 //if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
930 if ($status == self::STATUS_CLOSED) {
931 $statusType = 'status6';
932 }
933
934 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
935 }
936
943 public function info($id)
944 {
945 $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
946 $sql .= ' fk_user_creat, fk_user_modif';
947 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
948 $sql .= ' WHERE t.rowid = '.((int) $id);
949 $result = $this->db->query($sql);
950 if ($result) {
951 if ($this->db->num_rows($result)) {
952 $obj = $this->db->fetch_object($result);
953 $this->id = $obj->rowid;
954
955 $this->user_creation_id = $obj->fk_user_creat;
956 $this->user_modification_id = $obj->fk_user_modif;
957 $this->date_creation = $this->db->jdate($obj->datec);
958 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
959 }
960
961 $this->db->free($result);
962 } else {
963 dol_print_error($this->db);
964 }
965 }
966
973 public function initAsSpecimen()
974 {
975 return $this->initAsSpecimenCommon();
976 }
977
983 public function getLinesArray()
984 {
985 $this->lines = array();
986
987 $objectline = new StockTransferLine($this->db);
988 $result = $objectline->fetchAll('ASC', 'rang', 0, 0, "(fk_stocktransfer:=:".((int) $this->id).")");
989
990 if (is_numeric($result)) {
991 $this->error = $objectline->error;
992 $this->errors = $objectline->errors;
993 return $result;
994 } else {
995 $this->lines = $result;
996 return $this->lines;
997 }
998 }
999
1005 public function getNextNumRef()
1006 {
1007 global $langs, $conf;
1008 $langs->load("stocks");
1009
1010 if (!getDolGlobalString('STOCKTRANSFER_STOCKTRANSFER_ADDON')) {
1011 $conf->global->STOCKTRANSFER_STOCKTRANSFER_ADDON = 'mod_stocktransfer_standard';
1012 }
1013
1014 if (getDolGlobalString('STOCKTRANSFER_STOCKTRANSFER_ADDON')) {
1015 $mybool = false;
1016
1017 $file = getDolGlobalString('STOCKTRANSFER_STOCKTRANSFER_ADDON') . ".php";
1018 $classname = getDolGlobalString('STOCKTRANSFER_STOCKTRANSFER_ADDON');
1019
1020 // Include file with class
1021 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1022 foreach ($dirmodels as $reldir) {
1023 $dir = dol_buildpath($reldir."core/modules/stocktransfer/");
1024
1025 // Load file with numbering class (if found)
1026 $mybool = ((bool) @include_once $dir.$file) || $mybool;
1027 }
1028
1029 if (!$mybool) {
1030 dol_print_error(null, "Failed to include file ".$file);
1031 return '';
1032 }
1033
1034 if (class_exists($classname)) {
1035 $obj = new $classname();
1036 '@phan-var-force ModeleNumRefStockTransfer $obj';
1037 $numref = $obj->getNextValue($this);
1038
1039 if ($numref != '' && $numref != '-1') {
1040 return $numref;
1041 } else {
1042 $this->error = $obj->error;
1043 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1044 return "";
1045 }
1046 } else {
1047 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1048 return "";
1049 }
1050 } else {
1051 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1052 return "";
1053 }
1054 }
1055
1067 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1068 {
1069 global $conf, $langs;
1070
1071 $result = 0;
1072 $includedocgeneration = 1;
1073
1074 $langs->load("stocks");
1075
1076 if (!dol_strlen($modele)) {
1077 $modele = 'eagle';
1078
1079 if ($this->model_pdf) {
1080 $modele = $this->model_pdf;
1081 } elseif (getDolGlobalString('STOCKTRANSFER_ADDON_PDF')) {
1082 $modele = getDolGlobalString('STOCKTRANSFER_ADDON_PDF');
1083 }
1084 }
1085
1086 $modelpath = "core/modules/stocktransfer/doc/";
1087
1088 if ($includedocgeneration) {
1089 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1090 }
1091
1092 return $result;
1093 }
1094
1102 public function doScheduledJob()
1103 {
1104 global $conf, $langs;
1105
1106 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1107
1108 $error = 0;
1109 $this->output = '';
1110 $this->error = '';
1111
1112 dol_syslog(__METHOD__, LOG_DEBUG);
1113
1114 $now = dol_now();
1115
1116 $this->db->begin();
1117
1118 // ...
1119
1120 $this->db->commit();
1121
1122 return $error;
1123 }
1124}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
$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.
deleteLineCommon(User $user, $idline, $notrigger=0)
Delete a line of object in database.
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.
setErrorsFromObject($object)
setErrorsFromObject
createCommon(User $user, $notrigger=0)
Create object in the database.
getFieldList($alias='', $excludefields=array())
Function to concat keys of fields.
updateCommon(User $user, $notrigger=0)
Update object into database.
setStatusCommon($user, $status, $notrigger=0, $triggercode='')
Set to a status.
initAsSpecimenCommon()
Initialise object with example values Id must be 0 if object instance is a specimen.
copy_linked_contact($objFrom, $source='internal')
Copy contact from one element to current.
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.
deleteCommon(User $user, $notrigger=0, $forcechilddeletion=0)
Delete object in 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.
update(User $user, $notrigger=0)
Update object into database.
static stocktransferCmpRank($a, $b)
Used to sort lines by rank.
fetch($id, $ref=null)
Load object in memory from the database.
deleteLine(User $user, $idline, $notrigger=0)
Delete a line of object in database.
LibStatut($status, $mode=0)
Return the status.
fetchLines()
Load object lines in memory from the database.
validate($user, $notrigger=0)
Validate object.
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.
create(User $user, $notrigger=0)
Create object into database.
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.
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter='', $filtermode='AND')
Load list of objects in memory from the database.
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionally 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.
Class for StockTransferLine.
Class to manage Dolibarr users.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:162
dol_dir_list($utf8_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:63
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
dol_now($mode='auto')
Return date for now.
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.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.