dolibarr 20.0.0
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{
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
79
83 public $picto = 'stock';
84
85 public $date_prevue_depart;
86 public $date_prevue_arrivee;
87 public $date_reelle_depart;
88 public $date_reelle_arrivee;
89 public $origin_type;
90
91
92 const STATUS_DRAFT = 0;
93 const STATUS_VALIDATED = 1;
94 const STATUS_TRANSFERED = 2;
95 const STATUS_CLOSED = 3;
96
97
123 // BEGIN MODULEBUILDER PROPERTIES
127 public $fields = array(
128 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'comment' => "Id"),
129 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'position' => 1, 'default' => '1', 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'comment' => "Id"),
130 '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"),
131 '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),
132 'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'position' => 31, 'notnull' => 0, 'visible' => 3,),
133 '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'),
134 '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'),
135 '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'),
136 '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'),
137 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 61, 'notnull' => 0, 'visible' => 0,),
138 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 62, 'notnull' => 0, 'visible' => 0,),
139 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2,),
140 'date_prevue_depart' => array('type' => 'date', 'label' => 'DatePrevueDepart', 'enabled' => 1, 'position' => 100, 'notnull' => 0, 'visible' => 1,),
141 'date_reelle_depart' => array('type' => 'date', 'label' => 'DateReelleDepart', 'enabled' => 1, 'position' => 101, 'notnull' => 0, 'visible' => 5,),
142 'date_prevue_arrivee' => array('type' => 'date', 'label' => 'DatePrevueArrivee', 'enabled' => 1, 'position' => 102, 'notnull' => 0, 'visible' => 1,),
143 'date_reelle_arrivee' => array('type' => 'date', 'label' => 'DateReelleArrivee', 'enabled' => 1, 'position' => 103, 'notnull' => 0, 'visible' => 5,),
144 'lead_time_for_warning' => array('type' => 'integer', 'label' => 'LeadTimeForWarning', 'enabled' => 1, 'position' => 200, 'default' => '0', 'notnull' => 0, 'visible' => 1),
145 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2,),
146 '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',),
147 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'ChangedBy', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2,),
148 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,),
149 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0,),
150 'fk_incoterms' => array('type' => 'integer', 'label' => 'IncotermCode', 'enabled' => '$conf->incoterm->enabled', 'visible' => -2, 'position' => 220),
151 'location_incoterms' => array('type' => 'varchar(255)', 'label' => 'IncotermLabel', 'enabled' => '$conf->incoterm->enabled', 'visible' => -2, 'position' => 225),
152 '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'),),
153 );
154 public $rowid;
155 public $ref;
156 public $label;
157 public $socid;
158 public $fk_soc; // deprecated
159 public $fk_project;
160 public $description;
161 public $note_public;
162 public $note_private;
163 public $date_creation;
164 public $lead_time_for_warning;
165 public $fk_user_creat;
166 public $fk_user_modif;
167 public $import_key;
168 public $model_pdf;
169 public $status;
170
174 public $lines;
175
176 public $fk_warehouse_source;
177 public $fk_warehouse_destination;
178 // END MODULEBUILDER PROPERTIES
179
180
186 public function __construct(DoliDB $db)
187 {
188 global $conf, $langs;
189
190 $this->db = $db;
191
192 $this->ismultientitymanaged = 0;
193 $this->isextrafieldmanaged = 1;
194
195 $this->origin_type = 'StockTransfer@product/stock/stocktransfer';
196
197 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
198 $this->fields['rowid']['visible'] = 0;
199 }
200 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
201 $this->fields['entity']['enabled'] = 0;
202 }
203
204 // Example to show how to set values of fields definition dynamically
205 /*if ($user->rights->stocktransfer->stocktransfer->read) {
206 $this->fields['myfield']['visible'] = 1;
207 $this->fields['myfield']['noteditable'] = 0;
208 }*/
209
210 // Unset fields that are disabled
211 foreach ($this->fields as $key => $val) {
212 if (isset($val['enabled']) && empty($val['enabled'])) {
213 unset($this->fields[$key]);
214 }
215 }
216
217 // Translate some data of arrayofkeyval
218 if (is_object($langs)) {
219 foreach ($this->fields as $key => $val) {
220 if (isset($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
221 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
222 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
223 }
224 }
225 }
226 }
227 }
228
236 public function create(User $user, $notrigger = 0)
237 {
238 $this->status = (int) $this->status;
239 if ($this->fk_warehouse_source <= 0) {
240 $this->fk_warehouse_source = 0;
241 }
242 if ($this->fk_warehouse_destination <= 0) {
243 $this->fk_warehouse_destination = 0;
244 }
245 return $this->createCommon($user, $notrigger);
246 }
247
255 public function createFromClone(User $user, $fromid)
256 {
257 global $langs, $extrafields;
258 $error = 0;
259
260 dol_syslog(__METHOD__, LOG_DEBUG);
261
262 $object = new self($this->db);
263
264 $this->db->begin();
265
266 // Load source object
267 $result = $object->fetchCommon($fromid);
268 if ($result > 0 && !empty($object->table_element_line)) {
269 $object->fetchLines();
270 }
271
272 // get lines so they will be clone
273 //foreach($this->lines as $line)
274 // $line->fetch_optionals();
275
276 // Reset some properties
277 unset($object->id);
278 unset($object->fk_user_creat);
279 unset($object->import_key);
280 unset($object->date_prevue_depart);
281 unset($object->date_prevue_arrivee);
282 unset($object->date_reelle_depart);
283 unset($object->date_reelle_arrivee);
284
285
286 // Clear fields
287 $object->ref = empty($this->fields['ref']['default']) ? "copy_of_".$object->ref : $this->fields['ref']['default'];
288 $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
289 $object->status = self::STATUS_DRAFT;
290 // ...
291 // Clear extrafields that are unique
292 if (is_array($object->array_options) && count($object->array_options) > 0) {
293 $extrafields->fetch_name_optionals_label($this->table_element);
294 foreach ($object->array_options as $key => $option) {
295 $shortkey = preg_replace('/options_/', '', $key);
296 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
297 //var_dump($key); var_dump($clonedObj->array_options[$key]); exit;
298 unset($object->array_options[$key]);
299 }
300 }
301 }
302
303 // Create clone
304 $object->context['createfromclone'] = 'createfromclone';
305 $result = $object->createCommon($user);
306 if ($result < 0) {
307 $error++;
308 $this->error = $object->error;
309 $this->errors = $object->errors;
310 }
311
312 if (!$error) {
313 // copy internal contacts
314 if ($this->copy_linked_contact($object, 'internal') < 0) {
315 $error++;
316 }
317 }
318
319 if (!$error) {
320 // copy external contacts if same company
321 if (property_exists($this, 'socid') && $this->socid == $object->socid) {
322 if ($this->copy_linked_contact($object, 'external') < 0) {
323 $error++;
324 }
325 }
326 }
327
328 unset($object->context['createfromclone']);
329
330 // End
331 if (!$error) {
332 $this->db->commit();
333 return $object;
334 } else {
335 $this->db->rollback();
336 return -1;
337 }
338 }
339
347 public function fetch($id, $ref = null)
348 {
349 $result = $this->fetchCommon($id, $ref);
350
351 $this->socid = $this->fk_soc;
352
353 if ($result > 0 && !empty($this->table_element_line)) {
354 $this->fetchLines();
355 }
356 return $result;
357 }
358
364 public function fetchLines()
365 {
366 require_once DOL_DOCUMENT_ROOT . '/product/stock/stocktransfer/class/stocktransferline.class.php';
367 $this->lines = array();
368
369 $result = $this->fetchLinesCommon();
370 usort($this->lines, array('StockTransfer', 'stocktransferCmpRank'));
371 return $result;
372 }
373
381 public static function stocktransferCmpRank($a, $b)
382 {
383 if ($a->rang == $b->rang) {
384 return 0;
385 }
386 return ($a->rang < $b->rang) ? -1 : 1;
387 }
388
394 public function getValorisationTotale()
395 {
396 $total_pmp = 0;
397
398 if (empty($this->lines)) {
399 $this->fetchLines();
400 }
401 if (!empty($this->lines)) {
402 foreach ($this->lines as $l) {
403 $total_pmp += ($l->pmp * $l->qty);
404 }
405 }
406
407 return $total_pmp;
408 }
409
422 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
423 {
424 dol_syslog(__METHOD__, LOG_DEBUG);
425
426 $records = array();
427
428 $sql = 'SELECT ';
429 $sql .= $this->getFieldList();
430 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
431 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
432 $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
433 } else {
434 $sql .= ' WHERE 1 = 1';
435 }
436
437 // Manage filter
438 $errormessage = '';
439 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
440 if ($errormessage) {
441 $this->errors[] = $errormessage;
442 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
443 return -1;
444 }
445
446 if (!empty($sortfield)) {
447 $sql .= $this->db->order($sortfield, $sortorder);
448 }
449 if (!empty($limit)) {
450 $sql .= ' '.$this->db->plimit($limit, $offset);
451 }
452
453 $resql = $this->db->query($sql);
454 if ($resql) {
455 $num = $this->db->num_rows($resql);
456 $i = 0;
457 while ($i < ($limit ? min($limit, $num) : $num)) {
458 $obj = $this->db->fetch_object($resql);
459
460 $record = new self($this->db);
461 $record->setVarsFromFetchObj($obj);
462
463 $records[$record->id] = $record;
464
465 $i++;
466 }
467 $this->db->free($resql);
468
469 return $records;
470 } else {
471 $this->errors[] = 'Error '.$this->db->lasterror();
472 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
473
474 return -1;
475 }
476 }
477
485 public function update(User $user, $notrigger = 0)
486 {
487 $this->tms = 0; // Will be done automatically because tms field is on update cascade
488 $res = $this->updateCommon($user, $notrigger);
489 if (($this->socid > 0 || $this->fk_soc > 0) && empty($this->thirdparty)) {
490 $this->fetch_thirdparty();
491 }
492 if (empty($this->socid) && empty($this->fk_soc)) {
493 unset($this->thirdparty);
494 }
495 return $res;
496 }
497
505 public function delete(User $user, $notrigger = 0)
506 {
507 if ($this->status > self::STATUS_VALIDATED) {
508 return 0;
509 } else {
510 return $this->deleteCommon($user, $notrigger);
511 }
512 }
513
522 public function deleteLine(User $user, $idline, $notrigger = 0)
523 {
524 if ($this->status < 0) {
525 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
526 return -2;
527 }
528
529 $res = $this->deleteLineCommon($user, $idline, $notrigger);
530 $this->line_order(true);
531 return $res;
532 }
533
534
542 public function validate($user, $notrigger = 0)
543 {
544 global $conf, $langs;
545
546 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
547
548 $error = 0;
549
550 // Protection
551 if ($this->status == self::STATUS_VALIDATED) {
552 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
553 return 0;
554 }
555
556 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer->write))
557 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer->stocktransfer_advance->validate))))
558 {
559 $this->error='NotEnoughPermissions';
560 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
561 return -1;
562 }*/
563
564 $now = dol_now();
565
566 $this->db->begin();
567
568 // Define new ref
569 if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
570 $num = $this->getNextNumRef();
571 } else {
572 $num = $this->ref;
573 }
574 $this->newref = $num;
575
576 if (!empty($num)) {
577 // Validate
578 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
579 $sql .= " SET ref = '".$this->db->escape($num)."',";
580 $sql .= " status = ".self::STATUS_VALIDATED;
581 if (!empty($this->fields['date_validation'])) {
582 $sql .= ", date_validation = '".$this->db->idate($now)."',";
583 }
584 if (!empty($this->fields['fk_user_valid'])) {
585 $sql .= ", fk_user_valid = ".((int) $user->id);
586 }
587 $sql .= " WHERE rowid = ".((int) $this->id);
588
589 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
590 $resql = $this->db->query($sql);
591 if (!$resql) {
592 dol_print_error($this->db);
593 $this->error = $this->db->lasterror();
594 $error++;
595 }
596
597 if (!$error && !$notrigger) {
598 // Call trigger
599 $result = $this->call_trigger('STOCKTRANSFER_VALIDATE', $user);
600 if ($result < 0) {
601 $error++;
602 }
603 // End call triggers
604 }
605 }
606
607 if (!$error) {
608 $this->oldref = $this->ref;
609
610 // Rename directory if dir was a temporary ref
611 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
612 // Now we rename also files into index
613 $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)."'";
614 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'stocktransfer/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
615 $resql = $this->db->query($sql);
616 if (!$resql) {
617 $error++;
618 $this->error = $this->db->lasterror();
619 }
620 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'stocktransfer/".$this->db->escape($this->newref)."'";
621 $sql .= " WHERE filepath = 'stocktransfer/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
622 $resql = $this->db->query($sql);
623 if (!$resql) {
624 $error++;
625 $this->error = $this->db->lasterror();
626 }
627
628 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
629 $oldref = dol_sanitizeFileName($this->ref);
630 $newref = dol_sanitizeFileName($num);
631 $dirsource = $conf->stocktransfer->dir_output.'/stocktransfer/'.$oldref;
632 $dirdest = $conf->stocktransfer->dir_output.'/stocktransfer/'.$newref;
633 if (!$error && file_exists($dirsource)) {
634 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
635
636 if (@rename($dirsource, $dirdest)) {
637 dol_syslog("Rename ok");
638 // Rename docs starting with $oldref with $newref
639 $listoffiles = dol_dir_list($conf->stocktransfer->dir_output.'/stocktransfer/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
640 foreach ($listoffiles as $fileentry) {
641 $dirsource = $fileentry['name'];
642 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
643 $dirsource = $fileentry['path'].'/'.$dirsource;
644 $dirdest = $fileentry['path'].'/'.$dirdest;
645 @rename($dirsource, $dirdest);
646 }
647 }
648 }
649 }
650 }
651
652 // Set new ref and current status
653 if (!$error) {
654 $this->ref = $num;
655 $this->status = self::STATUS_VALIDATED;
656 }
657
658 if (!$error) {
659 $this->db->commit();
660 return 1;
661 } else {
662 $this->db->rollback();
663 return -1;
664 }
665 }
666
667
675 public function setDraft($user, $notrigger = 0)
676 {
677 // Protection
678 if ($this->status <= self::STATUS_DRAFT) {
679 return 0;
680 }
681
682 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->write))
683 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer_advance->validate))))
684 {
685 $this->error='Permission denied';
686 return -1;
687 }*/
688
689 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'STOCKTRANSFER_UNVALIDATE');
690 }
691
699 public function cancel($user, $notrigger = 0)
700 {
701 // Protection
702 if ($this->status != self::STATUS_VALIDATED) {
703 return 0;
704 }
705
706 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->write))
707 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer_advance->validate))))
708 {
709 $this->error='Permission denied';
710 return -1;
711 }*/
712
713 return $this->setStatusCommon($user, self::STATUS_CLOSED, $notrigger, 'STOCKTRANSFER_CLOSE');
714 }
715
723 public function reopen($user, $notrigger = 0)
724 {
725 // Protection
726 if ($this->status != self::STATUS_CLOSED) {
727 return 0;
728 }
729
730 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->write))
731 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->stocktransfer->stocktransfer_advance->validate))))
732 {
733 $this->error='Permission denied';
734 return -1;
735 }*/
736
737 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'STOCKTRANSFER_REOPEN');
738 }
739
750 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
751 {
752 global $conf, $langs, $hookmanager;
753
754 if (!empty($conf->dol_no_mouse_hover)) {
755 $notooltip = 1;
756 } // Force disable tooltips
757
758 $result = '';
759
760 $label = '<u>'.$langs->trans("StockTransfer").'</u>';
761 $label .= '<br>';
762 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
763 if (isset($this->status)) {
764 $label .= '<br><b>'.$langs->trans("Status").":</b> ".$this->getLibStatut(5);
765 }
766
767 $url = dol_buildpath('/product/stock/stocktransfer/stocktransfer_card.php', 1).'?id='.$this->id;
768
769 if ($option != 'nolink') {
770 // Add param to save lastsearch_values or not
771 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
772 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
773 $add_save_lastsearch_values = 1;
774 }
775 if ($add_save_lastsearch_values) {
776 $url .= '&save_lastsearch_values=1';
777 }
778 }
779
780 $linkclose = '';
781 if (empty($notooltip)) {
782 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
783 $label = $langs->trans("ShowStockTransfer");
784 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
785 }
786 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
787 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
788 } else {
789 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
790 }
791
792 $linkstart = '<a href="'.$url.'"';
793 $linkstart .= $linkclose.'>';
794 $linkend = '</a>';
795
796 $result .= $linkstart;
797
798 if (empty($this->showphoto_on_popup)) {
799 if ($withpicto) {
800 $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);
801 }
802 } else {
803 if ($withpicto) {
804 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
805
806 list($class, $module) = explode('@', $this->picto);
807 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
808 $filearray = dol_dir_list($upload_dir, "files");
809 $filename = $filearray[0]['name'];
810 if (!empty($filename)) {
811 $pospoint = strpos($filearray[0]['name'], '.');
812
813 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
814 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
815 $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>';
816 } else {
817 $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>';
818 }
819
820 $result .= '</div>';
821 } else {
822 $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);
823 }
824 }
825 }
826
827 if ($withpicto != 2) {
828 $result .= $this->ref;
829 }
830
831 $result .= $linkend;
832 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
833
834 global $action, $hookmanager;
835 $hookmanager->initHooks(array('stocktransferdao'));
836 $parameters = array('id' => $this->id, 'getnomurl' => $result);
837 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
838 if ($reshook > 0) {
839 $result = $hookmanager->resPrint;
840 } else {
841 $result .= $hookmanager->resPrint;
842 }
843
844 return $result;
845 }
846
853 public function getLibStatut($mode = 0)
854 {
855 return $this->LibStatut($this->status, $mode);
856 }
857
858 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
866 public function LibStatut($status, $mode = 0)
867 {
868 // phpcs:enable
869 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
870 global $langs;
871 //$langs->load("stocktransfer@stocktransfer");
872 $this->labelStatus[self::STATUS_DRAFT] = $langs->trans('Draft');
873 $this->labelStatus[self::STATUS_VALIDATED] = $langs->trans('Validated');
874 $this->labelStatus[self::STATUS_TRANSFERED] = $langs->trans('StockStransferDecremented');
875 $this->labelStatus[self::STATUS_CLOSED] = $langs->trans('StockStransferIncremented');
876 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->trans('Draft');
877 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->trans('Validated');
878 $this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->trans('StockStransferDecremented');
879 $this->labelStatusShort[self::STATUS_CLOSED] = $langs->trans('StockStransferIncremented');
880 }
881
882 $statusType = 'status'.$status;
883 //if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
884 if ($status == self::STATUS_CLOSED) {
885 $statusType = 'status6';
886 }
887
888 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
889 }
890
897 public function info($id)
898 {
899 $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
900 $sql .= ' fk_user_creat, fk_user_modif';
901 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
902 $sql .= ' WHERE t.rowid = '.((int) $id);
903 $result = $this->db->query($sql);
904 if ($result) {
905 if ($this->db->num_rows($result)) {
906 $obj = $this->db->fetch_object($result);
907 $this->id = $obj->rowid;
908
909 $this->user_creation_id = $obj->fk_user_creat;
910 $this->user_modification_id = $obj->fk_user_modif;
911 $this->date_creation = $this->db->jdate($obj->datec);
912 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
913 }
914
915 $this->db->free($result);
916 } else {
917 dol_print_error($this->db);
918 }
919 }
920
927 public function initAsSpecimen()
928 {
929 return $this->initAsSpecimenCommon();
930 }
931
937 public function getLinesArray()
938 {
939 $this->lines = array();
940
941 $objectline = new StockTransferLine($this->db);
942 $result = $objectline->fetchAll('ASC', 'rang', 0, 0, "(fk_stocktransfer:=:".((int) $this->id).")");
943
944 if (is_numeric($result)) {
945 $this->error = $objectline->error;
946 $this->errors = $objectline->errors;
947 return $result;
948 } else {
949 $this->lines = $result;
950 return $this->lines;
951 }
952 }
953
959 public function getNextNumRef()
960 {
961 global $langs, $conf;
962 $langs->load("stocks");
963
964 if (!getDolGlobalString('STOCKTRANSFER_STOCKTRANSFER_ADDON')) {
965 $conf->global->STOCKTRANSFER_STOCKTRANSFER_ADDON = 'mod_stocktransfer_standard';
966 }
967
968 if (getDolGlobalString('STOCKTRANSFER_STOCKTRANSFER_ADDON')) {
969 $mybool = false;
970
971 $file = getDolGlobalString('STOCKTRANSFER_STOCKTRANSFER_ADDON') . ".php";
972 $classname = getDolGlobalString('STOCKTRANSFER_STOCKTRANSFER_ADDON');
973
974 // Include file with class
975 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
976 foreach ($dirmodels as $reldir) {
977 $dir = dol_buildpath($reldir."core/modules/stocktransfer/");
978
979 // Load file with numbering class (if found)
980 $mybool = ((bool) @include_once $dir.$file) || $mybool;
981 }
982
983 if ($mybool === false) {
984 dol_print_error(null, "Failed to include file ".$file);
985 return '';
986 }
987
988 if (class_exists($classname)) {
989 $obj = new $classname();
990 $numref = $obj->getNextValue($this);
991
992 if ($numref != '' && $numref != '-1') {
993 return $numref;
994 } else {
995 $this->error = $obj->error;
996 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
997 return "";
998 }
999 } else {
1000 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1001 return "";
1002 }
1003 } else {
1004 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1005 return "";
1006 }
1007 }
1008
1020 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1021 {
1022 global $conf, $langs;
1023
1024 $result = 0;
1025 $includedocgeneration = 1;
1026
1027 $langs->load("stocks");
1028
1029 if (!dol_strlen($modele)) {
1030 $modele = 'eagle';
1031
1032 if ($this->model_pdf) {
1033 $modele = $this->model_pdf;
1034 } elseif (getDolGlobalString('STOCKTRANSFER_ADDON_PDF')) {
1035 $modele = getDolGlobalString('STOCKTRANSFER_ADDON_PDF');
1036 }
1037 }
1038
1039 $modelpath = "core/modules/stocktransfer/doc/";
1040
1041 if ($includedocgeneration) {
1042 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1043 }
1044
1045 return $result;
1046 }
1047
1055 public function doScheduledJob()
1056 {
1057 global $conf, $langs;
1058
1059 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1060
1061 $error = 0;
1062 $this->output = '';
1063 $this->error = '';
1064
1065 dol_syslog(__METHOD__, LOG_DEBUG);
1066
1067 $now = dol_now();
1068
1069 $this->db->begin();
1070
1071 // ...
1072
1073 $this->db->commit();
1074
1075 return $error;
1076 }
1077}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition security.php:636
$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.
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.
trait CommonIncoterm
Superclass for incoterm classes.
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 dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.