39require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
40require_once DOL_DOCUMENT_ROOT.
"/expedition/class/expeditionligne.class.php";
41require_once DOL_DOCUMENT_ROOT.
'/core/class/commonincoterm.class.php';
42if (isModEnabled(
"propal")) {
43 require_once DOL_DOCUMENT_ROOT.
'/comm/propal/class/propal.class.php';
45if (isModEnabled(
'order')) {
46 require_once DOL_DOCUMENT_ROOT.
'/commande/class/commande.class.php';
48require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expeditionlinebatch.class.php';
49require_once DOL_DOCUMENT_ROOT.
'/core/class/commonsignedobject.class.php';
50require_once DOL_DOCUMENT_ROOT.
'/subtotals/class/commonsubtotal.class.php';
60 use CommonSignedObject;
66 public $element =
"shipping";
71 public $fk_element =
"fk_expedition";
76 public $table_element =
"expedition";
81 public $table_element_line =
"expeditiondet";
86 public $picto =
'dolly';
92 public $fields = array();
97 public $user_author_id;
102 public $fk_user_author;
119 public $ref_customer;
129 public $tracking_number;
134 public $tracking_url;
147 public $weight_units;
163 public $height_units;
180 public $livraison_id;
185 public $multicurrency_subprice;
215 public $date_delivery;
229 public $date_expedition;
235 public $date_shipping;
264 public $lines = array();
270 public $fk_multicurrency;
275 public $multicurrency_code;
279 public $multicurrency_tx;
283 public $multicurrency_total_ht;
287 public $multicurrency_total_tva;
291 public $multicurrency_total_ttc;
338 $this->ismultientitymanaged = 1;
339 $this->isextrafieldmanaged = 1;
342 $this->labelStatus = array();
343 $this->labelStatus[-1] =
'StatusSendingCanceled';
344 $this->labelStatus[0] =
'StatusSendingDraft';
345 $this->labelStatus[1] =
'StatusSendingValidated';
346 $this->labelStatus[2] =
'StatusSendingProcessed';
349 $this->labelStatusShort = array();
350 $this->labelStatusShort[-1] =
'StatusSendingCanceledShort';
351 $this->labelStatusShort[0] =
'StatusSendingDraftShort';
352 $this->labelStatusShort[1] =
'StatusSendingValidatedShort';
353 $this->labelStatusShort[2] =
'StatusSendingProcessedShort';
364 global $langs,
$conf;
365 $langs->load(
"sendings");
374 $dirmodels = array_merge(array(
'/'), (array)
$conf->modules_parts[
'models']);
376 foreach ($dirmodels as $reldir) {
380 $mybool = ((bool) @include_once $dir.$file) || $mybool;
388 $obj =
new $classname();
389 '@phan-var-force ModelNumRefExpedition $obj';
390 $numref = $obj->getNextValue($soc, $this);
395 dol_print_error($this->db, get_class($this).
"::getNextNumRef ".$obj->error);
399 print $langs->trans(
"Error").
" ".$langs->trans(
"Error_EXPEDITION_ADDON_NUMBER_NotDefined");
411 public function create($user, $notrigger = 0)
415 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
420 if (empty($this->fk_project)) {
421 $this->fk_project = 0;
423 if (empty($this->date_creation)) {
424 $this->date_creation = $now;
426 if (empty($this->date_shipping) && !empty($this->date_expedition)) {
427 $this->date_shipping = $this->date_expedition;
435 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"expedition (";
438 $sql .=
", ref_customer";
440 $sql .=
", date_creation";
441 $sql .=
", fk_user_author";
442 $sql .=
", date_expedition";
443 $sql .=
", date_delivery";
445 $sql .=
", fk_projet";
446 $sql .=
", fk_address";
447 $sql .=
", fk_shipping_method";
448 $sql .=
", tracking_number";
453 $sql .=
", weight_units";
454 $sql .=
", size_units";
455 $sql .=
", note_private";
456 $sql .=
", note_public";
457 $sql .=
", model_pdf";
458 $sql .=
", fk_incoterms, location_incoterms";
459 $sql .=
", signed_status";
460 $sql .=
") VALUES (";
462 $sql .=
", ".((int) $this->entity);
463 $sql .=
", ".($this->ref_customer ?
"'".$this->db->escape($this->ref_customer).
"'" :
"null");
464 $sql .=
", ".($this->ref_ext ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
465 $sql .=
", '".$this->db->idate($this->date_creation).
"'";
466 $sql .=
", ".((int) $user->id);
467 $sql .=
", ".($this->date_shipping > 0 ?
"'".$this->db->idate($this->date_shipping).
"'" :
"null");
468 $sql .=
", ".($this->date_delivery > 0 ?
"'".$this->db->idate($this->date_delivery).
"'" :
"null");
469 $sql .=
", ".($this->socid > 0 ? ((int) $this->socid) :
"null");
470 $sql .=
", ".($this->fk_project > 0 ? ((int) $this->fk_project) :
"null");
471 $sql .=
", ".($this->fk_delivery_address > 0 ? $this->fk_delivery_address :
"null");
472 $sql .=
", ".($this->shipping_method_id > 0 ? ((int) $this->shipping_method_id) :
"null");
473 $sql .=
", '".$this->db->escape($this->tracking_number).
"'";
474 $sql .=
", ".(is_numeric($this->weight) ? $this->weight :
'NULL');
475 $sql .=
", ".(is_numeric($this->sizeS) ? $this->sizeS :
'NULL');
476 $sql .=
", ".(is_numeric($this->sizeW) ? $this->sizeW :
'NULL');
477 $sql .=
", ".(is_numeric($this->sizeH) ? $this->sizeH :
'NULL');
478 $sql .=
", ".($this->weight_units !=
'' ? (int) $this->weight_units :
'NULL');
479 $sql .=
", ".($this->size_units !=
'' ? (int) $this->size_units :
'NULL');
480 $sql .=
", ".(!empty($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null");
481 $sql .=
", ".(!empty($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null");
482 $sql .=
", ".(!empty($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null");
483 $sql .=
", ".(int) $this->fk_incoterms;
484 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
485 $sql .=
", ".($this->signed_status);
488 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
489 $resql = $this->db->query($sql);
491 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
"expedition");
493 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
494 $sql .=
" SET ref = '(PROV".$this->id.
")'";
495 $sql .=
" WHERE rowid = ".((int) $this->
id);
497 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
498 if ($this->db->query($sql)) {
500 $num = count($this->lines);
501 $kits_list = array();
503 for ($i = 0; $i < $num; $i++) {
505 $objectsrc->fetch($this->lines[$i]->origin_line_id);
506 if ($this->lines[$i]->product_type ==
"9" && $objectsrc->special_code == SUBTOTALS_SPECIAL_CODE) {
507 if ($this->
create_line($this->lines[$i]->entrepot_id, $this->lines[$i]->origin_line_id, $this->lines[$i]->qty, $this->lines[$i]->rang, $this->lines[$i]->array_options) <= 0) {
514 $line = $this->lines[$i];
515 if ($line->fk_product > 0) {
521 if (!isset($kits_list[$line->fk_elementdet])) {
522 if (!is_object($line->product)) {
523 $line_product =
new Product($this->db);
524 $result = $line_product->fetch($line->fk_product,
'',
'',
'', 1, 1, 1);
529 $line_product = $line->product;
533 $line_product->get_sousproduits_arbo();
534 $prods_arbo = $line_product->get_arbo_each_prod($line->qty);
535 if (count($prods_arbo) > 0) {
536 $kits_list[$line->fk_elementdet] = array(
537 'arbo' => $prods_arbo,
538 'total_qty' => $line->qty,
542 $kits_list[$line->fk_elementdet][
'total_qty'] += $line->qty;
548 $kits_id_cached = array();
549 $sub_kits_id_cached = array();
550 $sub_parents_cached = array();
551 for ($i = 0; $i < $num; $i++) {
552 $line = $this->lines[$i];
555 if (!isset($kits_id_cached[$line->fk_elementdet])) {
556 if (!isset($line->detail_batch) || (isset($kits_list[$line->fk_elementdet]) && !
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE'))) {
557 $qty = isset($kits_list[$line->fk_elementdet]) ? $kits_list[$line->fk_elementdet][
'total_qty'] : $line->qty;
558 $warehouse_id = (isset($kits_list[$line->fk_elementdet]) && !
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) ? 0 : $line->entrepot_id;
559 $line_id = $this->
create_line($warehouse_id, $line->origin_line_id, $qty, $line->rang, $line->array_options, 0, $line->fk_product);
563 if (isset($kits_list[$line->fk_elementdet])) $kits_id_cached[$line->fk_elementdet] = $line_id;
570 $line_id = $kits_id_cached[$line->fk_elementdet];
574 if (isset($kits_list[$line->fk_elementdet]) && !
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) {
575 $prods_arbo = $kits_list[$line->fk_elementdet][
'arbo'];
578 $parent_line_id = $line_id;
580 $product_child_id = 0;
581 foreach ($prods_arbo as $index => $product_child_arr) {
596 $product_child_level = (int) $product_child_arr[
'level'];
597 $product_child_incdec = !empty($product_child_arr[
'incdec']);
600 if ($product_child_level != $level_last) {
601 $parent_line_id = $line_id;
602 $parent_product_id = $product_child_id;
603 if (isset($sub_parents_cached[$line->fk_elementdet][$parent_product_id])) {
604 $parent_line_id = $sub_parents_cached[$line->fk_elementdet][$parent_product_id];
606 $sub_parents_cached[$line->fk_elementdet][$parent_product_id] = $parent_line_id;
612 $next_level = $product_child_level;
613 $next_index = $index + 1;
614 if (isset($prods_arbo[$next_index])) {
615 $next_level = (int) $prods_arbo[$next_index][
'level'];
617 if ($next_level > $product_child_level) {
622 $product_child_id = (int) $product_child_arr[
'id'];
623 $product_child_qty = (float) $product_child_arr[
'nb_total'];
624 $warehouse_id = $line->entrepot_id;
625 if ($is_kit || !$product_child_incdec) {
626 if (!$product_child_incdec) {
627 $product_child_qty = 0;
633 if (!isset($sub_kits_id_cached[$line->fk_elementdet][$product_child_id]) || $warehouse_id > 0) {
634 $line_id = $this->
create_line($warehouse_id, ($parent_line_id ? 0 : $line->origin_line_id), $product_child_qty, $line->rang, $line->array_options, $parent_line_id, $product_child_id);
642 if (empty($warehouse_id)) {
643 $sub_kits_id_cached[$line->fk_elementdet][$product_child_id] = $line_id;
647 $level_last = $product_child_level;
653 if (!$error && $this->
id && $this->origin_id) {
660 if (!$error && $this->
id &&
getDolGlobalInt(
'SHIPPING_USE_ITS_OWN_CONTACTS') &&
getDolGlobalString(
'MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN') && !empty($this->origin_type) && !empty($this->origin_id)) {
661 $originforcontact = $this->origin_type;
662 $originidforcontact = $this->origin_id;
664 $sqlcontact =
"SELECT ctc.code, ctc.source, ec.fk_socpeople FROM ".MAIN_DB_PREFIX.
"element_contact as ec, ".MAIN_DB_PREFIX.
"c_type_contact as ctc";
665 $sqlcontact .=
" WHERE element_id = ".((int) $originidforcontact).
" AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$this->db->escape($originforcontact).
"'";
667 $resqlcontact = $this->db->query($sqlcontact);
669 while ($objcontact = $this->db->fetch_object($resqlcontact)) {
670 $this->
add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source);
685 if (!$error && !$notrigger) {
687 $result = $this->
call_trigger(
'SHIPPING_CREATE', $user);
697 foreach ($this->errors as $errmsg) {
698 dol_syslog(get_class($this).
"::create ".$errmsg, LOG_ERR);
699 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
701 $this->db->rollback();
706 $this->db->rollback();
711 $this->error = $this->db->lasterror().
" - sql=$sql";
712 $this->db->rollback();
717 $this->error = $this->db->error().
" - sql=$sql";
718 $this->db->rollback();
736 public function create_line($entrepot_id, $origin_line_id, $qty, $rang = 0, $array_options = [], $parent_line_id = 0, $product_id = 0)
742 $expeditionline->fk_expedition = $this->id;
743 $expeditionline->entrepot_id = $entrepot_id;
744 $expeditionline->fk_elementdet = $origin_line_id;
745 $expeditionline->element_type = $this->origin;
746 $expeditionline->fk_parent = $parent_line_id;
747 $expeditionline->fk_product = $product_id;
748 $expeditionline->qty = $qty;
749 $expeditionline->rang = $rang;
750 $expeditionline->array_options = $array_options;
752 if (!($expeditionline->fk_product > 0)) {
754 $order_line->fetch($expeditionline->fk_elementdet);
755 $expeditionline->fk_product = $order_line->fk_product;
758 if (($lineId = $expeditionline->insert($user)) < 0) {
759 $this->errors[] = $expeditionline->error;
777 $stockLocationQty = array();
779 $tab = $line_ext->detail_batch;
781 foreach ($tab as $detbatch) {
782 if (!empty($detbatch->fk_warehouse)) {
783 if (empty($stockLocationQty[$detbatch->fk_warehouse])) {
784 $stockLocationQty[$detbatch->fk_warehouse] = 0;
786 $stockLocationQty[$detbatch->fk_warehouse] += $detbatch->qty;
790 foreach ($stockLocationQty as $stockLocation => $qty) {
791 $line_id = $this->
create_line($stockLocation, $line_ext->origin_line_id, $qty, $line_ext->rang, $array_options);
796 foreach ($tab as $detbatch) {
797 if ($detbatch->fk_warehouse == $stockLocation) {
798 if (!($detbatch->create($line_id) > 0)) {
799 $this->errors = $detbatch->errors;
823 public function fetch($id, $ref =
'', $ref_ext =
'', $notused =
'')
828 if (empty($id) && empty($ref) && empty($ref_ext)) {
832 $sql =
"SELECT e.rowid, e.entity, e.ref, e.fk_soc as socid, e.date_creation, e.ref_customer, e.ref_ext, e.fk_user_author, e.fk_statut, e.signed_status, e.fk_projet as fk_project, e.billed";
833 $sql .=
", e.date_valid";
834 $sql .=
", e.weight, e.weight_units, e.size, e.size_units, e.width, e.height";
835 $sql .=
", e.date_expedition as date_expedition, e.model_pdf, e.fk_address, e.date_delivery";
836 $sql .=
", e.fk_shipping_method, e.tracking_number";
837 $sql .=
", e.note_private, e.note_public";
838 $sql .=
', e.fk_incoterms, e.location_incoterms';
839 $sql .=
', e.signed_status';
840 $sql .=
', i.libelle as label_incoterms';
841 $sql .=
', s.libelle as shipping_method';
842 $sql .=
", el.fk_source as origin_id, el.sourcetype as origin_type";
843 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expedition as e";
844 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"element_element as el ON el.fk_target = e.rowid AND el.targettype = '".$this->db->escape($this->element).
"'";
845 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON e.fk_incoterms = i.rowid';
846 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_shipment_mode as s ON e.fk_shipping_method = s.rowid';
847 $sql .=
" WHERE e.entity IN (".getEntity(
'expedition').
")";
849 $sql .=
" AND e.rowid = ".((int) $id);
852 $sql .=
" AND e.ref='".$this->db->escape($ref).
"'";
855 $sql .=
" AND e.ref_ext='".$this->db->escape($ref_ext).
"'";
858 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
859 $result = $this->db->query($sql);
861 if ($this->db->num_rows($result)) {
862 $obj = $this->db->fetch_object($result);
864 $this->
id = $obj->rowid;
865 $this->entity = $obj->entity;
866 $this->
ref = $obj->ref;
867 $this->socid = $obj->socid;
868 $this->ref_customer = $obj->ref_customer;
869 $this->ref_ext = $obj->ref_ext;
870 $this->
status = $obj->fk_statut;
871 $this->statut = $this->status;
872 $this->signed_status = $obj->signed_status;
873 $this->user_author_id = $obj->fk_user_author;
874 $this->fk_user_author = $obj->fk_user_author;
875 $this->date_creation = $this->db->jdate($obj->date_creation);
876 $this->date_valid = $this->db->jdate($obj->date_valid);
877 $this->date = $this->db->jdate($obj->date_expedition);
878 $this->date_expedition = $this->db->jdate($obj->date_expedition);
879 $this->date_shipping = $this->db->jdate($obj->date_expedition);
880 $this->date_delivery = $this->db->jdate($obj->date_delivery);
881 $this->fk_delivery_address = $obj->fk_address;
882 $this->model_pdf = $obj->model_pdf;
883 $this->shipping_method_id = $obj->fk_shipping_method;
884 $this->shipping_method = $obj->shipping_method;
885 $this->tracking_number = $obj->tracking_number;
886 $this->origin = ($obj->origin_type ? $obj->origin_type :
'commande');
887 $this->origin_type = ($obj->origin_type ? $obj->origin_type :
'commande');
888 $this->origin_id = $obj->origin_id;
889 $this->billed = $obj->billed;
890 $this->fk_project = $obj->fk_project;
891 $this->signed_status = $obj->signed_status;
892 $this->trueWeight = $obj->weight;
893 $this->weight_units = $obj->weight_units;
895 $this->trueWidth = $obj->width;
896 $this->width_units = $obj->size_units;
897 $this->trueHeight = $obj->height;
898 $this->height_units = $obj->size_units;
899 $this->trueDepth = $obj->size;
900 $this->depth_units = $obj->size_units;
902 $this->note_public = $obj->note_public;
903 $this->note_private = $obj->note_private;
906 $this->trueSize = $obj->size.
"x".$obj->width.
"x".$obj->height;
907 $this->size_units = $obj->size_units;
910 $this->fk_incoterms = $obj->fk_incoterms;
911 $this->location_incoterms = $obj->location_incoterms;
912 $this->label_incoterms = $obj->label_incoterms;
914 $this->db->free($result);
926 if (isModEnabled(
'multicurrency')) {
927 if (!empty($this->multicurrency_code)) {
928 $this->multicurrency_code = $this->thirdparty->multicurrency_code;
930 if (
getDolGlobalString(
'MULTICURRENCY_USE_ORIGIN_TX') && !empty($this->thirdparty->multicurrency_tx)) {
931 $this->multicurrency_tx = $this->thirdparty->multicurrency_tx;
945 dol_syslog(get_class($this).
'::Fetch no expedition found', LOG_ERR);
946 $this->error =
'Shipment with id '.$id.
' not found';
950 $this->error = $this->db->error();
962 public function valid($user, $notrigger = 0)
966 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
972 dol_syslog(get_class($this).
"::valid not in draft status", LOG_WARNING);
976 if (!((!
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'expedition',
'creer'))
977 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'expedition',
'shipping_advance',
'validate')))) {
978 $this->error =
'Permission denied';
979 dol_syslog(get_class($this).
"::valid ".$this->error, LOG_ERR);
989 $soc->fetch($this->socid);
992 $result = $soc->setAsCustomer();
995 if (!$error && (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref))) {
997 } elseif (!empty($this->
ref)) {
998 $numref = $this->ref;
1000 $numref =
"EXP".$this->id;
1007 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition SET";
1008 $sql .=
" ref='".$this->db->escape($numref).
"'";
1009 $sql .=
", fk_statut = 1";
1010 $sql .=
", date_valid = '".$this->db->idate($now).
"'";
1011 $sql .=
", fk_user_valid = ".((int) $user->id);
1012 $sql .=
" WHERE rowid = ".((int) $this->
id);
1014 dol_syslog(get_class($this).
"::valid update expedition", LOG_DEBUG);
1015 $resql = $this->db->query($sql);
1017 $this->error = $this->db->lasterror();
1022 if (!$error && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT')) {
1030 $triggerKey =
'SHIPPING_';
1031 if ($this->origin ==
'commande') {
1032 $triggerKey.=
'ORDER_SHIPMENTONPROCESS';
1034 $triggerKey.= strtoupper($this->origin).
'_SHIPMENTONPROCESS';
1043 if (!$error && !$notrigger) {
1045 $result = $this->
call_trigger(
'SHIPPING_VALIDATE', $user);
1053 $this->oldref = $this->ref;
1056 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
1058 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filename = CONCAT('".$this->db->escape($this->newref).
"', SUBSTR(filename, ".(strlen($this->
ref) + 1).
")), filepath = 'expedition/sending/".$this->db->escape($this->newref).
"'";
1059 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'expedition/sending/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
1060 $resql = $this->db->query($sql);
1063 $this->error = $this->db->lasterror();
1065 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'expedition/sending/".$this->db->escape($this->newref).
"'";
1066 $sql .=
" WHERE filepath = 'expedition/sending/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
1067 $resql = $this->db->query($sql);
1070 $this->error = $this->db->lasterror();
1076 $dirsource =
$conf->expedition->dir_output.
'/sending/'.$oldref;
1077 $dirdest =
$conf->expedition->dir_output.
'/sending/'.$newref;
1078 if (!$error && file_exists($dirsource)) {
1079 dol_syslog(get_class($this).
"::valid rename dir ".$dirsource.
" into ".$dirdest);
1081 if (@rename($dirsource, $dirdest)) {
1084 $listoffiles =
dol_dir_list(
$conf->expedition->dir_output.
'/sending/'.$newref,
'files', 1,
'^'.preg_quote($oldref,
'/'));
1085 foreach ($listoffiles as $fileentry) {
1086 $dirsource = $fileentry[
'name'];
1087 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
1088 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
1089 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
1090 @rename($dirsource, $dirdest);
1099 $this->
ref = $numref;
1105 $this->db->commit();
1108 $this->db->rollback();
1127 if ($this->
status == self::STATUS_VALIDATED || $this->
status == self::STATUS_CLOSED) {
1129 include_once DOL_DOCUMENT_ROOT.
'/delivery/class/delivery.class.php';
1130 $delivery =
new Delivery($this->db);
1131 $result = $delivery->create_from_sending($user, $this->
id);
1135 $this->error = $delivery->error;
1160 public function addline($entrepot_id, $id, $qty, $array_options = [], $fk_product = 0, $fk_parent = 0)
1162 global
$conf, $langs;
1164 $num = count($this->lines);
1167 $line->entrepot_id = $entrepot_id;
1168 $line->origin_line_id = $id;
1169 $line->fk_elementdet = $id;
1170 $line->element_type =
'order';
1171 $line->fk_parent = $fk_parent;
1172 $line->fk_product = $fk_product;
1176 $orderline->fetch($id);
1179 $line->rang = $orderline->rang;
1180 $line->product_type = $orderline->product_type;
1181 if (!($line->fk_product > 0)) {
1182 $line->fk_product = $orderline->fk_product;
1185 if (isModEnabled(
'stock') && !empty($orderline->fk_product)) {
1186 $product =
new Product($this->db);
1187 $product->fetch($orderline->fk_product);
1190 $langs->load(
"errors");
1191 $this->error = $langs->trans(
"ErrorWarehouseRequiredIntoShipmentLine");
1196 $productChildrenNb = 0;
1198 $productChildrenNb = $product->hasFatherOrChild(1);
1200 if ($productChildrenNb > 0) {
1201 $product_stock =
null;
1202 $product->loadStockForVirtualProduct(
'warehouseopen', $line->qty);
1203 if ($entrepot_id > 0) {
1204 if (isset($product->stock_warehouse[$entrepot_id])) {
1205 $product_stock = $product->stock_warehouse[$entrepot_id]->real;
1208 foreach ($product->stock_warehouse as $componentStockWarehouse) {
1209 if ($product_stock ===
null) {
1210 $product_stock = $componentStockWarehouse->real;
1212 $product_stock = min($product_stock, $componentStockWarehouse->real);
1216 if ($product_stock ===
null) {
1221 if ($entrepot_id > 0) {
1222 $product->load_stock(
'warehouseopen');
1223 $product_stock = $product->stock_warehouse[$entrepot_id]->real;
1225 $product_stock = $product->stock_reel;
1229 $product_type = $product->type;
1231 $isavirtualproduct = ($productChildrenNb > 0);
1234 if ($product->stockable_product == Product::ENABLED_STOCK && $product_stock < $qty) {
1235 $langs->load(
"errors");
1236 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnShipment', $product->ref);
1237 $this->errorhidden =
'ErrorStockIsNotEnoughToAddProductOnShipment';
1239 $this->db->rollback();
1249 if (isModEnabled(
'productbatch') && !empty($line->fk_product) && !empty($orderline->product_tobatch)) {
1250 $this->error =
'ADDLINE_WAS_CALLED_INSTEAD_OF_ADDLINEBATCH '.$orderline->id.
' '.$line->fk_product;
1255 if (!
getDolGlobalString(
'MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) {
1256 $line->array_options = $array_options;
1259 $this->lines[$num] = $line;
1273 public function addline_batch($dbatch, $array_options = [], $origin_line =
null)
1276 global
$conf, $langs;
1278 $num = count($this->lines);
1280 if ($dbatch[
'qty'] > 0 || ($dbatch[
'qty'] == 0 &&
getDolGlobalString(
'SHIPMENT_GETS_ALL_ORDER_PRODUCTS'))) {
1283 foreach ($dbatch[
'detail'] as $key => $value) {
1284 if ($value[
'q'] > 0 || ($value[
'q'] == 0 &&
getDolGlobalString(
'SHIPMENT_GETS_ALL_ORDER_PRODUCTS'))) {
1290 $ret = $linebatch->fetchFromStock($value[
'id_batch']);
1295 $linebatch->qty = $value[
'q'];
1296 if ($linebatch->qty == 0 &&
getDolGlobalString(
'SHIPMENT_GETS_ALL_ORDER_PRODUCTS')) {
1297 $linebatch->batch =
null;
1299 $tab[] = $linebatch;
1302 require_once DOL_DOCUMENT_ROOT.
'/product/class/productbatch.class.php';
1304 $prod_batch->fetch($value[
'id_batch']);
1306 if ($prod_batch->qty < $linebatch->qty) {
1307 $langs->load(
"errors");
1308 $this->errors[] = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnShipment', $prod_batch->fk_product);
1309 dol_syslog(get_class($this).
"::addline_batch error=Product ".$prod_batch->batch.
": ".$this->errorsToString(), LOG_ERR);
1310 $this->db->rollback();
1318 if (is_object($linebatch)) {
1319 $line->entrepot_id = $linebatch->fk_warehouse;
1321 $line->origin_line_id = $dbatch[
'ix_l'];
1322 $line->fk_elementdet = $dbatch[
'ix_l'];
1323 $line->qty = $dbatch[
'qty'];
1324 $line->detail_batch = $tab;
1325 if (!($line->rang > 0)) {
1326 $line->rang = $origin_line->rang;
1328 if (!($line->fk_product > 0)) {
1329 $line->fk_product = $origin_line->fk_product;
1333 if (!
getDolGlobalString(
'MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) {
1334 $line->array_options = $array_options;
1338 $this->lines[$num] = $line;
1351 public function update($user =
null, $notrigger = 0)
1358 if (isset($this->
ref)) {
1359 $this->
ref = trim($this->
ref);
1361 if (isset($this->entity)) {
1362 $this->entity = (int) $this->entity;
1364 if (isset($this->ref_customer)) {
1365 $this->ref_customer = trim($this->ref_customer);
1367 if (isset($this->socid)) {
1368 $this->socid = (int) $this->socid;
1370 if (isset($this->fk_user_author)) {
1371 $this->fk_user_author = (int) $this->fk_user_author;
1373 if (isset($this->fk_user_valid)) {
1375 $this->fk_user_valid = (int) $this->fk_user_valid;
1377 if (isset($this->fk_delivery_address)) {
1378 $this->fk_delivery_address = (int) $this->fk_delivery_address;
1380 if (isset($this->shipping_method_id)) {
1381 $this->shipping_method_id = (int) $this->shipping_method_id;
1383 if (isset($this->tracking_number)) {
1384 $this->tracking_number = trim($this->tracking_number);
1386 if (isset($this->statut)) {
1387 $this->statut = (int) $this->statut;
1389 if (isset($this->
status)) {
1392 if (isset($this->trueDepth)) {
1393 $this->trueDepth = trim($this->trueDepth);
1395 if (isset($this->trueWidth)) {
1396 $this->trueWidth = trim($this->trueWidth);
1398 if (isset($this->trueHeight)) {
1399 $this->trueHeight = trim($this->trueHeight);
1401 if (isset($this->size_units)) {
1402 $this->size_units = trim($this->size_units);
1404 if (isset($this->weight_units)) {
1405 $this->weight_units = (int) $this->weight_units;
1407 if (isset($this->trueWeight)) {
1408 $this->weight = trim((
string) $this->trueWeight);
1410 if (isset($this->note_private)) {
1411 $this->note_private = trim($this->note_private);
1413 if (isset($this->note_public)) {
1414 $this->note_public = trim($this->note_public);
1416 if (isset($this->model_pdf)) {
1417 $this->model_pdf = trim($this->model_pdf);
1419 if (!empty($this->date_expedition)) {
1420 $this->date_shipping = $this->date_expedition;
1427 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition SET";
1428 $sql .=
" ref = ".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
1429 $sql .=
" ref_ext = ".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
1430 $sql .=
" ref_customer = ".(isset($this->ref_customer) ?
"'".$this->db->escape($this->ref_customer).
"'" :
"null").
",";
1431 $sql .=
" fk_soc = ".(isset($this->socid) ? $this->socid :
"null").
",";
1432 $sql .=
" date_creation = ".(dol_strlen($this->date_creation) != 0 ?
"'".$this->db->idate($this->date_creation).
"'" :
'null').
",";
1433 $sql .=
" fk_user_author = ".(isset($this->fk_user_author) ? $this->fk_user_author :
"null").
",";
1434 $sql .=
" date_valid = ".(dol_strlen($this->date_valid) != 0 ?
"'".$this->db->idate($this->date_valid).
"'" :
'null').
",";
1435 $sql .=
" fk_user_valid = ".(isset($this->fk_user_valid) ? $this->fk_user_valid :
"null").
",";
1436 $sql .=
" date_expedition = ".(dol_strlen($this->date_shipping) != 0 ?
"'".$this->db->idate($this->date_shipping).
"'" :
'null').
",";
1437 $sql .=
" date_delivery = ".(dol_strlen($this->date_delivery) != 0 ?
"'".$this->db->idate($this->date_delivery).
"'" :
'null').
",";
1438 $sql .=
" fk_address = ".(isset($this->fk_delivery_address) ? $this->fk_delivery_address :
"null").
",";
1439 $sql .=
" fk_shipping_method = ".((isset($this->shipping_method_id) && $this->shipping_method_id > 0) ? $this->shipping_method_id :
"null").
",";
1440 $sql .=
" tracking_number = ".(isset($this->tracking_number) ?
"'".$this->db->escape($this->tracking_number).
"'" :
"null").
",";
1441 $sql .=
" fk_statut = ".(isset($this->
status) ? $this->
status :
"null").
",";
1442 $sql .=
" fk_projet = ".(isset($this->fk_project) ? $this->fk_project :
"null").
",";
1443 $sql .=
" height = ".(($this->trueHeight !=
'') ? $this->trueHeight :
"null").
",";
1444 $sql .=
" width = ".(($this->trueWidth !=
'') ? $this->trueWidth :
"null").
",";
1445 $sql .=
" size_units = ".(isset($this->size_units) ? $this->size_units :
"null").
",";
1446 $sql .=
" size = ".(($this->trueDepth !=
'') ? $this->trueDepth :
"null").
",";
1447 $sql .=
" weight_units = ".(isset($this->weight_units) ? $this->weight_units :
"null").
",";
1448 $sql .=
" weight = ".(($this->trueWeight !=
'') ? $this->trueWeight :
"null").
",";
1449 $sql .=
" note_private = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
1450 $sql .=
" note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
1451 $sql .=
" model_pdf = ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
1452 $sql .=
" entity = ".((int)
$conf->entity);
1453 $sql .=
" WHERE rowid = ".((int) $this->
id);
1457 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1458 $resql = $this->db->query($sql);
1461 $this->errors[] =
"Error ".$this->db->lasterror();
1472 if (!$error && !$notrigger) {
1474 $result = $this->
call_trigger(
'SHIPPING_MODIFY', $user);
1483 foreach ($this->errors as $errmsg) {
1484 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
1485 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1487 $this->db->rollback();
1490 $this->db->commit();
1503 public function cancel($notrigger = 0, $also_update_stock =
false)
1505 global
$conf, $langs, $user;
1507 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1516 if (isset($this->linkedObjectsIds[
'delivery']) && count($this->linkedObjectsIds[
'delivery']) > 0) {
1517 $this->error =
'ErrorThereIsSomeDeliveries';
1521 if (!$error && !$notrigger) {
1523 $result = $this->
call_trigger(
'SHIPPING_CANCEL', $user);
1531 $can_update_stock = isModEnabled(
'stock') &&
1533 (
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT_CLOSE') && $this->
status == self::STATUS_CLOSED && $also_update_stock));
1535 require_once DOL_DOCUMENT_ROOT.
"/product/stock/class/mouvementstock.class.php";
1537 $langs->load(
"agenda");
1541 $sql .=
" ed.fk_product";
1542 $sql .=
", ed.qty, ed.fk_entrepot, ed.rowid as expeditiondet_id";
1543 $sql .=
", SUM(".$this->db->ifsql(
"pa.rowid IS NOT NULL",
"1",
"0").
") as iskit";
1544 $sql .=
", ".$this->db->ifsql(
"pai.incdec IS NULL",
"1",
"pai.incdec").
" as incdec";
1545 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet as ed";
1546 $sql .=
" LEFT JOIN ".$this->db->prefix().
"product_association as pa ON pa.fk_product_pere = ed.fk_product";
1547 $sql .=
" LEFT JOIN ".$this->db->prefix().
"expeditiondet as edp ON edp.rowid = ed.fk_parent";
1548 $sql .=
" LEFT JOIN ".$this->db->prefix().
"product_association as pai ON pai.fk_product_pere = edp.fk_product AND pai.fk_product_fils = ed.fk_product";
1549 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
1550 $sql .=
" GROUP BY ed.fk_product, ed.qty, ed.fk_entrepot, ed.rowid, pai.incdec";
1551 $sql .= $this->db->order(
"ed.rowid",
"DESC");
1553 dol_syslog(get_class($this).
"::delete select details", LOG_DEBUG);
1554 $resql = $this->db->query($sql);
1556 $cpt = $this->db->num_rows($resql);
1560 for ($i = 0; $i < $cpt; $i++) {
1561 dol_syslog(get_class($this).
"::delete movement index ".$i);
1562 $obj = $this->db->fetch_object($resql);
1563 $line_id = (int) $obj->expeditiondet_id;
1565 if ($can_update_stock && (empty($obj->iskit) ||
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) && !empty($obj->incdec)) {
1568 $mouvS->origin =
'';
1571 if (isModEnabled(
'productbatch')) {
1572 $lotArray = $shipmentlinebatch->fetchAll($obj->expeditiondet_id);
1573 if (!is_array($lotArray)) {
1575 $this->errors[] =
"Error ".$this->db->lasterror();
1579 if (empty($lotArray)) {
1583 $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $obj->qty, 0, $langs->trans(
"ShipmentCanceledInDolibarr", $this->ref),
'',
'',
'',
'', 0,
'', 0, (empty($obj->iskit) ? 1 : 0));
1586 $this->errors = array_merge($this->errors, $mouvS->errors);
1592 foreach ($lotArray as $lot) {
1593 $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $lot->qty, 0, $langs->trans(
"ShipmentCanceledInDolibarr", $this->ref), $lot->eatby, $lot->sellby, (
string) $lot->batch,
'', 0,
'', 0, (empty($obj->iskit) ? 1 : 0));
1596 $this->errors = array_merge($this->errors, $mouvS->errors);
1609 $res = $shipment_line->fetch($line_id);
1611 $result = $shipment_line->delete($user);
1614 $this->errors[] =
"Error ".$shipment_line->errorsToString();
1618 $this->errors[] =
"Error ".$shipment_line->errorsToString();
1628 $this->errors[] =
"Error ".$this->db->lasterror();
1641 $sql =
"SELECT rowid FROM ".$this->db->prefix().
"expedition";
1642 $sql .=
" WHERE rowid = ".((int) $this->
id);
1644 if ($this->db->query($sql)) {
1645 if (!empty($this->origin) && $this->origin_id > 0) {
1648 '@phan-var-force Facture|Commande $origin_object';
1660 $this->db->commit();
1664 if (!empty(
$conf->expedition->dir_output)) {
1665 $dir =
$conf->expedition->dir_output.
'/sending/'.$ref;
1666 $file = $dir.
'/'.$ref.
'.pdf';
1667 if (file_exists($file)) {
1672 if (file_exists($dir)) {
1674 $this->error = $langs->trans(
"ErrorCanNotDeleteDir", $dir);
1682 $this->db->rollback();
1686 $this->error = $this->db->lasterror().
" - sql=$sql";
1687 $this->db->rollback();
1691 $this->db->rollback();
1695 $this->db->rollback();
1709 public function delete($user =
null, $notrigger = 0, $also_update_stock =
false)
1711 global
$conf, $langs;
1717 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1726 if (isset($this->linkedObjectsIds[
'delivery']) && count($this->linkedObjectsIds[
'delivery']) > 0) {
1727 $this->error =
'ErrorThereIsSomeDeliveries';
1731 if (!$error && !$notrigger) {
1733 $result = $this->
call_trigger(
'SHIPPING_DELETE', $user);
1741 $can_update_stock = isModEnabled(
'stock') &&
1743 (
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT_CLOSE') && $this->
status == self::STATUS_CLOSED && $also_update_stock));
1745 require_once DOL_DOCUMENT_ROOT.
"/product/stock/class/mouvementstock.class.php";
1747 $langs->load(
"agenda");
1754 $sql .=
" ed.fk_product";
1755 $sql .=
", ed.qty, ed.fk_entrepot, ed.rowid as expeditiondet_id";
1756 $sql .=
", SUM(".$this->db->ifsql(
"pa.rowid IS NOT NULL",
"1",
"0").
") as iskit";
1757 $sql .=
", ".$this->db->ifsql(
"pai.incdec IS NULL",
"1",
"pai.incdec").
" as incdec";
1758 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet as ed";
1759 $sql .=
" LEFT JOIN ".$this->db->prefix().
"product_association as pa ON pa.fk_product_pere = ed.fk_product";
1760 $sql .=
" LEFT JOIN ".$this->db->prefix().
"expeditiondet as edp ON edp.rowid = ed.fk_parent";
1761 $sql .=
" LEFT JOIN ".$this->db->prefix().
"product_association as pai ON pai.fk_product_pere = edp.fk_product AND pai.fk_product_fils = ed.fk_product";
1762 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
1763 $sql .=
" GROUP BY ed.fk_product, ed.qty, ed.fk_entrepot, ed.rowid, pai.incdec";
1764 $sql .= $this->db->order(
"ed.rowid",
"DESC");
1766 dol_syslog(get_class($this).
"::delete select details", LOG_DEBUG);
1767 $resql = $this->db->query($sql);
1769 $cpt = $this->db->num_rows($resql);
1770 for ($i = 0; $i < $cpt; $i++) {
1771 dol_syslog(get_class($this).
"::delete movement index ".$i);
1772 $obj = $this->db->fetch_object($resql);
1773 $line_id = (int) $obj->expeditiondet_id;
1775 if ($can_update_stock && (empty($obj->iskit) ||
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) && !empty($obj->incdec)) {
1778 $mouvS->origin =
'';
1780 $lotArray = $shipmentlinebatch->fetchAll($line_id);
1781 if (!is_array($lotArray)) {
1783 $this->errors[] =
"Error ".$this->db->lasterror();
1785 if (empty($lotArray)) {
1789 $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $obj->qty, 0, $langs->trans(
"ShipmentDeletedInDolibarr", $this->ref),
'',
'',
'',
'', 0,
'', 0, (empty($obj->iskit) ? 1 : 0));
1792 $this->errors = array_merge($this->errors, $mouvS->errors);
1798 foreach ($lotArray as $lot) {
1799 if (empty($lot->qty)) {
1802 $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $lot->qty, 0, $langs->trans(
"ShipmentDeletedInDolibarr", $this->ref), $lot->eatby, $lot->sellby, (
string) $lot->batch,
'', 0,
'', 0, (empty($obj->iskit) ? 1 : 0));
1805 $this->errors = array_merge($this->errors, $mouvS->errors);
1818 $res = $shipment_line->fetch($line_id);
1820 $result = $shipment_line->delete($user);
1823 $this->errors[] =
"Error ".$shipment_line->errorsToString();
1827 $this->errors[] =
"Error ".$shipment_line->errorsToString();
1837 $this->errors[] =
"Error ".$this->db->lasterror();
1862 $sql =
"DELETE FROM ".$this->db->prefix().
"expedition";
1863 $sql .=
" WHERE rowid = ".((int) $this->
id);
1865 if ($this->db->query($sql)) {
1866 if (!empty($this->origin) && $this->origin_id > 0) {
1869 '@phan-var-force Facture|Commande $origin_object';
1881 $this->db->commit();
1889 if (!empty(
$conf->expedition->dir_output)) {
1890 $dir =
$conf->expedition->dir_output .
'/sending/' . $ref;
1891 $file = $dir .
'/' . $ref .
'.pdf';
1892 if (file_exists($file)) {
1897 if (file_exists($dir)) {
1899 $this->error = $langs->trans(
"ErrorCanNotDeleteDir", $dir);
1907 $this->db->rollback();
1911 $this->error = $this->db->lasterror().
" - sql=$sql";
1912 $this->db->rollback();
1916 $this->db->rollback();
1920 $this->db->rollback();
1936 $this->lines = array();
1941 $sql =
"SELECT cd.rowid, cd.fk_product, cd.label as custom_label, cd.description, cd.qty as qty_asked, cd.product_type, cd.fk_unit";
1942 $sql .=
", cd.total_ht, cd.total_localtax1, cd.total_localtax2, cd.total_ttc, cd.total_tva";
1943 $sql .=
", cd.fk_remise_except, cd.fk_product_fournisseur_price as fk_fournprice";
1944 $sql .=
", cd.vat_src_code, cd.tva_tx, cd.localtax1_tx, cd.localtax2_tx, cd.localtax1_type, cd.localtax2_type, cd.info_bits, cd.price, cd.subprice, cd.remise_percent,cd.buy_price_ht as pa_ht";
1945 $sql .=
", cd.fk_multicurrency, cd.multicurrency_code, cd.multicurrency_subprice, cd.multicurrency_total_ht, cd.multicurrency_total_tva, cd.multicurrency_total_ttc, cd.rang, cd.date_start, cd.date_end, cd.special_code";
1946 $sql .=
", ed.rowid as line_id, ed.qty as qty_shipped, ed.fk_element, ed.fk_elementdet, ed.element_type, ed.fk_entrepot, ed.extraparams";
1947 $sql .=
", p.ref as product_ref, p.label as product_label, p.fk_product_type, p.barcode as product_barcode";
1948 $sql .=
", p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units";
1949 $sql .=
", p.surface, p.surface_units, p.volume, p.volume_units, p.tosell as product_tosell, p.tobuy as product_tobuy";
1950 $sql .=
", p.tobatch as product_tobatch, p.stockable_product";
1951 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expeditiondet as ed, ".MAIN_DB_PREFIX.
"commandedet as cd";
1952 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"product as p ON p.rowid = cd.fk_product";
1953 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
1954 $sql .=
" AND ed.fk_elementdet = cd.rowid";
1955 $sql .=
" ORDER BY cd.rang, ed.fk_elementdet";
1957 dol_syslog(get_class($this).
"::fetch_lines", LOG_DEBUG);
1958 $resql = $this->db->query($sql);
1960 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
1962 $num = $this->db->num_rows($resql);
1968 $this->total_ht = 0;
1969 $this->total_tva = 0;
1970 $this->total_ttc = 0;
1971 $this->total_localtax1 = 0;
1972 $this->total_localtax2 = 0;
1974 $this->multicurrency_total_ht = 0;
1975 $this->multicurrency_total_tva = 0;
1976 $this->multicurrency_total_ttc = 0;
1982 $obj = $this->db->fetch_object($resql);
1984 if ($originline > 0 && $originline == $obj->fk_elementdet) {
1986 $line->entrepot_id = 0;
1987 $line->qty_shipped += $obj->qty_shipped;
1990 $line->entrepot_id = $obj->fk_entrepot;
1991 $line->qty_shipped = $obj->qty_shipped;
1995 $detail_entrepot->entrepot_id = $obj->fk_entrepot;
1996 $detail_entrepot->qty_shipped = $obj->qty_shipped;
1997 $detail_entrepot->line_id = $obj->line_id;
1998 $line->details_entrepot[] = $detail_entrepot;
2000 $line->line_id = $obj->line_id;
2001 $line->rowid = $obj->line_id;
2002 $line->id = $obj->line_id;
2004 $line->fk_origin =
'orderline';
2006 $line->fk_element = $obj->fk_element;
2007 $line->origin_id = $obj->fk_element;
2008 $line->fk_elementdet = $obj->fk_elementdet;
2009 $line->origin_line_id = $obj->fk_elementdet;
2010 $line->element_type = $obj->element_type;
2012 $line->fk_expedition = $this->id;
2014 $line->stockable_product = $obj->stockable_product;
2015 $line->product_type = $obj->product_type;
2016 $line->fk_product = $obj->fk_product;
2017 $line->fk_product_type = $obj->fk_product_type;
2018 $line->ref = $obj->product_ref;
2019 $line->product_ref = $obj->product_ref;
2020 $line->product_label = $obj->product_label;
2021 $line->libelle = $obj->product_label;
2022 $line->product_barcode = $obj->product_barcode;
2023 $line->product_tosell = $obj->product_tosell;
2024 $line->product_tobuy = $obj->product_tobuy;
2025 $line->product_tobatch = $obj->product_tobatch;
2026 $line->fk_fournprice = $obj->fk_fournprice;
2027 $line->label = $obj->custom_label;
2028 $line->description = $obj->description;
2029 $line->qty_asked = $obj->qty_asked;
2030 $line->rang = $obj->rang;
2031 $line->weight = $obj->weight;
2032 $line->weight_units = $obj->weight_units;
2033 $line->length = $obj->length;
2034 $line->length_units = $obj->length_units;
2035 $line->width = $obj->width;
2036 $line->width_units = $obj->width_units;
2037 $line->height = $obj->height;
2038 $line->height_units = $obj->height_units;
2039 $line->surface = $obj->surface;
2040 $line->surface_units = $obj->surface_units;
2041 $line->volume = $obj->volume;
2042 $line->volume_units = $obj->volume_units;
2043 $line->stockable_product = $obj->stockable_product;
2044 $line->fk_unit = $obj->fk_unit;
2046 $line->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
2048 $line->pa_ht = $obj->pa_ht;
2051 $localtax_array = array(0 => $obj->localtax1_type, 1 => $obj->localtax1_tx, 2 => $obj->localtax2_type, 3 => $obj->localtax2_tx);
2052 $localtax1_tx =
get_localtax($obj->tva_tx, 1, $this->thirdparty);
2053 $localtax2_tx =
get_localtax($obj->tva_tx, 2, $this->thirdparty);
2056 $tabprice =
calcul_price_total($obj->qty_shipped, $obj->subprice, $obj->remise_percent, $obj->tva_tx, $localtax1_tx, $localtax2_tx, 0,
'HT', $obj->info_bits, $obj->fk_product_type, $mysoc, $localtax_array);
2057 $line->desc = $obj->description;
2058 $line->qty = $line->qty_shipped;
2059 $line->total_ht = (float) $tabprice[0];
2060 $line->total_localtax1 = (float) $tabprice[9];
2061 $line->total_localtax2 = (float) $tabprice[10];
2062 $line->total_ttc = (float) $tabprice[2];
2063 $line->total_tva = (float) $tabprice[1];
2064 $line->vat_src_code = $obj->vat_src_code;
2065 $line->tva_tx = $obj->tva_tx;
2066 $line->localtax1_tx = $obj->localtax1_tx;
2067 $line->localtax2_tx = $obj->localtax2_tx;
2068 $line->info_bits = $obj->info_bits;
2069 $line->price = $obj->price;
2070 $line->subprice = $obj->subprice;
2071 $line->fk_remise_except = $obj->fk_remise_except;
2072 $line->remise_percent = $obj->remise_percent;
2074 $this->total_ht += $tabprice[0];
2075 $this->total_tva += $tabprice[1];
2076 $this->total_ttc += $tabprice[2];
2077 $this->total_localtax1 += $tabprice[9];
2078 $this->total_localtax2 += $tabprice[10];
2080 $line->date_start = $this->db->jdate($obj->date_start);
2081 $line->date_end = $this->db->jdate($obj->date_end);
2083 $line->special_code = $obj->special_code;
2086 $this->fk_multicurrency = $obj->fk_multicurrency;
2087 $this->multicurrency_code = $obj->multicurrency_code;
2088 $line->multicurrency_subprice = $obj->multicurrency_subprice;
2089 $line->multicurrency_total_ht = $obj->multicurrency_total_ht;
2090 $line->multicurrency_total_tva = $obj->multicurrency_total_tva;
2091 $line->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
2093 $this->multicurrency_total_ht += $obj->multicurrency_total_ht;
2094 $this->multicurrency_total_tva += $obj->multicurrency_total_tva;
2095 $this->multicurrency_total_ttc += $obj->multicurrency_total_ttc;
2097 if ($originline != $obj->fk_elementdet) {
2098 $line->detail_batch = array();
2102 if (isModEnabled(
'productbatch') && $obj->line_id > 0 && $obj->product_tobatch > 0) {
2103 $newdetailbatch = $shipmentlinebatch->fetchAll($obj->line_id, $obj->fk_product);
2105 if (is_array($newdetailbatch)) {
2106 if ($originline != $obj->fk_elementdet) {
2107 $line->detail_batch = $newdetailbatch;
2109 $line->detail_batch = array_merge($line->detail_batch, $newdetailbatch);
2116 $detail_children = array();
2117 $line_child_list = array();
2118 $res = $line->findAllChild($line->id, $line_child_list, 1);
2120 foreach ($line_child_list as $child_line) {
2121 foreach ($child_line as $child_obj) {
2122 $child_product_id = (int) $child_obj->fk_product;
2123 $child_warehouse_id = (int) $child_obj->fk_warehouse;
2125 if ($child_warehouse_id > 0) {
2127 if (!isset($detail_children[$child_product_id])) {
2128 $detail_children[$child_product_id] = array();
2130 if (!isset($detail_children[$child_product_id][$child_warehouse_id])) {
2131 $detail_children[$child_product_id][$child_warehouse_id] = 0;
2133 $detail_children[$child_product_id][$child_warehouse_id] += $child_obj->qty;
2138 $line->detail_children = $detail_children;
2141 $line->fetch_optionals();
2143 if ($originline != $obj->fk_elementdet) {
2144 $this->lines[$lineindex] = $line;
2147 $line->total_ht += $tabprice[0];
2148 $line->total_localtax1 += $tabprice[9];
2149 $line->total_localtax2 += $tabprice[10];
2150 $line->total_ttc += $tabprice[2];
2151 $line->total_tva += $tabprice[1];
2155 $originline = $obj->fk_elementdet;
2157 $this->db->free($resql);
2160 $this->error = $this->db->error();
2176 if ($this->
status == self::STATUS_DRAFT) {
2182 $line->fetch($lineid);
2184 if ($line->delete($user) > 0) {
2187 $this->db->commit();
2190 $this->db->rollback();
2194 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
2208 global
$conf, $langs;
2210 $langs->load(
'sendings');
2212 $nofetch = !empty($params[
'nofetch']);
2215 $datas[
'picto'] =
img_picto(
'', $this->picto).
' <u class="paddingrightonly">'.$langs->trans(
"Shipment").
'</u>';
2216 if (isset($this->
status)) {
2217 $datas[
'picto'] .=
' '.$this->getLibStatut(5);
2219 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
2220 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.($this->ref_customer ? $this->ref_customer : $this->ref_client);
2222 $langs->load(
'companies');
2223 if (empty($this->thirdparty)) {
2226 $datas[
'customer'] =
'<br><b>'.$langs->trans(
'Customer').
':</b> '.$this->thirdparty->getNomUrl(1,
'', 0, 1);
2243 public function getNomUrl($withpicto = 0, $option =
'', $max = 0, $short = 0, $notooltip = 0, $save_lastsearch_value = -1)
2245 global $langs, $hookmanager;
2250 'objecttype' => $this->element,
2251 'option' => $option,
2254 $classfortooltip =
'classfortooltip';
2257 $classfortooltip =
'classforajaxtooltip';
2258 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
2264 $url = DOL_URL_ROOT.
'/expedition/card.php?id='.$this->id;
2270 if ($option !==
'nolink') {
2272 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2273 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
2274 $add_save_lastsearch_values = 1;
2276 if ($add_save_lastsearch_values) {
2277 $url .=
'&save_lastsearch_values=1';
2282 if (empty($notooltip)) {
2284 $label = $langs->trans(
"Shipment");
2285 $linkclose .=
' alt="'.dolPrintHTMLForAttribute($label).
'"';
2287 $linkclose .= ($label ?
' title="'.dolPrintHTMLForAttribute($label).
'"' :
' title="tocomplete"');
2288 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
2291 $linkstart =
'<a href="'.$url.
'"';
2292 $linkstart .= $linkclose.
'>';
2295 $result .= $linkstart;
2297 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), ($notooltip ? (($withpicto != 2) ?
'class="paddingright"' :
'') :
'class="'.(($withpicto != 2) ?
'paddingright ' :
'').
'"'), 0, 0, $notooltip ? 0 : 1);
2299 if ($withpicto != 2) {
2300 $result .= $this->ref;
2302 $result .= $linkend;
2304 $hookmanager->initHooks(array($this->element .
'dao'));
2305 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result);
2306 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
2308 $result = $hookmanager->resPrint;
2310 $result .= $hookmanager->resPrint;
2339 $labelStatus = $langs->transnoentitiesnoconv($this->labelStatus[$status]);
2340 $labelStatusShort = $langs->transnoentitiesnoconv($this->labelStatusShort[$status]);
2342 $statusType =
'status'.$status;
2343 if ($status == self::STATUS_VALIDATED) {
2344 $statusType =
'status4';
2346 if ($status == self::STATUS_CLOSED) {
2347 $statusType =
'status6';
2349 if ($status == self::STATUS_CANCELED) {
2350 $statusType =
'status9';
2354 $status_label = $this->signed_status ? $labelStatus . $signed_label : $labelStatus;
2355 $status_label_short = $this->signed_status ? $labelStatusShort . $signed_label : $labelStatusShort;
2357 return dolGetStatus($status_label, $status_label_short,
'', $statusType, $mode);
2369 global $langs,
$conf;
2371 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
2373 $return =
'<div class="box-flex-item box-flex-grow-zero">';
2374 $return .=
'<div class="info-box info-box-sm">';
2375 $return .=
'<div class="info-box-icon bg-infobox-action">';
2377 $return .=
'</div>';
2378 $return .=
'<div class="info-box-content">';
2379 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl() : $this->ref).
'</span>';
2380 if ($selected >= 0) {
2381 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
2383 if (property_exists($this,
'thirdparty') && is_object($this->thirdparty)) {
2384 $return .=
'<br><div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).
'</div>';
2386 if (property_exists($this,
'total_ht')) {
2387 $return .=
'<div class="info-box-ref amount">'.price($this->total_ht, 0, $langs, 0, -1, -1,
$conf->currency).
' '.$langs->trans(
'HT').
'</div>';
2389 if (method_exists($this,
'getLibStatut')) {
2390 $return .=
'<div class="info-box-status">'.$this->getLibStatut(3).
'</div>';
2392 $return .=
'</div>';
2393 $return .=
'</div>';
2394 $return .=
'</div>';
2412 dol_syslog(get_class($this).
"::initAsSpecimen");
2415 $order->initAsSpecimen();
2419 $this->
ref =
'SPECIMEN';
2420 $this->specimen = 1;
2422 $this->livraison_id = 0;
2424 $this->date_creation = $now;
2425 $this->date_valid = $now;
2426 $this->date_delivery = $now + 24 * 3600;
2427 $this->date_expedition = $now + 24 * 3600;
2429 $this->entrepot_id = 0;
2430 $this->fk_delivery_address = 0;
2433 $this->commande_id = 0;
2434 $this->commande = $order;
2436 $this->origin_id = 1;
2437 $this->origin_type =
'commande';
2439 $this->note_private =
'Private note';
2440 $this->note_public =
'Public note';
2444 while ($xnbp < $nbp) {
2446 $line->product_desc = $langs->trans(
"Description").
" ".$xnbp;
2447 $line->product_label = $langs->trans(
"Description").
" ".$xnbp;
2449 $line->qty_asked = 5;
2450 $line->qty_shipped = 4;
2451 $line->fk_product = $this->commande->lines[$xnbp]->fk_product;
2453 $line->weight = 1.123456;
2454 $line->weight_units = 0;
2456 $line->volume = 2.34567;
2457 $line->volume_unit = 0;
2459 $this->lines[] = $line;
2490 if ($user->hasRight(
'expedition',
'creer')) {
2491 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
2492 $sql .=
" SET date_delivery = ".($delivery_date ?
"'".$this->db->idate($delivery_date).
"'" :
'null');
2493 $sql .=
" WHERE rowid = ".((int) $this->
id);
2495 dol_syslog(get_class($this).
"::setDeliveryDate", LOG_DEBUG);
2496 $resql = $this->db->query($sql);
2498 $this->date_delivery = $delivery_date;
2501 $this->error = $this->db->error();
2518 if ($user->hasRight(
'expedition',
'creer')) {
2519 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
2520 $sql .=
" SET date_expedition = ".($shipping_date ?
"'".$this->db->idate($shipping_date).
"'" :
'null');
2521 $sql .=
" WHERE rowid = ".((int) $this->
id);
2523 dol_syslog(get_class($this).
"::setShippingDate", LOG_DEBUG);
2524 $resql = $this->db->query($sql);
2526 $this->date_shipping = $shipping_date;
2529 $this->error = $this->db->error();
2547 $this->meths = array();
2549 $sql =
"SELECT em.rowid, em.code, em.libelle as label";
2550 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2551 $sql .=
" WHERE em.active = 1";
2552 $sql .=
" ORDER BY em.libelle ASC";
2554 $resql = $this->db->query($sql);
2556 while ($obj = $this->db->fetch_object($resql)) {
2557 $label = $langs->trans(
'SendingMethod'.$obj->code);
2558 $this->meths[$obj->rowid] = ($label !=
'SendingMethod'.$obj->code ? $label : $obj->label);
2575 $this->listmeths = array();
2578 $sql =
"SELECT em.rowid, em.code, em.libelle as label, em.description, em.tracking, em.active";
2579 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2581 $sql .=
" WHERE em.rowid=".((int) $id);
2584 $resql = $this->db->query($sql);
2586 while ($obj = $this->db->fetch_object($resql)) {
2587 $this->listmeths[$i][
'rowid'] = $obj->rowid;
2588 $this->listmeths[$i][
'code'] = $obj->code;
2589 $label = $langs->trans(
'SendingMethod'.$obj->code);
2590 $this->listmeths[$i][
'libelle'] = ($label !=
'SendingMethod'.$obj->code ? $label : $obj->label);
2591 $this->listmeths[$i][
'description'] = $obj->description;
2592 $this->listmeths[$i][
'tracking'] = $obj->tracking;
2593 $this->listmeths[$i][
'active'] = $obj->active;
2607 if (!empty($this->shipping_method_id)) {
2608 $sql =
"SELECT em.code, em.tracking";
2609 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2610 $sql .=
" WHERE em.rowid = ".((int) $this->shipping_method_id);
2612 $resql = $this->db->query($sql);
2614 if ($obj = $this->db->fetch_object($resql)) {
2615 $tracking = $obj->tracking;
2620 if (!empty($tracking) && !empty($value)) {
2621 $url = str_replace(
'{TRACKID}', $value, $tracking);
2622 $this->tracking_url = sprintf(
'<a target="_blank" rel="noopener noreferrer" href="%s">%s</a>', $url, ($value ? $value :
'url'));
2624 $this->tracking_url = $value;
2640 if ($this->
status == self::STATUS_CLOSED) {
2647 if (empty($this->date_shipping)) {
2648 $sql .=
", date_expedition = '".$this->db->escape($this->db->idate(
dol_now())).
"'";
2650 $sql .=
" WHERE rowid = ".((int) $this->
id).
" AND fk_statut > 0";
2652 $resql = $this->db->query($sql);
2655 if ($this->origin ==
'commande' && $this->origin_id > 0) {
2657 $order->fetch($this->origin_id);
2659 $order->loadExpeditions(self::STATUS_CLOSED);
2661 $shipments_match_order = 1;
2662 foreach ($order->lines as $line) {
2663 $lineid = $line->id;
2665 if (($line->product_type == 0 ||
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES')) && $order->expeditions[$lineid] != $qty) {
2666 $shipments_match_order = 0;
2667 $text =
'Qty for order line id '.$lineid.
' is '.$qty.
'. However in the shipments with status Expedition::STATUS_CLOSED='.self::STATUS_CLOSED.
' we have qty = '.$order->expeditions[$lineid].
', so we can t close order';
2672 if ($shipments_match_order) {
2673 dol_syslog(
"Qty for the ".count($order->lines).
" lines of the origin order is same than qty for lines in the shipment we close (shipments_match_order is true), with new status Expedition::STATUS_CLOSED=".self::STATUS_CLOSED.
', so we close order');
2675 $order->cloture($user);
2683 if (!$error && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT_CLOSE')) {
2692 $result = $this->
call_trigger(
'SHIPPING_CLOSED', $user);
2703 $this->db->commit();
2709 $this->db->rollback();
2728 require_once DOL_DOCUMENT_ROOT .
'/product/stock/class/mouvementstock.class.php';
2730 $langs->load(
"agenda");
2734 $sql .=
" ed.rowid as edid, ed.fk_product, ed.qty, ed.fk_entrepot";
2735 $sql .=
", cd.rowid as cdid";
2736 $sql .=
", cd.subprice";
2737 $sql .=
", edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
2739 $sql .=
" FROM " . $this->db->prefix() .
"expeditiondet as ed";
2740 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"commandedet as cd ON cd.rowid = ed.fk_elementdet";
2741 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
2742 $sql .=
" INNER JOIN " . $this->db->prefix() .
"expedition as e ON ed.fk_expedition = e.rowid";
2743 $sql .=
" WHERE ed.fk_expedition = " . ((int) $this->
id);
2746 dol_syslog(get_class($this) .
"::valid select details", LOG_DEBUG);
2747 $resql = $this->db->query($sql);
2749 $cpt = $this->db->num_rows($resql);
2750 for ($i = 0; $i < $cpt; $i++) {
2751 $obj = $this->db->fetch_object($resql);
2752 if (empty($obj->edbrowid)) {
2755 $qty = $obj->edbqty;
2757 if ($qty <= 0 || ($qty < 0 && !
getDolGlobalInt(
'SHIPMENT_ALLOW_NEGATIVE_QTY'))) {
2760 dol_syslog(get_class($this) .
"::valid movement index " . $i .
" ed.rowid=" . $obj->edid .
" edb.rowid=" . $obj->edbrowid);
2763 $mouvS->origin = &$this;
2764 $mouvS->setOrigin($this->element, $this->
id, $obj->cdid, $obj->edid);
2766 if (empty($obj->edbrowid)) {
2770 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans($labelmovement, $obj->ref));
2772 $this->error = $mouvS->error;
2773 $this->errors = $mouvS->errors;
2781 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans($labelmovement, $obj->ref),
'', $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, $obj->fk_origin_stock);
2783 $this->error = $mouvS->error;
2784 $this->errors = $mouvS->errors;
2792 $sqldelete =
"DELETE FROM ".$this->db->prefix().
"product_stock WHERE reel = 0 AND rowid NOT IN (SELECT fk_product_stock FROM ".$this->db->prefix().
"product_batch as pb)";
2793 $resqldelete = $this->db->query($sqldelete);
2797 $this->error = $this->db->lasterror();
2798 $this->errors[] = $this->db->lasterror();
2821 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'expedition SET billed = 1';
2822 $sql .=
" WHERE rowid = ".((int) $this->
id).
' AND fk_statut > 0';
2824 $resql = $this->db->query($sql);
2829 $result = $this->
call_trigger(
'SHIPPING_BILLED', $user);
2836 $this->errors[] = $this->db->lasterror;
2839 if (empty($error)) {
2840 $this->db->commit();
2843 $this->db->rollback();
2858 if ($this->
status <= self::STATUS_DRAFT) {
2862 return $this->
setStatusCommon($user, self::STATUS_DRAFT, $notrigger,
'SHIPMENT_UNVALIDATE');
2872 global $langs, $user;
2877 if ($this->
status == self::STATUS_VALIDATED) {
2883 $oldbilled = $this->billed;
2885 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'expedition SET fk_statut = 1';
2886 $sql .=
" WHERE rowid = ".((int) $this->
id).
' AND fk_statut > 0';
2888 $resql = $this->db->query($sql);
2895 if (!$error && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT_CLOSE')) {
2896 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
2898 $langs->load(
"agenda");
2902 $sql =
"SELECT cd.fk_product, cd.subprice,";
2903 $sql .=
" ed.rowid, ed.qty, ed.fk_entrepot,";
2904 $sql .=
" edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
2905 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commandedet as cd,";
2906 $sql .=
" ".MAIN_DB_PREFIX.
"expeditiondet as ed";
2907 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
2908 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
2909 $sql .=
" AND cd.rowid = ed.fk_elementdet";
2911 dol_syslog(get_class($this).
"::valid select details", LOG_DEBUG);
2912 $resql = $this->db->query($sql);
2914 $cpt = $this->db->num_rows($resql);
2915 for ($i = 0; $i < $cpt; $i++) {
2916 $obj = $this->db->fetch_object($resql);
2917 if (empty($obj->edbrowid)) {
2920 $qty = $obj->edbqty;
2925 dol_syslog(get_class($this).
"::reopen expedition movement index ".$i.
" ed.rowid=".$obj->rowid.
" edb.rowid=".$obj->edbrowid);
2929 $mouvS->origin = &$this;
2930 $mouvS->setOrigin($this->element, $this->
id);
2932 if (empty($obj->edbrowid)) {
2936 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans(
"ShipmentUnClassifyCloseddInDolibarr", $this->ref));
2938 $this->error = $mouvS->error;
2939 $this->errors = $mouvS->errors;
2947 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans(
"ShipmentUnClassifyCloseddInDolibarr", $this->ref),
'', $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, $obj->fk_origin_stock);
2949 $this->error = $mouvS->error;
2950 $this->errors = $mouvS->errors;
2957 $this->error = $this->db->lasterror();
2964 $result = $this->
call_trigger(
'SHIPPING_REOPEN', $user);
2971 $this->errors[] = $this->db->lasterror();
2975 $this->db->commit();
2980 $this->billed = $oldbilled;
2981 $this->db->rollback();
2997 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
2999 $outputlangs->load(
"products");
3004 if (!empty($this->model_pdf)) {
3005 $modele = $this->model_pdf;
3011 $modelpath =
"core/modules/expedition/doc/";
3015 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
Class to manage customers orders.
const STATUS_SHIPMENTONPROCESS
Shipment on process.
const STATUS_VALIDATED
Validated status.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
deleteEcmFiles($mode=0)
Delete related files of object in database.
add_object_linked($origin=null, $origin_id=null, $f_user=null, $notrigger=0)
Add an object link into llx_element_element.
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.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid=0, $f_user=null, $notrigger=0)
Delete all links between an object $this.
setErrorsFromObject($object)
setErrorsFromObject
setStatut($status, $elementId=null, $elementType='', $trigkey='', $fieldstatus='fk_statut')
Set status of an object.
deleteExtraFields()
Delete all extra fields values for the current object.
setStatusCommon($user, $status, $notrigger=0, $triggercode='')
Set to a status.
fetchObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $clause='OR', $alsosametype=1, $orderby='sourcetype', $loadalsoobjects=1)
Fetch array of objects linked to current object (object of enabled modules only).
errorsToString()
Method to output saved errors.
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
fetch_origin()
Read linked origin object.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
delete_linked_contact($source='', $code='')
Delete all links between an object $this and all its contacts in llx_element_contact.
call_trigger($triggerName, $user)
Call trigger based on this instance.
add_contact($fk_socpeople, $type_contact, $source='external', $notrigger=0)
Add a link between element $this->element and a contact.
Class to manage receptions.
Class to manage Dolibarr database access.
getNomUrl($withpicto=0, $option='', $max=0, $short=0, $notooltip=0, $save_lastsearch_value=-1)
Return clickable link of object (with eventually picto)
addline_batch($dbatch, $array_options=[], $origin_line=null)
Add a shipment line with batch record.
create_delivery($user)
Create a delivery receipt from a shipment.
setDraft($user, $notrigger=0)
Set draft status.
const STATUS_SHIPMENT_IN_PROGRESS
Expedition in progress -> package exit the warehouse and is now in the truck or into the hand of the ...
getUrlTrackingStatus($value='')
Forge an set tracking url.
setClosed()
Classify the shipping as closed (this records also the stock movement)
__construct($db)
Constructor.
create_line($entrepot_id, $origin_line_id, $qty, $rang=0, $array_options=[], $parent_line_id=0, $product_id=0)
Create a expedition line.
addline($entrepot_id, $id, $qty, $array_options=[], $fk_product=0, $fk_parent=0)
Add an expedition line.
create($user, $notrigger=0)
Create expedition en base.
LibStatut($status, $mode)
Return label of a status.
setBilled()
Classify the shipping as invoiced (used for example by trigger when WORKFLOW_SHIPPING_CLASSIFY_BILLED...
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
getTooltipContentArray($params)
getTooltipContentArray
setDeliveryDate($user, $delivery_date)
Set the planned delivery date.
getKanbanView($option='', $arraydata=null)
Return clickable link of object (with eventually picto)
setShippingDate($user, $shipping_date)
Set the shipping date.
const STATUS_DRAFT
Draft status.
const STATUS_CANCELED
Canceled status.
getLibStatut($mode=0)
Return status label.
set_date_livraison($user, $delivery_date)
Set delivery date.
initAsSpecimen()
Initialise an instance with random values.
getNextNumRef($soc)
Return next expedition ref.
const STATUS_CLOSED
Closed status -> parcel was received by customer / end of process prev status : validated or shipment...
const STATUS_VALIDATED
Validated status -> parcel is ready to be sent prev status : draft next status : closed or shipment_i...
create_line_batch($line_ext, $array_options=[])
Create the detail of the expedition line.
manageStockMvtOnEvt($user, $labelmovement='ShipmentClassifyClosedInDolibarr')
Manage Stock MVt onb Close or valid Shipment.
valid($user, $notrigger=0)
Validate object and update stock if option enabled.
update($user=null, $notrigger=0)
Update database.
cancel($notrigger=0, $also_update_stock=false)
Cancel shipment.
fetch_delivery_methods()
Fetch deliveries method and return an array.
fetch($id, $ref='', $ref_ext='', $notused='')
Get object and lines from database.
reOpen()
Classify the shipping as validated/opened.
deleteLine($user, $lineid)
Delete detail line.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
list_delivery_methods($id=0)
Fetch all deliveries method and return an array.
Class to manage lines of shipment.
CRUD class for batch number management within shipment.
Class to manage stock movements.
Class to manage order lines.
Class to manage products or services.
const TYPE_SERVICE
Service.
Manage record for batch number management.
Class to manage third parties objects (customers, suppliers, prospects...)
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...
getLibSignedStatus(int $mode=0)
Returns the label for signed status.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0, $level=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
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.
setEntity($currentobject)
Set entity id to use when to create an object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
get_localtax($vatrate, $local, $thirdparty_buyer=null, $thirdparty_seller=null, $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate,...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller=null, $localtaxes_array=[], $progress=100, $multicurrency_tx=1, $pu_devise=0, $multicurrency_code='')
Calculate totals (net, vat, ...) of a line.
$conf db user
Active Directory does not allow anonymous connections.