344 $sql =
'SELECT ed.rowid, ed.fk_expedition, ed.fk_entrepot, ed.fk_product, ed.fk_parent, ed.description, ed.fk_unit, ed.fk_elementdet, ed.element_type, ed.qty, ed.rang, ed.extraparams';
345 $sql .=
' FROM '.MAIN_DB_PREFIX.$this->table_element.
' as ed';
346 $sql .=
' WHERE ed.rowid = '.((int) $rowid);
347 $result = $this->db->query($sql);
349 $objp = $this->db->fetch_object($result);
350 $this->
id = $objp->rowid;
351 $this->fk_expedition = $objp->fk_expedition;
352 $this->entrepot_id = $objp->fk_entrepot;
353 $this->fk_entrepot = $objp->fk_entrepot;
354 $this->fk_product = $objp->fk_product;
355 $this->fk_parent = $objp->fk_parent;
357 $this->fk_unit = $objp->fk_unit;
358 $this->fk_elementdet = $objp->fk_elementdet;
359 $this->element_type = $objp->element_type;
360 $this->qty = $objp->qty;
361 $this->rang = $objp->rang;
363 $this->extraparams = !empty($objp->extraparams) ? (array) json_decode($objp->extraparams,
true) : array();
365 $this->db->free($result);
369 $this->errors[] = $this->db->lasterror();
370 $this->error = $this->db->lasterror();
382 public function insert($user =
null, $notrigger = 0)
387 $skip_check_parameters =
false;
390 if (!empty($this->element_type)
391 && !empty($this->fk_elementdet)
392 && $this->element_type ==
'commande') {
393 $objectsrc_line =
new OrderLine($this->db);
394 $objectsrc_line->fetch($this->fk_elementdet);
395 $skip_check_parameters = $objectsrc_line->special_code == SUBTOTALS_SPECIAL_CODE;
399 $origin_id = $this->origin_id;
400 if ($origin_id > 0) {
401 if ((empty($this->fk_expedition)
402 || (empty($this->fk_elementdet) && empty($this->fk_parent))
403 || !is_numeric($this->qty))
404 && !$skip_check_parameters) {
405 $langs->load(
'errors');
406 $this->errors[] = $langs->trans(
'ErrorMandatoryParametersNotProvided');
410 if (empty($this->fk_expedition) || !is_numeric($this->qty)) {
411 $langs->load(
'errors');
412 $this->errors[] = $langs->trans(
'ErrorMandatoryParametersNotProvided');
418 if (
getDolGlobalString(
'STOCK_EXPEDITION_NO_MORE_THAN_ORDER') && !empty($this->fk_elementdet) && !empty($this->fk_expedition)) {
420 if (!empty($this->error)) {
421 $this->db->rollback();
426 if (empty($this->rang)) {
431 $ranktouse = $this->rang;
432 if ($ranktouse == -1) {
433 $rangmax = $this->
line_max($this->fk_expedition);
434 $ranktouse = $rangmax + 1;
437 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"expeditiondet (";
438 $sql .=
"fk_expedition";
439 $sql .=
", fk_entrepot";
440 $sql .=
", fk_elementdet";
441 $sql .=
", fk_parent";
442 $sql .=
", fk_product";
443 $sql .=
", element_type";
446 $sql .=
", description";
448 $sql .=
") VALUES (";
449 $sql .= ((int) $this->fk_expedition);
450 $sql .=
", ".(empty($this->entrepot_id) ?
'NULL' : ((int) $this->entrepot_id));
451 $sql .=
", ".(empty($this->fk_elementdet) ?
'NULL' : ((int) $this->fk_elementdet));
452 $sql .=
", ".(empty($this->fk_parent) ?
'NULL' : ((int) $this->fk_parent));
453 $sql .=
", ".(empty($this->fk_product) ?
'NULL' : ((int) $this->fk_product));
454 $sql .=
", '".(empty($this->element_type) ?
'order' : $this->db->escape($this->element_type)).
"'";
455 $sql .=
", ".price2num($this->qty,
'MS');
456 $sql .=
", ".((int) $this->fk_unit);
458 $sql .=
", ".((int) $ranktouse);
461 dol_syslog(get_class($this).
"::insert", LOG_DEBUG);
462 $resql = $this->db->query($sql);
464 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
"expeditiondet");
473 if (!$error && !$notrigger) {
475 $result = $this->call_trigger(
'LINESHIPPING_INSERT', $user);
483 foreach ($this->errors as $errmsg) {
485 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
493 $this->db->rollback();
513 $sql =
"SELECT ed.rowid as child_line_id";
515 $sql .=
", ed.fk_product";
516 $sql .=
", ed.fk_parent";
517 $sql .=
", " . $this->db->ifsql(
'eb.rowid IS NULL',
'ed.qty',
'eb.qty') .
" as qty";
518 $sql .=
", " . $this->db->ifsql(
'eb.rowid IS NULL',
'ed.fk_entrepot',
'eb.fk_warehouse') .
" as fk_warehouse";
519 $sql .=
", eb.batch, eb.eatby, eb.sellby";
521 $sql .=
" FROM " . $this->db->prefix() . $this->table_element .
" as ed";
522 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"expeditiondet_batch as eb ON eb.fk_expeditiondet = " . ((int) $line_id);
523 $sql .=
" WHERE ed.fk_parent = " . ((int) $line_id);
524 $sql .= $this->db->order(
'ed.fk_product,ed.rowid',
'ASC,ASC');
526 $resql = $this->db->query($sql);
528 while ($obj = $this->db->fetch_object($resql)) {
529 $child_line_id = (int) $obj->child_line_id;
530 if (!isset($list[$line_id])) {
531 $list[$line_id] = array();
535 $list[$line_id][] = $child_line_id;
536 } elseif ($mode == 1) {
538 $line_obj->rowid = $child_line_id;
539 $line_obj->fk_product = $obj->fk_product;
540 $line_obj->fk_parent = $obj->fk_parent;
541 $line_obj->qty = $obj->qty;
542 $line_obj->fk_warehouse = $obj->fk_warehouse;
543 $line_obj->batch = $obj->batch;
544 $line_obj->eatby = $obj->eatby;
545 $line_obj->sellby = $obj->sellby;
546 $line_obj->iskit = 0;
547 $line_obj->incdec = 0;
548 $list[$line_id][] = $line_obj;
553 $this->db->free($resql);
555 $this->error = $this->db->lasterror();
556 $this->errors[] = $this->error;
557 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
571 public function delete($user =
null, $notrigger = 0)
579 if ((
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS') || $this->element_type ==
'shipping') && !($this->fk_parent > 0)) {
581 $line_id_list = array();
582 $result = $this->
findAllChild($this->
id, $line_id_list);
584 $child_line_id_list = array_reverse($line_id_list,
true);
585 foreach ($child_line_id_list as $child_line_id_arr) {
586 foreach ($child_line_id_arr as $child_line_id) {
589 $sql =
"DELETE FROM " . $this->db->prefix() .
"expeditiondet_batch";
590 $sql .=
" WHERE fk_expeditiondet = " . ((int) $child_line_id);
591 if (!$this->db->query($sql)) {
593 $this->errors[] = $this->db->lasterror() .
" - sql=$sql";
597 $sql =
"DELETE FROM " . $this->db->prefix() .
"expeditiondet";
598 $sql .=
" WHERE rowid = " . ((int) $child_line_id);
599 if (!$this->db->query($sql)) {
601 $this->errors[] = $this->db->lasterror() .
" - sql=$sql";
620 $sql =
"DELETE FROM ".$this->db->prefix().
"expeditiondet_batch";
621 $sql .=
" WHERE fk_expeditiondet = ".((int) $this->
id);
623 if (!$this->db->query($sql)) {
624 $this->errors[] = $this->db->lasterror().
" - sql=$sql";
629 $sql =
"DELETE FROM ".$this->db->prefix().
"expeditiondet";
630 $sql .=
" WHERE rowid = ".((int) $this->
id);
632 if (!$error && $this->db->query($sql)) {
637 $this->errors[] = $this->error;
641 if (!$error && !$notrigger) {
643 $result = $this->call_trigger(
'LINESHIPPING_DELETE', $user);
645 $this->errors[] = $this->error;
651 $this->errors[] = $this->db->lasterror().
" - sql=$sql";
660 foreach ($this->errors as $errmsg) {
661 dol_syslog(get_class($this).
"::delete ".$errmsg, LOG_ERR);
662 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
664 $this->db->rollback();
676 public function update($user =
null, $notrigger = 0)
681 dol_syslog(get_class($this).
"::update id=$this->id, entrepot_id=$this->entrepot_id, product_id=$this->fk_product, qty=$this->qty");
685 if (!empty($this->
id) && empty($this->fk_elementdet)) {
686 $sql =
"SELECT fk_elementdet FROM ".MAIN_DB_PREFIX.
"expeditiondet";
687 $sql .=
" WHERE rowid = ".((int) $this->
id);
688 $resql = $this->db->query($sql);
690 $obj = $this->db->fetch_object($resql);
692 $this->fk_elementdet = $obj->fk_elementdet;
697 if (
getDolGlobalString(
'STOCK_EXPEDITION_NO_MORE_THAN_ORDER') && !empty($this->fk_elementdet)) {
698 $qty_to_check = $this->qty;
699 if (!empty($this->detail_batch)) {
700 if (is_array($this->detail_batch)) {
701 $qty_to_check = array_sum(array_column($this->detail_batch,
'qty'));
703 $qty_to_check = $this->detail_batch->qty;
707 if (!empty($this->error)) {
708 $this->db->rollback();
714 if (empty($this->qty)) {
718 $fk_unit = $this->fk_unit;
722 $expedition_batch_id = 0;
723 $origin_id = $this->origin_id;
724 if ($origin_id > 0) {
725 if (is_array($this->detail_batch)) {
726 if (count($this->detail_batch) > 1) {
727 dol_syslog(get_class($this).
'::update only possible for one batch', LOG_ERR);
728 $this->errors[] =
'ErrorBadParameters';
731 $batch = $this->detail_batch[0]->batch;
732 $batch_id = $this->detail_batch[0]->fk_origin_stock;
733 $expedition_batch_id = $this->detail_batch[0]->id;
734 if ($this->entrepot_id != $this->detail_batch[0]->entrepot_id) {
735 dol_syslog(get_class($this).
'::update only possible for batch of same warehouse', LOG_ERR);
736 $this->errors[] =
'ErrorBadParameters';
739 $qty =
price2num($this->detail_batch[0]->qty);
741 } elseif (!empty($this->detail_batch)) {
742 $batch = $this->detail_batch->batch;
743 $batch_id = $this->detail_batch->fk_origin_stock;
744 $expedition_batch_id = $this->detail_batch->id;
745 if ($this->entrepot_id != $this->detail_batch->entrepot_id) {
746 dol_syslog(get_class($this).
'::update only possible for batch of same warehouse', LOG_ERR);
747 $this->errors[] =
'ErrorBadParameters';
750 $qty =
price2num($this->detail_batch->qty);
754 if (!isset($this->
id) || !isset($this->entrepot_id)) {
755 dol_syslog(get_class($this).
'::update missing line id and/or warehouse id', LOG_ERR);
756 $langs->load(
'errors');
757 $this->errors[] = $langs->trans(
'ErrorMandatoryParametersNotProvided');
764 $batch_id_str = $batch_id ??
'null';
765 dol_syslog(get_class($this).
"::update expedition batch id=$expedition_batch_id, batch_id=$batch_id_str, batch=$batch");
767 if (empty($batch_id) || empty($this->fk_product)) {
768 dol_syslog(get_class($this).
'::update missing fk_origin_stock (batch_id) and/or fk_product', LOG_ERR);
769 $langs->load(
'errors');
770 $this->errors[] = $langs->trans(
'ErrorMandatoryParametersNotProvided');
776 $lotArray = $shipmentlinebatch->fetchAll($this->
id);
777 if (!$error && $lotArray < 0) {
778 $this->errors[] = $this->db->lasterror().
" - ExpeditionLineBatch::fetchAll";
782 foreach ($lotArray as $lot) {
783 if ($expedition_batch_id != $lot->id) {
784 $remainingQty += $lot->qty;
787 $qty += $remainingQty;
791 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/productlot.class.php';
793 if ($lot->fetch(0, $this->fk_product, $batch) < 0) {
794 $this->errors = array_merge($this->errors, $lot->errors);
797 if (!$error && !empty($expedition_batch_id)) {
799 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"expeditiondet_batch";
800 $sql .=
" WHERE fk_expeditiondet = ".((int) $this->
id);
801 $sql .=
" AND rowid = ".((int) $expedition_batch_id);
803 if (!$this->db->query($sql)) {
804 $this->errors[] = $this->db->lasterror().
" - sql=$sql";
808 if (!$error && $this->detail_batch->qty > 0) {
810 if (isset($lot->id)) {
812 $shipmentLot->batch = $lot->batch;
813 $shipmentLot->eatby = $lot->eatby;
814 $shipmentLot->sellby = $lot->sellby;
815 $shipmentLot->fk_warehouse = $this->detail_batch->entrepot_id;
816 $shipmentLot->qty = $this->detail_batch->qty;
817 $shipmentLot->fk_origin_stock = (int) $batch_id;
818 if ($shipmentLot->create($this->id) < 0) {
819 $this->errors = $shipmentLot->errors;
829 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element.
" SET";
830 $sql .=
" fk_entrepot = ".($this->entrepot_id > 0 ? ((int) $this->entrepot_id) :
'null');
831 $sql .=
" , qty = ".((float)
price2num($qty,
'MS'));
832 $sql .=
" , fk_unit = ".((int) $this->fk_unit);
833 $sql .=
" WHERE rowid = ".((int) $this->
id);
835 if (!$this->db->query($sql)) {
836 $this->errors[] = $this->db->lasterror().
" - sql=$sql";
844 $this->errors[] = $this->error;
849 if (!$error && !$notrigger) {
851 $result = $this->call_trigger(
'LINESHIPPING_MODIFY', $user);
853 $this->errors[] = $this->error;
862 foreach ($this->errors as $errmsg) {
863 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
864 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
866 $this->db->rollback();
885 require_once DOL_DOCUMENT_ROOT.
'/commande/class/commande.class.php';
887 if ($orderline->fetch($fk_elementdet) <= 0) {
890 if ($orderline->product_type == 9) {
893 $qty_ordered = (float) $orderline->qty;
896 $sql =
"SELECT COALESCE(SUM(ed.qty), 0) as qty_shipped";
897 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expeditiondet as ed";
898 $sql .=
" INNER JOIN ".MAIN_DB_PREFIX.
"expedition as e ON e.rowid = ed.fk_expedition";
899 $sql .=
" WHERE ed.fk_elementdet = ".((int) $fk_elementdet);
900 $sql .=
" AND e.fk_statut >= 0";
901 if ($exclude_line_id > 0) {
902 $sql .=
" AND ed.rowid != ".((int) $exclude_line_id);
905 $resql = $this->db->query($sql);
909 $obj = $this->db->fetch_object($resql);
910 $qty_already_shipped = $obj ? (float) $obj->qty_shipped : 0;
912 $qty_remaining = $qty_ordered - $qty_already_shipped;
914 if ($qty > $qty_remaining) {
915 $langs->load(
'errors');
916 $product_ref = !empty($orderline->product_ref) ? $orderline->product_ref : $orderline->desc;
917 $this->error = $langs->trans(
'ErrorExpeditionQtyTooHigh', $qty, max(0, $qty_remaining), $product_ref);