dolibarr 21.0.0-alpha
expeditionligne.class.php
1<?php
2/* Copyright (C) 2003-2008 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
5 * Copyright (C) 2006-2012 Laurent Destailleur <eldy@users.sourceforge.net>
6 * Copyright (C) 2011-2020 Juanjo Menent <jmenent@2byte.es>
7 * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
8 * Copyright (C) 2014 Cedric GROSS <c.gross@kreiz-it.fr>
9 * Copyright (C) 2014-2015 Marcos García <marcosgdf@gmail.com>
10 * Copyright (C) 2014-2017 Francis Appels <francis.appels@yahoo.com>
11 * Copyright (C) 2015 Claudio Aschieri <c.aschieri@19.coop>
12 * Copyright (C) 2016-2024 Ferran Marcet <fmarcet@2byte.es>
13 * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
14 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
15 * Copyright (C) 2020 Lenin Rivas <lenin@leninrivas.com>
16 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 3 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program. If not, see <https://www.gnu.org/licenses/>.
30 */
31
38require_once DOL_DOCUMENT_ROOT."/core/class/commonobjectline.class.php";
39require_once DOL_DOCUMENT_ROOT.'/expedition/class/expeditionlinebatch.class.php';
40
45{
49 public $element = 'expeditiondet';
50
54 public $table_element = 'expeditiondet';
55
59 public $parent_element = 'expedition';
60
64 public $fk_parent_attribute = 'fk_expedition';
65
72 public $line_id; // deprecated
73
77 public $fk_element;
78
82 public $origin_id;
83
87 public $fk_elementdet;
88
92 public $origin_line_id;
93
97 public $element_type;
98
99
106 public $fk_origin; // Example: 'orderline'
107
111 public $fk_expedition;
112
116 public $db;
117
121 public $qty;
122
126 public $qty_shipped;
127
131 public $fk_product;
132
138 public $detail_batch;
139
144 public $details_entrepot;
145
146
150 public $entrepot_id;
151
152
156 public $qty_asked;
157
163 public $ref;
164
168 public $product_ref;
169
175 public $libelle;
176
180 public $product_label;
181
187 public $desc;
188
192 public $product_desc;
193
198 public $product_type = 0;
199
203 public $rang;
204
208 public $weight;
209
213 public $weight_units;
214
218 public $length;
219
223 public $length_units;
224
228 public $width;
229
233 public $width_units;
234
238 public $height;
239
243 public $height_units;
244
248 public $surface;
249
253 public $surface_units;
254
258 public $volume;
259
263 public $volume_units;
264
268 public $remise_percent;
269
273 public $tva_tx;
274
278 public $total_ht;
279
283 public $total_ttc;
284
288 public $total_tva;
289
293 public $total_localtax1;
294
298 public $total_localtax2;
299
300
306 public function __construct($db)
307 {
308 $this->db = $db;
309 }
310
317 public function fetch($rowid)
318 {
319 $sql = 'SELECT ed.rowid, ed.fk_expedition, ed.fk_entrepot, ed.fk_elementdet, ed.element_type, ed.qty, ed.rang';
320 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as ed';
321 $sql .= ' WHERE ed.rowid = '.((int) $rowid);
322 $result = $this->db->query($sql);
323 if ($result) {
324 $objp = $this->db->fetch_object($result);
325 $this->id = $objp->rowid;
326 $this->fk_expedition = $objp->fk_expedition;
327 $this->entrepot_id = $objp->fk_entrepot;
328 $this->fk_elementdet = $objp->fk_elementdet;
329 $this->element_type = $objp->element_type;
330 $this->qty = $objp->qty;
331 $this->rang = $objp->rang;
332
333 $this->db->free($result);
334
335 return 1;
336 } else {
337 $this->errors[] = $this->db->lasterror();
338 $this->error = $this->db->lasterror();
339 return -1;
340 }
341 }
342
350 public function insert($user, $notrigger = 0)
351 {
352 $error = 0;
353
354 // Check parameters
355 if (empty($this->fk_expedition) || empty($this->fk_elementdet) || !is_numeric($this->qty)) {
356 $this->error = 'ErrorMandatoryParametersNotProvided';
357 return -1;
358 }
359
360 $this->db->begin();
361
362 if (empty($this->rang)) {
363 $this->rang = 0;
364 }
365
366 // Rank to use
367 $ranktouse = $this->rang;
368 if ($ranktouse == -1) {
369 $rangmax = $this->line_max($this->fk_expedition);
370 $ranktouse = $rangmax + 1;
371 }
372
373 $sql = "INSERT INTO ".MAIN_DB_PREFIX."expeditiondet (";
374 $sql .= "fk_expedition";
375 $sql .= ", fk_entrepot";
376 $sql .= ", fk_elementdet";
377 $sql .= ", element_type";
378 $sql .= ", qty";
379 $sql .= ", rang";
380 $sql .= ") VALUES (";
381 $sql .= $this->fk_expedition;
382 $sql .= ", ".(empty($this->entrepot_id) ? 'NULL' : $this->entrepot_id);
383 $sql .= ", ".((int) $this->fk_elementdet);
384 $sql .= ", '".(empty($this->element_type) ? 'order' : $this->db->escape($this->element_type))."'";
385 $sql .= ", ".price2num($this->qty, 'MS');
386 $sql .= ", ".((int) $ranktouse);
387 $sql .= ")";
388
389 dol_syslog(get_class($this)."::insert", LOG_DEBUG);
390 $resql = $this->db->query($sql);
391 if ($resql) {
392 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."expeditiondet");
393
394 if (!$error) {
395 $result = $this->insertExtraFields();
396 if ($result < 0) {
397 $error++;
398 }
399 }
400
401 if (!$error && !$notrigger) {
402 // Call trigger
403 $result = $this->call_trigger('LINESHIPPING_INSERT', $user);
404 if ($result < 0) {
405 $error++;
406 }
407 // End call triggers
408 }
409
410 if ($error) {
411 foreach ($this->errors as $errmsg) {
412 dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
413 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
414 }
415 }
416 } else {
417 $error++;
418 }
419
420 if ($error) {
421 $this->db->rollback();
422 return -1;
423 } else {
424 $this->db->commit();
425 return $this->id;
426 }
427 }
428
436 public function delete($user = null, $notrigger = 0)
437 {
438 $error = 0;
439
440 $this->db->begin();
441
442 // delete batch expedition line
443 if (isModEnabled('productbatch')) {
444 $sql = "DELETE FROM ".MAIN_DB_PREFIX."expeditiondet_batch";
445 $sql .= " WHERE fk_expeditiondet = ".((int) $this->id);
446
447 if (!$this->db->query($sql)) {
448 $this->errors[] = $this->db->lasterror()." - sql=$sql";
449 $error++;
450 }
451 }
452
453 $sql = "DELETE FROM ".MAIN_DB_PREFIX."expeditiondet";
454 $sql .= " WHERE rowid = ".((int) $this->id);
455
456 if (!$error && $this->db->query($sql)) {
457 // Remove extrafields
458 if (!$error) {
459 $result = $this->deleteExtraFields();
460 if ($result < 0) {
461 $this->errors[] = $this->error;
462 $error++;
463 }
464 }
465 if (!$error && !$notrigger) {
466 // Call trigger
467 $result = $this->call_trigger('LINESHIPPING_DELETE', $user);
468 if ($result < 0) {
469 $this->errors[] = $this->error;
470 $error++;
471 }
472 // End call triggers
473 }
474 } else {
475 $this->errors[] = $this->db->lasterror()." - sql=$sql";
476 $error++;
477 }
478
479 if (!$error) {
480 $this->db->commit();
481 return 1;
482 } else {
483 foreach ($this->errors as $errmsg) {
484 dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
485 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
486 }
487 $this->db->rollback();
488 return -1 * $error;
489 }
490 }
491
499 public function update($user = null, $notrigger = 0)
500 {
501 $error = 0;
502
503 dol_syslog(get_class($this)."::update id=$this->id, entrepot_id=$this->entrepot_id, product_id=$this->fk_product, qty=$this->qty");
504
505 $this->db->begin();
506
507 // Clean parameters
508 if (empty($this->qty)) {
509 $this->qty = 0;
510 }
511 $qty = price2num($this->qty);
512 $remainingQty = 0;
513 $batch = null;
514 $batch_id = null;
515 $expedition_batch_id = null;
516 if (is_array($this->detail_batch)) { // array of ExpeditionLineBatch
517 if (count($this->detail_batch) > 1) {
518 dol_syslog(get_class($this).'::update only possible for one batch', LOG_ERR);
519 $this->errors[] = 'ErrorBadParameters';
520 $error++;
521 } else {
522 $batch = $this->detail_batch[0]->batch;
523 $batch_id = $this->detail_batch[0]->fk_origin_stock;
524 $expedition_batch_id = $this->detail_batch[0]->id;
525 if ($this->entrepot_id != $this->detail_batch[0]->entrepot_id) {
526 dol_syslog(get_class($this).'::update only possible for batch of same warehouse', LOG_ERR);
527 $this->errors[] = 'ErrorBadParameters';
528 $error++;
529 }
530 $qty = price2num($this->detail_batch[0]->qty);
531 }
532 } elseif (!empty($this->detail_batch)) {
533 $batch = $this->detail_batch->batch;
534 $batch_id = $this->detail_batch->fk_origin_stock;
535 $expedition_batch_id = $this->detail_batch->id;
536 if ($this->entrepot_id != $this->detail_batch->entrepot_id) {
537 dol_syslog(get_class($this).'::update only possible for batch of same warehouse', LOG_ERR);
538 $this->errors[] = 'ErrorBadParameters';
539 $error++;
540 }
541 $qty = price2num($this->detail_batch->qty);
542 }
543
544 // check parameters
545 if (!isset($this->id) || !isset($this->entrepot_id)) {
546 dol_syslog(get_class($this).'::update missing line id and/or warehouse id', LOG_ERR);
547 $this->errors[] = 'ErrorMandatoryParametersNotProvided';
548 $error++;
549 return -1;
550 }
551
552 // update lot
553
554 if (!empty($batch) && isModEnabled('productbatch')) {
555 $batch_id_str = $batch_id ?? 'null';
556 dol_syslog(get_class($this)."::update expedition batch id=$expedition_batch_id, batch_id=$batch_id_str, batch=$batch");
557
558 if (empty($batch_id) || empty($this->fk_product)) {
559 dol_syslog(get_class($this).'::update missing fk_origin_stock (batch_id) and/or fk_product', LOG_ERR);
560 $this->errors[] = 'ErrorMandatoryParametersNotProvided';
561 $error++;
562 }
563
564 // fetch remaining lot qty
565 $shipmentlinebatch = new ExpeditionLineBatch($this->db);
566 $lotArray = $shipmentlinebatch->fetchAll($this->id);
567 if (!$error && $lotArray < 0) {
568 $this->errors[] = $this->db->lasterror()." - ExpeditionLineBatch::fetchAll";
569 $error++;
570 } else {
571 // calculate new total line qty
572 foreach ($lotArray as $lot) {
573 if ($expedition_batch_id != $lot->id) {
574 $remainingQty += $lot->qty;
575 }
576 }
577 $qty += $remainingQty;
578
579 //fetch lot details
580
581 // fetch from product_lot
582 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
583 $lot = new Productlot($this->db);
584 if ($lot->fetch(0, $this->fk_product, $batch) < 0) {
585 $this->errors = array_merge($this->errors, $lot->errors);
586 $error++;
587 }
588 if (!$error && !empty($expedition_batch_id)) {
589 // delete lot expedition line
590 $sql = "DELETE FROM ".MAIN_DB_PREFIX."expeditiondet_batch";
591 $sql .= " WHERE fk_expeditiondet = ".((int) $this->id);
592 $sql .= " AND rowid = ".((int) $expedition_batch_id);
593
594 if (!$this->db->query($sql)) {
595 $this->errors[] = $this->db->lasterror()." - sql=$sql";
596 $error++;
597 }
598 }
599 if (!$error && $this->detail_batch->qty > 0) {
600 // create lot expedition line
601 if (isset($lot->id)) {
602 $shipmentLot = new ExpeditionLineBatch($this->db);
603 $shipmentLot->batch = $lot->batch;
604 $shipmentLot->eatby = $lot->eatby;
605 $shipmentLot->sellby = $lot->sellby;
606 $shipmentLot->entrepot_id = $this->detail_batch->entrepot_id;
607 $shipmentLot->qty = $this->detail_batch->qty;
608 $shipmentLot->fk_origin_stock = $batch_id;
609 if ($shipmentLot->create($this->id) < 0) {
610 $this->errors = $shipmentLot->errors;
611 $error++;
612 }
613 }
614 }
615 }
616 }
617 if (!$error) {
618 // update line
619 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
620 $sql .= " fk_entrepot = ".($this->entrepot_id > 0 ? $this->entrepot_id : 'null');
621 $sql .= " , qty = ".((float) price2num($qty, 'MS'));
622 $sql .= " WHERE rowid = ".((int) $this->id);
623
624 if (!$this->db->query($sql)) {
625 $this->errors[] = $this->db->lasterror()." - sql=$sql";
626 $error++;
627 }
628 }
629
630 if (!$error) {
631 $result = $this->insertExtraFields();
632 if ($result < 0) {
633 $this->errors[] = $this->error;
634 $error++;
635 }
636 }
637
638 if (!$error && !$notrigger) {
639 // Call trigger
640 $result = $this->call_trigger('LINESHIPPING_MODIFY', $user);
641 if ($result < 0) {
642 $this->errors[] = $this->error;
643 $error++;
644 }
645 // End call triggers
646 }
647 if (!$error) {
648 $this->db->commit();
649 return 1;
650 } else {
651 foreach ($this->errors as $errmsg) {
652 dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
653 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
654 }
655 $this->db->rollback();
656 return -1 * $error;
657 }
658 }
659}
deleteExtraFields()
Delete all extra fields values for the current object.
line_max($fk_parent_line=0)
Get max value used for position of line (rang)
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage lines of shipment.
fetch($rowid)
Load line expedition.
__construct($db)
Constructor.
insert($user, $notrigger=0)
Insert line into database.
update($user=null, $notrigger=0)
Update a line in database.
CRUD class for batch number management within shipment.
Class with list of lots and properties.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.