338 $sql =
'SELECT ed.rowid, ed.fk_expedition, ed.fk_entrepot, ed.description, ed.fk_unit, ed.fk_elementdet, ed.element_type, ed.qty, ed.rang, ed.extraparams';
339 $sql .=
' FROM '.MAIN_DB_PREFIX.$this->table_element.
' as ed';
340 $sql .=
' WHERE ed.rowid = '.((int) $rowid);
341 $result = $this->db->query($sql);
343 $objp = $this->db->fetch_object($result);
344 $this->
id = $objp->rowid;
345 $this->fk_expedition = $objp->fk_expedition;
346 $this->entrepot_id = $objp->fk_entrepot;
348 $this->fk_unit = $objp->fk_unit;
349 $this->fk_elementdet = $objp->fk_elementdet;
350 $this->element_type = $objp->element_type;
351 $this->qty = $objp->qty;
352 $this->rang = $objp->rang;
354 $this->extraparams = !empty($objp->extraparams) ? (array) json_decode($objp->extraparams,
true) : array();
356 $this->db->free($result);
360 $this->errors[] = $this->db->lasterror();
361 $this->error = $this->db->lasterror();
373 public function insert($user =
null, $notrigger = 0)
378 $skip_check_parameters =
false;
381 if (!empty($this->element_type)
382 && !empty($this->fk_elementdet)
383 && $this->element_type ==
'commande') {
384 $objectsrc_line =
new OrderLine($this->db);
385 $objectsrc_line->fetch($this->fk_elementdet);
386 $skip_check_parameters = $objectsrc_line->special_code == SUBTOTALS_SPECIAL_CODE;
390 $origin_id = $this->origin_id;
391 if ($origin_id > 0) {
392 if ((empty($this->fk_expedition)
393 || (empty($this->fk_elementdet) && empty($this->fk_parent))
394 || !is_numeric($this->qty))
395 && !$skip_check_parameters) {
396 $langs->load(
'errors');
397 $this->errors[] = $langs->trans(
'ErrorMandatoryParametersNotProvided');
401 if (empty($this->fk_expedition) || !is_numeric($this->qty)) {
402 $langs->load(
'errors');
403 $this->errors[] = $langs->trans(
'ErrorMandatoryParametersNotProvided');
409 if (
getDolGlobalString(
'STOCK_EXPEDITION_NO_MORE_THAN_ORDER') && !empty($this->fk_elementdet) && !empty($this->fk_expedition)) {
411 if (!empty($this->error)) {
412 $this->db->rollback();
417 if (empty($this->rang)) {
422 $ranktouse = $this->rang;
423 if ($ranktouse == -1) {
424 $rangmax = $this->
line_max($this->fk_expedition);
425 $ranktouse = $rangmax + 1;
428 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"expeditiondet (";
429 $sql .=
"fk_expedition";
430 $sql .=
", fk_entrepot";
431 $sql .=
", fk_elementdet";
432 $sql .=
", fk_parent";
433 $sql .=
", fk_product";
434 $sql .=
", element_type";
437 $sql .=
", description";
439 $sql .=
") VALUES (";
440 $sql .= $this->fk_expedition;
441 $sql .=
", ".(empty($this->entrepot_id) ?
'NULL' : $this->entrepot_id);
442 $sql .=
", ".(empty($this->fk_elementdet) ?
'NULL' : $this->fk_elementdet);
443 $sql .=
", ".(empty($this->fk_parent) ?
'NULL' : $this->fk_parent);
444 $sql .=
", ".(empty($this->fk_product) ?
'NULL' : $this->fk_product);
445 $sql .=
", '".(empty($this->element_type) ?
'order' : $this->db->escape($this->element_type)).
"'";
446 $sql .=
", ".price2num($this->qty,
'MS');
447 $sql .=
", ".((int) $this->fk_unit);
449 $sql .=
", ".((int) $ranktouse);
452 dol_syslog(get_class($this).
"::insert", LOG_DEBUG);
453 $resql = $this->db->query($sql);
455 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
"expeditiondet");
464 if (!$error && !$notrigger) {
466 $result = $this->call_trigger(
'LINESHIPPING_INSERT', $user);
474 foreach ($this->errors as $errmsg) {
476 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
484 $this->db->rollback();
504 $sql =
"SELECT ed.rowid as child_line_id";
506 $sql .=
", ed.fk_product";
507 $sql .=
", ed.fk_parent";
508 $sql .=
", " . $this->db->ifsql(
'eb.rowid IS NULL',
'ed.qty',
'eb.qty') .
" as qty";
509 $sql .=
", " . $this->db->ifsql(
'eb.rowid IS NULL',
'ed.fk_entrepot',
'eb.fk_warehouse') .
" as fk_warehouse";
510 $sql .=
", eb.batch, eb.eatby, eb.sellby";
512 $sql .=
" FROM " . $this->db->prefix() . $this->table_element .
" as ed";
513 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"expeditiondet_batch as eb ON eb.fk_expeditiondet = " . ((int) $line_id);
514 $sql .=
" WHERE ed.fk_parent = " . ((int) $line_id);
515 $sql .= $this->db->order(
'ed.fk_product,ed.rowid',
'ASC,ASC');
517 $resql = $this->db->query($sql);
519 while ($obj = $this->db->fetch_object($resql)) {
520 $child_line_id = (int) $obj->child_line_id;
521 if (!isset($list[$line_id])) {
522 $list[$line_id] = array();
526 $list[$line_id][] = $child_line_id;
527 } elseif ($mode == 1) {
529 $line_obj->rowid = $child_line_id;
530 $line_obj->fk_product = $obj->fk_product;
531 $line_obj->fk_parent = $obj->fk_parent;
532 $line_obj->qty = $obj->qty;
533 $line_obj->fk_warehouse = $obj->fk_warehouse;
534 $line_obj->batch = $obj->batch;
535 $line_obj->eatby = $obj->eatby;
536 $line_obj->sellby = $obj->sellby;
537 $line_obj->iskit = 0;
538 $line_obj->incdec = 0;
539 $list[$line_id][] = $line_obj;
544 $this->db->free($resql);
546 $this->error = $this->db->lasterror();
547 $this->errors[] = $this->error;
548 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
562 public function delete($user =
null, $notrigger = 0)
569 if (
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS') && !($this->fk_parent > 0)) {
571 $line_id_list = array();
572 $result = $this->
findAllChild($this->
id, $line_id_list);
574 $child_line_id_list = array_reverse($line_id_list,
true);
575 foreach ($child_line_id_list as $child_line_id_arr) {
576 foreach ($child_line_id_arr as $child_line_id) {
579 $sql =
"DELETE FROM " . $this->db->prefix() .
"expeditiondet_batch";
580 $sql .=
" WHERE fk_expeditiondet = " . ((int) $child_line_id);
581 if (!$this->db->query($sql)) {
583 $this->errors[] = $this->db->lasterror() .
" - sql=$sql";
587 $sql =
"DELETE FROM " . $this->db->prefix() .
"expeditiondet";
588 $sql .=
" WHERE rowid = " . ((int) $child_line_id);
589 if (!$this->db->query($sql)) {
591 $this->errors[] = $this->db->lasterror() .
" - sql=$sql";
610 $sql =
"DELETE FROM ".$this->db->prefix().
"expeditiondet_batch";
611 $sql .=
" WHERE fk_expeditiondet = ".((int) $this->
id);
613 if (!$this->db->query($sql)) {
614 $this->errors[] = $this->db->lasterror().
" - sql=$sql";
619 $sql =
"DELETE FROM ".$this->db->prefix().
"expeditiondet";
620 $sql .=
" WHERE rowid = ".((int) $this->
id);
622 if (!$error && $this->db->query($sql)) {
627 $this->errors[] = $this->error;
631 if (!$error && !$notrigger) {
633 $result = $this->call_trigger(
'LINESHIPPING_DELETE', $user);
635 $this->errors[] = $this->error;
641 $this->errors[] = $this->db->lasterror().
" - sql=$sql";
650 foreach ($this->errors as $errmsg) {
651 dol_syslog(get_class($this).
"::delete ".$errmsg, LOG_ERR);
652 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
654 $this->db->rollback();
666 public function update($user =
null, $notrigger = 0)
671 dol_syslog(get_class($this).
"::update id=$this->id, entrepot_id=$this->entrepot_id, product_id=$this->fk_product, qty=$this->qty");
675 if (!empty($this->
id) && empty($this->fk_elementdet)) {
676 $sql =
"SELECT fk_elementdet FROM ".MAIN_DB_PREFIX.
"expeditiondet";
677 $sql .=
" WHERE rowid = ".((int) $this->
id);
678 $resql = $this->db->query($sql);
680 $obj = $this->db->fetch_object($resql);
682 $this->fk_elementdet = $obj->fk_elementdet;
687 if (
getDolGlobalString(
'STOCK_EXPEDITION_NO_MORE_THAN_ORDER') && !empty($this->fk_elementdet)) {
688 $qty_to_check = $this->qty;
689 if (!empty($this->detail_batch)) {
690 if (is_array($this->detail_batch)) {
691 $qty_to_check = array_sum(array_column($this->detail_batch,
'qty'));
693 $qty_to_check = $this->detail_batch->qty;
697 if (!empty($this->error)) {
698 $this->db->rollback();
704 if (empty($this->qty)) {
708 $fk_unit = $this->fk_unit;
712 $expedition_batch_id = 0;
713 $origin_id = $this->origin_id;
714 if ($origin_id > 0) {
715 if (is_array($this->detail_batch)) {
716 if (count($this->detail_batch) > 1) {
717 dol_syslog(get_class($this).
'::update only possible for one batch', LOG_ERR);
718 $this->errors[] =
'ErrorBadParameters';
721 $batch = $this->detail_batch[0]->batch;
722 $batch_id = $this->detail_batch[0]->fk_origin_stock;
723 $expedition_batch_id = $this->detail_batch[0]->id;
724 if ($this->entrepot_id != $this->detail_batch[0]->entrepot_id) {
725 dol_syslog(get_class($this).
'::update only possible for batch of same warehouse', LOG_ERR);
726 $this->errors[] =
'ErrorBadParameters';
729 $qty =
price2num($this->detail_batch[0]->qty);
731 } elseif (!empty($this->detail_batch)) {
732 $batch = $this->detail_batch->batch;
733 $batch_id = $this->detail_batch->fk_origin_stock;
734 $expedition_batch_id = $this->detail_batch->id;
735 if ($this->entrepot_id != $this->detail_batch->entrepot_id) {
736 dol_syslog(get_class($this).
'::update only possible for batch of same warehouse', LOG_ERR);
737 $this->errors[] =
'ErrorBadParameters';
740 $qty =
price2num($this->detail_batch->qty);
744 if (!isset($this->
id) || !isset($this->entrepot_id)) {
745 dol_syslog(get_class($this).
'::update missing line id and/or warehouse id', LOG_ERR);
746 $langs->load(
'errors');
747 $this->errors[] = $langs->trans(
'ErrorMandatoryParametersNotProvided');
754 $batch_id_str = $batch_id ??
'null';
755 dol_syslog(get_class($this).
"::update expedition batch id=$expedition_batch_id, batch_id=$batch_id_str, batch=$batch");
757 if (empty($batch_id) || empty($this->fk_product)) {
758 dol_syslog(get_class($this).
'::update missing fk_origin_stock (batch_id) and/or fk_product', LOG_ERR);
759 $langs->load(
'errors');
760 $this->errors[] = $langs->trans(
'ErrorMandatoryParametersNotProvided');
766 $lotArray = $shipmentlinebatch->fetchAll($this->
id);
767 if (!$error && $lotArray < 0) {
768 $this->errors[] = $this->db->lasterror().
" - ExpeditionLineBatch::fetchAll";
772 foreach ($lotArray as $lot) {
773 if ($expedition_batch_id != $lot->id) {
774 $remainingQty += $lot->qty;
777 $qty += $remainingQty;
781 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/productlot.class.php';
783 if ($lot->fetch(0, $this->fk_product, $batch) < 0) {
784 $this->errors = array_merge($this->errors, $lot->errors);
787 if (!$error && !empty($expedition_batch_id)) {
789 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"expeditiondet_batch";
790 $sql .=
" WHERE fk_expeditiondet = ".((int) $this->
id);
791 $sql .=
" AND rowid = ".((int) $expedition_batch_id);
793 if (!$this->db->query($sql)) {
794 $this->errors[] = $this->db->lasterror().
" - sql=$sql";
798 if (!$error && $this->detail_batch->qty > 0) {
800 if (isset($lot->id)) {
802 $shipmentLot->batch = $lot->batch;
803 $shipmentLot->eatby = $lot->eatby;
804 $shipmentLot->sellby = $lot->sellby;
805 $shipmentLot->fk_warehouse = $this->detail_batch->entrepot_id;
806 $shipmentLot->qty = $this->detail_batch->qty;
807 $shipmentLot->fk_origin_stock = (int) $batch_id;
808 if ($shipmentLot->create($this->id) < 0) {
809 $this->errors = $shipmentLot->errors;
819 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element.
" SET";
820 $sql .=
" fk_entrepot = ".($this->entrepot_id > 0 ? $this->entrepot_id :
'null');
821 $sql .=
" , qty = ".((float)
price2num($qty,
'MS'));
822 $sql .=
" , fk_unit = ".((int) $this->fk_unit);
823 $sql .=
" WHERE rowid = ".((int) $this->
id);
825 if (!$this->db->query($sql)) {
826 $this->errors[] = $this->db->lasterror().
" - sql=$sql";
834 $this->errors[] = $this->error;
839 if (!$error && !$notrigger) {
841 $result = $this->call_trigger(
'LINESHIPPING_MODIFY', $user);
843 $this->errors[] = $this->error;
852 foreach ($this->errors as $errmsg) {
853 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
854 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
856 $this->db->rollback();
875 require_once DOL_DOCUMENT_ROOT.
'/commande/class/commande.class.php';
877 if ($orderline->fetch($fk_elementdet) <= 0) {
880 if ($orderline->product_type == 9) {
883 $qty_ordered = (float) $orderline->qty;
886 $sql =
"SELECT COALESCE(SUM(ed.qty), 0) as qty_shipped";
887 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expeditiondet as ed";
888 $sql .=
" INNER JOIN ".MAIN_DB_PREFIX.
"expedition as e ON e.rowid = ed.fk_expedition";
889 $sql .=
" WHERE ed.fk_elementdet = ".((int) $fk_elementdet);
890 $sql .=
" AND e.fk_statut >= 0";
891 if ($exclude_line_id > 0) {
892 $sql .=
" AND ed.rowid != ".((int) $exclude_line_id);
895 $resql = $this->db->query($sql);
899 $obj = $this->db->fetch_object($resql);
900 $qty_already_shipped = $obj ? (float) $obj->qty_shipped : 0;
902 $qty_remaining = $qty_ordered - $qty_already_shipped;
904 if ($qty > $qty_remaining) {
905 $langs->load(
'errors');
906 $this->error = $langs->trans(
'ErrorExpeditionQtyTooHigh', $qty, max(0, $qty_remaining));