40require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
41require_once DOL_DOCUMENT_ROOT.
"/expedition/class/expeditionligne.class.php";
42require_once DOL_DOCUMENT_ROOT.
'/core/class/commonincoterm.class.php';
44 require_once DOL_DOCUMENT_ROOT.
'/comm/propal/class/propal.class.php';
47 require_once DOL_DOCUMENT_ROOT.
'/commande/class/commande.class.php';
49require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expeditionlinebatch.class.php';
50require_once DOL_DOCUMENT_ROOT.
'/core/class/commonsignedobject.class.php';
51require_once DOL_DOCUMENT_ROOT.
'/subtotals/class/commonsubtotal.class.php';
61 use CommonSignedObject;
67 public $element =
"shipping";
72 public $fk_element =
"fk_expedition";
77 public $table_element =
"expedition";
82 public $table_element_line =
"expeditiondet";
87 public $class_element_line =
'ExpeditionLigne';
92 public $picto =
'dolly';
98 public $fields = array();
104 public $user_author_id;
110 public $fk_user_author;
116 public $fk_user_valid;
133 public $ref_customer;
143 public $tracking_number;
148 public $tracking_url;
161 public $weight_units;
177 public $height_units;
194 public $livraison_id;
199 public $multicurrency_subprice;
229 public $date_delivery;
243 public $date_expedition;
249 public $date_shipping;
278 public $lines = array();
284 public $fk_multicurrency;
289 public $multicurrency_code;
293 public $multicurrency_tx;
297 public $multicurrency_total_ht;
301 public $multicurrency_total_tva;
305 public $multicurrency_total_ttc;
350 $this->ismultientitymanaged = 1;
351 $this->isextrafieldmanaged = 1;
354 $this->labelStatus = array();
355 $this->labelStatus[-1] =
'StatusSendingCanceled';
356 $this->labelStatus[0] =
'StatusSendingDraft';
357 $this->labelStatus[1] =
'StatusSendingValidated';
358 $this->labelStatus[2] =
'StatusSendingProcessed';
361 $this->labelStatusShort = array();
362 $this->labelStatusShort[-1] =
'StatusSendingCanceledShort';
363 $this->labelStatusShort[0] =
'StatusSendingDraftShort';
364 $this->labelStatusShort[1] =
'StatusSendingValidatedShort';
365 $this->labelStatusShort[2] =
'StatusSendingProcessedShort';
374 public function getNextNumRef($soc)
376 global $langs,
$conf;
377 $langs->load(
"sendings");
386 $dirmodels = array_merge(array(
'/'), (array)
$conf->modules_parts[
'models']);
388 foreach ($dirmodels as $reldir) {
392 $mybool = ((bool) @include_once $dir.$file) || $mybool;
400 $obj =
new $classname();
401 '@phan-var-force ModelNumRefExpedition $obj';
403 $numref = $obj->getNextValue($soc, $this);
408 dol_print_error($this->db, get_class($this).
"::getNextNumRef ".$obj->error);
412 print $langs->trans(
"Error").
" ".$langs->trans(
"Error_EXPEDITION_ADDON_NUMBER_NotDefined");
424 public function create($user, $notrigger = 0)
428 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
433 $this->tracking_number = preg_replace(
'/\s+/',
'', $this->tracking_number);
435 if (empty($this->fk_project)) {
436 $this->fk_project = 0;
438 if (empty($this->date_creation)) {
439 $this->date_creation = $now;
441 if (empty($this->date_shipping) && !empty($this->date_expedition)) {
442 $this->date_shipping = $this->date_expedition;
450 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"expedition (";
453 $sql .=
", ref_customer";
455 $sql .=
", date_creation";
456 $sql .=
", fk_user_author";
457 $sql .=
", date_expedition";
458 $sql .=
", date_delivery";
460 $sql .=
", fk_projet";
461 $sql .=
", fk_address";
462 $sql .=
", fk_shipping_method";
463 $sql .=
", tracking_number";
468 $sql .=
", weight_units";
469 $sql .=
", size_units";
470 $sql .=
", note_private";
471 $sql .=
", note_public";
472 $sql .=
", model_pdf";
473 $sql .=
", fk_incoterms, location_incoterms";
474 $sql .=
", signed_status";
476 $sql .=
") VALUES (";
478 $sql .=
", ".((int) $this->entity);
479 $sql .=
", ".($this->ref_customer ?
"'".$this->db->escape($this->ref_customer).
"'" :
"null");
480 $sql .=
", ".($this->ref_ext ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
481 $sql .=
", '".$this->db->idate($this->date_creation).
"'";
482 $sql .=
", ".((int) $user->id);
483 $sql .=
", ".($this->date_shipping > 0 ?
"'".$this->db->idate($this->date_shipping).
"'" :
"null");
484 $sql .=
", ".($this->date_delivery > 0 ?
"'".$this->db->idate($this->date_delivery).
"'" :
"null");
485 $sql .=
", ".($this->socid > 0 ? ((int) $this->socid) :
"null");
486 $sql .=
", ".($this->fk_project > 0 ? ((int) $this->fk_project) :
"null");
487 $sql .=
", ".($this->fk_delivery_address > 0 ? ((int) $this->fk_delivery_address) :
"null");
488 $sql .=
", ".($this->shipping_method_id > 0 ? ((int) $this->shipping_method_id) :
"null");
489 $sql .=
", '".$this->db->escape($this->tracking_number).
"'";
490 $sql .=
", ".(is_numeric($this->weight) ? (float) $this->weight :
'NULL');
491 $sql .=
", ".(is_numeric($this->sizeS) ? (float) $this->sizeS :
'NULL');
492 $sql .=
", ".(is_numeric($this->sizeW) ? (float) $this->sizeW :
'NULL');
493 $sql .=
", ".(is_numeric($this->sizeH) ? (float) $this->sizeH :
'NULL');
494 $sql .=
", ".($this->weight_units !=
'' ? (int) $this->weight_units :
'NULL');
495 $sql .=
", ".($this->size_units !=
'' ? (int) $this->size_units :
'NULL');
496 $sql .=
", ".(!empty($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null");
497 $sql .=
", ".(!empty($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null");
498 $sql .=
", ".(!empty($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null");
499 $sql .=
", ".((int) $this->fk_incoterms);
500 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
501 $sql .=
", ".((int) $this->signed_status);
502 $sql .=
", ".((int) $this->billed);
505 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
506 $resql = $this->db->query($sql);
508 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
"expedition");
511 $initialref =
'(PROV'.$this->id.
')';
512 if (!empty($this->
ref)) {
513 $initialref = $this->ref;
516 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
517 $sql .=
" SET ref = '".$this->db->escape($initialref).
"'";
518 $sql .=
" WHERE rowid = ".((int) $this->
id);
520 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
521 if ($this->db->query($sql)) {
522 $this->
ref = $initialref;
524 $num = count($this->lines);
525 $kits_list = array();
527 for ($i = 0; $i < $num; $i++) {
529 $objectsrc->fetch($this->lines[$i]->origin_line_id);
530 if ($this->lines[$i]->product_type ==
"9" && $objectsrc->special_code == SUBTOTALS_SPECIAL_CODE) {
531 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) {
538 $line = $this->lines[$i];
539 if ($line->fk_product > 0) {
545 if (!isset($kits_list[$line->fk_elementdet])) {
546 if (!is_object($line->product)) {
547 $line_product =
new Product($this->db);
548 $result = $line_product->fetch($line->fk_product,
'',
'',
'', 1, 1, 1);
553 $line_product = $line->product;
557 $line_product->get_sousproduits_arbo();
558 $prods_arbo = $line_product->get_arbo_each_prod($line->qty);
559 if (count($prods_arbo) > 0) {
560 $kits_list[$line->fk_elementdet] = array(
561 'arbo' => $prods_arbo,
562 'total_qty' => $line->qty,
566 $kits_list[$line->fk_elementdet][
'total_qty'] += $line->qty;
572 $kits_id_cached = array();
573 $sub_kits_id_cached = array();
574 $sub_parents_cached = array();
575 for ($i = 0; $i < $num; $i++) {
576 $line = $this->lines[$i];
579 if (!isset($kits_id_cached[$line->fk_elementdet])) {
580 if (!isset($line->detail_batch) || (isset($kits_list[$line->fk_elementdet]) && !
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE'))) {
581 $qty = isset($kits_list[$line->fk_elementdet]) ? $kits_list[$line->fk_elementdet][
'total_qty'] : $line->qty;
582 $warehouse_id = (isset($kits_list[$line->fk_elementdet]) && !
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) ? 0 : $line->entrepot_id;
583 $line_id = $this->
create_line($warehouse_id, $line->origin_line_id, $qty, $line->rang, $line->array_options, 0, $line->fk_product);
587 if (isset($kits_list[$line->fk_elementdet])) {
588 $kits_id_cached[$line->fk_elementdet] = $line_id;
596 $line_id = $kits_id_cached[$line->fk_elementdet];
600 if (isset($kits_list[$line->fk_elementdet]) && !
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) {
601 $prods_arbo = $kits_list[$line->fk_elementdet][
'arbo'];
604 $parent_line_id = $line_id;
606 $product_child_id = 0;
607 foreach ($prods_arbo as $index => $product_child_arr) {
622 $product_child_level = (int) $product_child_arr[
'level'];
623 $product_child_incdec = !empty($product_child_arr[
'incdec']);
626 if ($product_child_level != $level_last) {
627 $parent_line_id = $line_id;
628 $parent_product_id = $product_child_id;
629 if (isset($sub_parents_cached[$line->fk_elementdet][$parent_product_id])) {
630 $parent_line_id = $sub_parents_cached[$line->fk_elementdet][$parent_product_id];
632 $sub_parents_cached[$line->fk_elementdet][$parent_product_id] = $parent_line_id;
638 $next_level = $product_child_level;
639 $next_index = $index + 1;
640 if (isset($prods_arbo[$next_index])) {
641 $next_level = (int) $prods_arbo[$next_index][
'level'];
643 if ($next_level > $product_child_level) {
648 $product_child_id = (int) $product_child_arr[
'id'];
649 $product_child_qty = (float) $product_child_arr[
'nb_total'];
650 $warehouse_id = $line->entrepot_id;
651 if ($is_kit || !$product_child_incdec) {
652 if (!$product_child_incdec) {
653 $product_child_qty = 0;
659 if (!isset($sub_kits_id_cached[$line->fk_elementdet][$product_child_id]) || $warehouse_id > 0) {
660 $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);
668 if (empty($warehouse_id)) {
669 $sub_kits_id_cached[$line->fk_elementdet][$product_child_id] = $line_id;
673 $level_last = $product_child_level;
679 if (!$error && $this->
id && $this->origin_id) {
686 if (!$error && $this->
id &&
getDolGlobalInt(
'SHIPPING_USE_ITS_OWN_CONTACTS') &&
getDolGlobalString(
'MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN') && !empty($this->origin_type) && !empty($this->origin_id)) {
687 $originforcontact = $this->origin_type;
688 $originidforcontact = $this->origin_id;
690 $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";
691 $sqlcontact .=
" WHERE element_id = ".((int) $originidforcontact).
" AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$this->db->escape($originforcontact).
"'";
693 $resqlcontact = $this->db->query($sqlcontact);
695 while ($objcontact = $this->db->fetch_object($resqlcontact)) {
696 $this->
add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source);
711 if (!$error && !$notrigger) {
713 $result = $this->call_trigger(
'SHIPPING_CREATE', $user);
723 foreach ($this->errors as $errmsg) {
724 dol_syslog(get_class($this).
"::create ".$errmsg, LOG_ERR);
725 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
727 $this->db->rollback();
732 $this->db->rollback();
737 $this->error = $this->db->lasterror().
" - sql=$sql";
738 $this->db->rollback();
743 $this->error = $this->db->error().
" - sql=$sql";
744 $this->db->rollback();
762 public function create_line($entrepot_id, $origin_line_id, $qty, $rang = 0, $array_options = [], $parent_line_id = 0, $product_id = 0)
768 $expeditionline->fk_expedition = $this->id;
769 $expeditionline->entrepot_id = $entrepot_id;
770 $expeditionline->fk_elementdet = $origin_line_id;
771 $expeditionline->element_type = $this->origin;
772 $expeditionline->fk_parent = $parent_line_id;
773 $expeditionline->fk_product = $product_id;
774 $expeditionline->qty = $qty;
775 $expeditionline->rang = $rang;
776 $expeditionline->array_options = $array_options;
778 if (!($expeditionline->fk_product > 0)) {
780 $order_line->fetch($expeditionline->fk_elementdet);
781 $expeditionline->fk_product = $order_line->fk_product;
784 if (($lineId = $expeditionline->insert($user)) < 0) {
785 $this->errors[] = $expeditionline->error;
803 $stockLocationQty = array();
805 $tab = $line_ext->detail_batch;
807 foreach ($tab as $detbatch) {
808 if (!empty($detbatch->fk_warehouse)) {
809 if (empty($stockLocationQty[$detbatch->fk_warehouse])) {
810 $stockLocationQty[$detbatch->fk_warehouse] = 0;
812 $stockLocationQty[$detbatch->fk_warehouse] += $detbatch->qty;
816 foreach ($stockLocationQty as $stockLocation => $qty) {
817 $line_id = $this->
create_line($stockLocation, $line_ext->origin_line_id, $qty, $line_ext->rang, $array_options);
822 foreach ($tab as $detbatch) {
823 if ($detbatch->fk_warehouse == $stockLocation) {
824 if (!($detbatch->create($line_id) > 0)) {
825 $this->errors = $detbatch->errors;
849 public function fetch($id, $ref =
'', $ref_ext =
'', $notused =
'')
854 if (empty($id) && empty($ref) && empty($ref_ext)) {
858 $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";
859 $sql .=
", e.date_valid";
860 $sql .=
", e.weight, e.weight_units, e.size, e.size_units, e.width, e.height";
861 $sql .=
", e.date_expedition as date_expedition, e.model_pdf, e.fk_address, e.date_delivery";
862 $sql .=
", e.fk_shipping_method, e.tracking_number";
863 $sql .=
", e.note_private, e.note_public";
864 $sql .=
', e.fk_incoterms, e.location_incoterms';
865 $sql .=
', e.signed_status';
866 $sql .=
', i.libelle as label_incoterms';
867 $sql .=
', s.libelle as shipping_method';
868 $sql .=
", el.fk_source as origin_id, el.sourcetype as origin_type";
869 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expedition as e";
870 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"element_element as el ON el.fk_target = e.rowid AND el.targettype = '".$this->db->escape($this->element).
"'";
871 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON e.fk_incoterms = i.rowid';
872 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_shipment_mode as s ON e.fk_shipping_method = s.rowid';
873 $sql .=
" WHERE e.entity IN (".getEntity(
'expedition').
")";
875 $sql .=
" AND e.rowid = ".((int) $id);
878 $sql .=
" AND e.ref='".$this->db->escape($ref).
"'";
881 $sql .=
" AND e.ref_ext='".$this->db->escape($ref_ext).
"'";
884 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
885 $result = $this->db->query($sql);
887 if ($this->db->num_rows($result)) {
888 $obj = $this->db->fetch_object($result);
890 $this->
id = (int) $obj->rowid;
891 $this->entity = $obj->entity;
892 $this->
ref = $obj->ref;
893 $this->socid = $obj->socid;
894 $this->ref_customer = $obj->ref_customer;
895 $this->ref_ext = $obj->ref_ext;
896 $this->
status = $obj->fk_statut;
897 $this->statut = $this->status;
898 $this->signed_status = $obj->signed_status;
899 $this->user_author_id = $obj->fk_user_author;
900 $this->fk_user_author = $obj->fk_user_author;
901 $this->user_creation_id = $obj->fk_user_author;
902 $this->date_creation = $this->db->jdate($obj->date_creation);
903 $this->date_valid = $this->db->jdate($obj->date_valid);
904 $this->
date = $this->db->jdate($obj->date_expedition);
905 $this->date_expedition = $this->db->jdate($obj->date_expedition);
906 $this->date_shipping = $this->db->jdate($obj->date_expedition);
907 $this->date_delivery = $this->db->jdate($obj->date_delivery);
908 $this->fk_delivery_address = $obj->fk_address;
909 $this->model_pdf = $obj->model_pdf;
910 $this->shipping_method_id = $obj->fk_shipping_method;
911 $this->shipping_method = $obj->shipping_method;
912 $this->tracking_number = $obj->tracking_number;
913 $this->origin = ($obj->origin_type ? $obj->origin_type :
'commande');
914 $this->origin_type = ($obj->origin_type ? $obj->origin_type :
'commande');
915 $this->origin_id = $obj->origin_id;
916 $this->billed = $obj->billed;
917 $this->fk_project = $obj->fk_project;
918 $this->signed_status = $obj->signed_status;
919 $this->trueWeight = $obj->weight;
920 $this->weight_units = $obj->weight_units;
922 $this->trueWidth = $obj->width;
923 $this->width_units = $obj->size_units;
924 $this->trueHeight = $obj->height;
925 $this->height_units = $obj->size_units;
926 $this->trueDepth = $obj->size;
927 $this->depth_units = $obj->size_units;
929 $this->note_public = $obj->note_public;
930 $this->note_private = $obj->note_private;
933 $this->trueSize = $obj->size.
"x".$obj->width.
"x".$obj->height;
934 $this->size_units = $obj->size_units;
937 $this->fk_incoterms = $obj->fk_incoterms;
938 $this->location_incoterms = $obj->location_incoterms;
939 $this->label_incoterms = $obj->label_incoterms;
941 $this->db->free($result);
954 if (!empty($this->multicurrency_code)) {
955 $this->multicurrency_code = $this->thirdparty->multicurrency_code;
957 if (
getDolGlobalString(
'MULTICURRENCY_USE_ORIGIN_TX') && !empty($this->thirdparty->multicurrency_tx)) {
958 $this->multicurrency_tx = $this->thirdparty->multicurrency_tx;
965 if (empty($obj->origin_id)) {
976 dol_syslog(get_class($this).
'::Fetch no expedition found', LOG_ERR);
977 $this->error =
'Shipment with id '.$id.
' not found';
981 $this->error = $this->db->error();
993 public function valid($user, $notrigger = 0)
997 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1003 dol_syslog(get_class($this).
"::valid not in draft status", LOG_WARNING);
1007 if (!isset($this->socid)) {
1008 dol_syslog(get_class($this).
"::can't valid socid not set", LOG_WARNING);
1012 if (!((!
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'expedition',
'creer'))
1013 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'expedition',
'shipping_advance',
'validate')))) {
1014 $this->error =
'Permission denied';
1015 dol_syslog(get_class($this).
"::valid ".$this->error, LOG_ERR);
1024 $soc =
new Societe($this->db);
1025 $soc->fetch($this->socid);
1028 $result = $soc->setAsCustomer();
1031 if (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
1032 $numref = $this->getNextNumRef($soc);
1033 } elseif (!empty($this->
ref)) {
1036 $numref =
"EXP".$this->id;
1043 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition SET";
1044 $sql .=
" ref = '".$this->db->escape($numref).
"'";
1045 $sql .=
", fk_statut = 1";
1046 $sql .=
", date_valid = '".$this->db->idate($now).
"'";
1047 $sql .=
", fk_user_valid = ".((int) $user->id);
1048 $sql .=
" WHERE rowid = ".((int) $this->
id);
1050 dol_syslog(get_class($this).
"::valid update expedition", LOG_DEBUG);
1051 $resql = $this->db->query($sql);
1053 $this->error = $this->db->lasterror();
1066 $triggerKey =
'SHIPPING_';
1067 if ($this->origin ==
'commande') {
1068 $triggerKey .=
'ORDER_SHIPMENTONPROCESS';
1070 $triggerKey .= strtoupper($this->origin).
'_SHIPMENTONPROCESS';
1081 if (!$error && !$notrigger) {
1083 $result = $this->call_trigger(
'SHIPPING_VALIDATE', $user);
1091 $this->oldref = $this->ref;
1094 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
1096 $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).
"'";
1097 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'expedition/sending/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
1098 $resql = $this->db->query($sql);
1101 $this->error = $this->db->lasterror();
1103 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'expedition/sending/".$this->db->escape($this->newref).
"'";
1104 $sql .=
" WHERE filepath = 'expedition/sending/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
1105 $resql = $this->db->query($sql);
1108 $this->error = $this->db->lasterror();
1114 $dirsource =
$conf->expedition->dir_output.
'/sending/'.$oldref;
1115 $dirdest =
$conf->expedition->dir_output.
'/sending/'.$newref;
1116 if (!$error && file_exists($dirsource)) {
1117 dol_syslog(get_class($this).
"::valid rename dir ".$dirsource.
" into ".$dirdest);
1119 if (@rename($dirsource, $dirdest)) {
1122 $listoffiles =
dol_dir_list(
$conf->expedition->dir_output.
'/sending/'.$newref,
'files', 1,
'^'.preg_quote($oldref,
'/'));
1123 foreach ($listoffiles as $fileentry) {
1124 $dirsource = $fileentry[
'name'];
1125 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
1126 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
1127 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
1128 @rename($dirsource, $dirdest);
1137 $this->
ref = $numref;
1143 $this->db->commit();
1146 $this->db->rollback();
1160 if (empty($rows) || !is_array($rows)) {
1164 $rowToOrigin = array();
1165 $originToRows = array();
1167 $sql =
"SELECT rowid, fk_elementdet";
1168 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet";
1169 $sql .=
" WHERE fk_expedition = ".((int) $this->
id);
1170 $sql .=
" ORDER BY rang ASC, rowid ASC";
1172 $resql = $this->db->query($sql);
1174 while ($obj = $this->db->fetch_object($resql)) {
1175 $rowid = (int) $obj->rowid;
1176 $originLine = (int) $obj->fk_elementdet;
1177 $rowToOrigin[$rowid] = $originLine;
1179 if (!isset($originToRows[$originLine])) {
1180 $originToRows[$originLine] = array();
1182 $originToRows[$originLine][] = $rowid;
1184 $this->db->free($resql);
1186 parent::line_ajaxorder($rows);
1190 $processedOrigins = array();
1193 foreach ($rows as $rowid) {
1194 $rowid = (int) $rowid;
1195 if (empty($rowid)) {
1199 $originLine = isset($rowToOrigin[$rowid]) ? $rowToOrigin[$rowid] : 0;
1200 if ($originLine > 0 && !empty($processedOrigins[$originLine])) {
1204 $rowidsToUpdate = array($rowid);
1205 if ($originLine > 0 && !empty($originToRows[$originLine])) {
1206 $rowidsToUpdate = $originToRows[$originLine];
1207 $processedOrigins[$originLine] = 1;
1210 foreach ($rowidsToUpdate as $childRowId) {
1229 if ($this->
status == self::STATUS_VALIDATED || $this->
status == self::STATUS_CLOSED) {
1231 include_once DOL_DOCUMENT_ROOT.
'/delivery/class/delivery.class.php';
1232 $delivery =
new Delivery($this->db);
1233 $result = $delivery->create_from_sending($user, $this->
id);
1258 public function addline($entrepot_id, $id, $qty, $array_options = [], $fk_product = 0, $fk_parent = 0)
1262 $num = count($this->lines);
1265 $line->entrepot_id = $entrepot_id;
1266 $line->origin_line_id = $id;
1267 $line->fk_elementdet = $id;
1268 $line->element_type =
'order';
1269 $line->fk_parent = $fk_parent;
1270 $line->fk_product = $fk_product;
1274 $orderline->fetch($id);
1277 $line->rang = $orderline->rang;
1278 $line->product_type = $orderline->product_type;
1279 if (!($line->fk_product > 0)) {
1280 $line->fk_product = $orderline->fk_product;
1283 if (
isModEnabled(
'stock') && !empty($orderline->fk_product)) {
1284 $product =
new Product($this->db);
1285 $product->fetch($orderline->fk_product);
1288 $langs->load(
"errors");
1289 $this->error = $langs->trans(
"ErrorWarehouseRequiredIntoShipmentLine");
1294 $productChildrenNb = 0;
1296 $productChildrenNb = $product->hasFatherOrChild(1);
1298 if ($productChildrenNb > 0) {
1299 $product_stock =
null;
1300 $product->loadStockForVirtualProduct(
'warehouseopen', $line->qty);
1301 if ($entrepot_id > 0) {
1302 if (isset($product->stock_warehouse[$entrepot_id])) {
1303 $product_stock = $product->stock_warehouse[$entrepot_id]->real;
1306 foreach ($product->stock_warehouse as $componentStockWarehouse) {
1307 if ($product_stock ===
null) {
1308 $product_stock = $componentStockWarehouse->real;
1310 $product_stock = min($product_stock, $componentStockWarehouse->real);
1314 if ($product_stock ===
null) {
1319 if ($entrepot_id > 0) {
1320 $product->load_stock(
'warehouseopen');
1321 $product_stock = $product->stock_warehouse[$entrepot_id]->real;
1323 $product_stock = $product->stock_reel;
1327 $product_type = $product->type;
1329 $isavirtualproduct = ($productChildrenNb > 0);
1334 || ($isavirtualproduct && !
getDolGlobalInt(
'STOCK_EXCLUDE_VIRTUAL_PRODUCTS'))
1337 if ($product->stockable_product == Product::ENABLED_STOCK && $product_stock < $qty) {
1338 $langs->load(
"errors");
1339 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnShipment', $product->ref);
1340 $this->errorhidden =
'ErrorStockIsNotEnoughToAddProductOnShipment';
1351 if (
isModEnabled(
'productbatch') && !empty($line->fk_product) && !empty($orderline->product_tobatch)) {
1352 $this->error =
'ADDLINE_WAS_CALLED_INSTEAD_OF_ADDLINEBATCH '.$orderline->id.
' '.$line->fk_product;
1357 if (!
getDolGlobalString(
'MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) {
1358 $line->array_options = $array_options;
1361 $this->lines[$num] = $line;
1379 public function addlinefree($qty, $element_type, $fk_product, $fk_unit, $rang, $description, $fk_parent, $array_options = [])
1381 global
$mysoc, $langs, $user;
1383 if ($this->
status == self::STATUS_DRAFT) {
1394 if ($ranktouse == -1) {
1395 $rangmax = $this->
line_max($fk_parent);
1396 $ranktouse = $rangmax + 1;
1401 $this->line->fk_expedition = $this->id;
1402 $this->line->element_type = $element_type;
1403 $this->line->fk_product = $fk_product;
1404 $this->line->description = $description;
1405 $this->line->desc = $description;
1406 $this->line->fk_parent = $fk_parent;
1407 $this->line->qty = (float) $qty;
1408 $this->line->fk_unit = $fk_unit;
1409 $this->line->rang = $ranktouse;
1411 if (is_array($array_options) && count($array_options) > 0) {
1412 $this->line->array_options = $array_options;
1415 $result = $this->line->insert($user);
1417 if (!isset($this->context[
'createfromclone'])) {
1418 if (!empty($fk_parent)) {
1420 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
1421 $linecount = count($this->lines);
1422 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
1426 $this->lines[] = $this->line;
1429 $this->db->commit();
1430 return $this->line->id;
1432 $this->error = $this->line->error;
1433 dol_syslog(get_class($this).
"::addlinefree error=".$this->error, LOG_ERR);
1434 $this->db->rollback();
1438 dol_syslog(get_class($this).
"::addlinefree status of shipment must be Draft to allow use of ->addlinefree()", LOG_ERR);
1458 public function updatelinefree($rowid, $qty, $element_type, $fk_product, $fk_unit, $rang, $description, $fk_parent, $notrigger, $array_options = array())
1460 global
$mysoc, $langs, $user;
1462 if ($this->
status == self::STATUS_DRAFT) {
1472 $qty = (float) $qty;
1473 $description = trim($description);
1478 $line->fetch($rowid);
1479 $line->fetch_optionals();
1481 if (!empty($line->fk_product)) {
1482 $product =
new Product($this->db);
1483 $result = $product->fetch($line->fk_product);
1484 $product_type = $product->type;
1487 $staticline = clone $line;
1489 $line->oldline = $staticline;
1490 $this->line = $line;
1491 $this->line->context = $this->context;
1492 $this->line->rang = $rang;
1493 $this->line->fk_expedition = $this->id;
1494 $this->line->element_type = $element_type;
1495 $this->line->fk_product = $fk_product;
1496 $this->line->qty = $qty;
1497 $this->line->fk_unit = $fk_unit;
1498 $this->line->fk_parent = $fk_parent;
1499 $this->line->description = $description;
1501 if (is_array($array_options) && count($array_options) > 0) {
1503 foreach ($array_options as $key => $value) {
1504 $this->line->array_options[$key] = $array_options[$key];
1508 $result = $this->line->update($user, $notrigger);
1511 if (!empty($fk_parent)) {
1515 $this->db->commit();
1518 $this->error = $this->line->error;
1520 $this->db->rollback();
1524 $this->error = get_class($this).
"::updatelinefree Shipment status makes operation forbidden";
1525 $this->errors = array(
'ShipmentStatusMakeOperationForbidden');
1539 public function addline_batch($dbatch, $array_options = [], $origin_line =
null)
1544 $num = count($this->lines);
1546 if ($dbatch[
'qty'] > 0 || ($dbatch[
'qty'] == 0 &&
getDolGlobalString(
'SHIPMENT_GETS_ALL_ORDER_PRODUCTS'))) {
1549 foreach ($dbatch[
'detail'] as $key => $value) {
1550 if ($value[
'q'] > 0 || ($value[
'q'] == 0 &&
getDolGlobalString(
'SHIPMENT_GETS_ALL_ORDER_PRODUCTS'))) {
1556 $ret = $linebatch->fetchFromStock($value[
'id_batch']);
1561 $linebatch->qty = $value[
'q'];
1562 if ($linebatch->qty == 0 &&
getDolGlobalString(
'SHIPMENT_GETS_ALL_ORDER_PRODUCTS')) {
1563 $linebatch->batch =
null;
1565 $tab[] = $linebatch;
1568 require_once DOL_DOCUMENT_ROOT.
'/product/class/productbatch.class.php';
1570 $prod_batch->fetch($value[
'id_batch']);
1572 if ($prod_batch->qty < $linebatch->qty) {
1573 $langs->load(
"errors");
1574 $this->errors[] = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnShipment', $prod_batch->fk_product);
1575 dol_syslog(get_class($this).
"::addline_batch error=Product ".$prod_batch->batch.
": ".$this->errorsToString(), LOG_ERR);
1581 if (is_object($linebatch)) {
1582 $line->entrepot_id = $linebatch->fk_warehouse;
1584 $line->origin_line_id = $dbatch[
'ix_l'];
1585 $line->fk_elementdet = $dbatch[
'ix_l'];
1586 $line->qty = $dbatch[
'qty'];
1587 $line->detail_batch = $tab;
1588 if (!($line->rang > 0)) {
1589 $line->rang = $origin_line->rang;
1591 if (!($line->fk_product > 0)) {
1592 $line->fk_product = $origin_line->fk_product;
1596 if (!
getDolGlobalString(
'MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) {
1597 $line->array_options = $array_options;
1601 $this->lines[$num] = $line;
1614 public function update($user =
null, $notrigger = 0)
1621 if (isset($this->
ref)) {
1622 $this->
ref = trim($this->
ref);
1624 if (isset($this->entity)) {
1625 $this->entity = (int) $this->entity;
1627 if (isset($this->ref_customer)) {
1628 $this->ref_customer = trim($this->ref_customer);
1630 if (isset($this->socid)) {
1631 $this->socid = (int) $this->socid;
1633 if (isset($this->fk_user_author)) {
1634 $this->fk_user_author = (int) $this->fk_user_author;
1636 if (isset($this->fk_user_valid)) {
1637 $this->fk_user_valid = (int) $this->fk_user_valid;
1639 if (isset($this->fk_delivery_address)) {
1640 $this->fk_delivery_address = (int) $this->fk_delivery_address;
1642 if (isset($this->shipping_method_id)) {
1643 $this->shipping_method_id = (int) $this->shipping_method_id;
1645 if (isset($this->tracking_number)) {
1646 $this->tracking_number = trim($this->tracking_number);
1648 if (isset($this->statut)) {
1649 $this->statut = (int) $this->statut;
1651 if (isset($this->
status)) {
1654 if (isset($this->trueDepth)) {
1655 $this->trueDepth = trim($this->trueDepth);
1657 if (isset($this->trueWidth)) {
1658 $this->trueWidth = trim($this->trueWidth);
1660 if (isset($this->trueHeight)) {
1661 $this->trueHeight = trim($this->trueHeight);
1663 if (isset($this->size_units)) {
1664 $this->size_units = trim($this->size_units);
1666 if (isset($this->weight_units)) {
1667 $this->weight_units = (int) $this->weight_units;
1669 if (isset($this->trueWeight)) {
1670 $this->weight = trim((
string) $this->trueWeight);
1672 if (isset($this->note_private)) {
1673 $this->note_private = trim($this->note_private);
1675 if (isset($this->note_public)) {
1676 $this->note_public = trim($this->note_public);
1678 if (isset($this->model_pdf)) {
1679 $this->model_pdf = trim($this->model_pdf);
1681 if (!empty($this->date_expedition)) {
1682 $this->date_shipping = $this->date_expedition;
1689 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition SET";
1690 $sql .=
" ref = ".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
1691 $sql .=
" ref_ext = ".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
1692 $sql .=
" ref_customer = ".(isset($this->ref_customer) ?
"'".$this->db->escape($this->ref_customer).
"'" :
"null").
",";
1693 $sql .=
" fk_soc = ".(isset($this->socid) ? ((int) $this->socid) :
"null").
",";
1694 $sql .=
" date_creation = ".(dol_strlen($this->date_creation) != 0 ?
"'".$this->db->idate($this->date_creation).
"'" :
'null').
",";
1695 $sql .=
" fk_user_author = ".(isset($this->fk_user_author) ? ((int) $this->fk_user_author) :
"null").
",";
1696 $sql .=
" date_valid = ".(dol_strlen($this->date_valid) != 0 ?
"'".$this->db->idate($this->date_valid).
"'" :
'null').
",";
1697 $sql .=
" fk_user_valid = ".(isset($this->fk_user_valid) ? ((int) $this->fk_user_valid) :
"null").
",";
1698 $sql .=
" date_expedition = ".(dol_strlen($this->date_shipping) != 0 ?
"'".$this->db->idate($this->date_shipping).
"'" :
'null').
",";
1699 $sql .=
" date_delivery = ".(dol_strlen($this->date_delivery) != 0 ?
"'".$this->db->idate($this->date_delivery).
"'" :
'null').
",";
1700 $sql .=
" fk_address = ".(isset($this->fk_delivery_address) ? ((int) $this->fk_delivery_address) :
"null").
",";
1701 $sql .=
" fk_shipping_method = ".((isset($this->shipping_method_id) && $this->shipping_method_id > 0) ? ((
int) $this->shipping_method_id) :
"null").
",";
1702 $sql .=
" tracking_number = ".(isset($this->tracking_number) ?
"'".$this->db->escape($this->tracking_number).
"'" :
"null").
",";
1703 $sql .=
" fk_statut = ".(isset($this->
status) ? ((int) $this->
status) :
"null").
",";
1704 $sql .=
" fk_projet = ".(isset($this->fk_project) ? ((int) $this->fk_project) :
"null").
",";
1705 $sql .=
" height = ".(($this->trueHeight !=
'') ? ((
float) $this->trueHeight) :
"null").
",";
1706 $sql .=
" width = ".(($this->trueWidth !=
'') ? ((
float) $this->trueWidth) :
"null").
",";
1707 $sql .=
" size_units = ".(isset($this->size_units) ? ((int) $this->size_units) :
"null").
",";
1708 $sql .=
" size = ".(($this->trueDepth !=
'') ? ((
float) $this->trueDepth) :
"null").
",";
1709 $sql .=
" weight_units = ".(isset($this->weight_units) ? ((int) $this->weight_units) :
"null").
",";
1710 $sql .=
" weight = ".(($this->trueWeight !=
'') ? ((
float) $this->trueWeight) :
"null").
",";
1711 $sql .=
" note_private = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
1712 $sql .=
" note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
1713 $sql .=
" model_pdf = ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
1714 $sql .=
" entity = ".((int)
$conf->entity);
1715 $sql .=
" WHERE rowid = ".((int) $this->
id);
1719 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1720 $resql = $this->db->query($sql);
1723 $this->errors[] =
"Error ".$this->db->lasterror();
1734 if (!$error && !$notrigger) {
1736 $result = $this->call_trigger(
'SHIPPING_MODIFY', $user);
1745 foreach ($this->errors as $errmsg) {
1746 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
1747 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1749 $this->db->rollback();
1752 $this->db->commit();
1766 public function cancel($user, $notrigger = 0, $also_update_stock =
false)
1768 global
$conf, $langs, $user;
1770 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1779 if (isset($this->linkedObjectsIds[
'delivery']) && count($this->linkedObjectsIds[
'delivery']) > 0) {
1780 $this->error =
'ErrorThereIsSomeDeliveries';
1784 if (!$error && !$notrigger) {
1786 $result = $this->call_trigger(
'SHIPPING_CANCEL', $user);
1796 (
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT_CLOSE') && $this->
status == self::STATUS_CLOSED && $also_update_stock));
1798 require_once DOL_DOCUMENT_ROOT.
"/product/stock/class/mouvementstock.class.php";
1800 $langs->load(
"agenda");
1804 $sql .=
" ed.fk_product";
1805 $sql .=
", ed.qty, ed.fk_entrepot, ed.rowid as expeditiondet_id";
1806 $sql .=
", SUM(".$this->db->ifsql(
"pa.rowid IS NOT NULL",
"1",
"0").
") as iskit";
1807 $sql .=
", ".$this->db->ifsql(
"pai.incdec IS NULL",
"1",
"pai.incdec").
" as incdec";
1808 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet as ed";
1809 $sql .=
" LEFT JOIN ".$this->db->prefix().
"product_association as pa ON pa.fk_product_pere = ed.fk_product";
1810 $sql .=
" LEFT JOIN ".$this->db->prefix().
"expeditiondet as edp ON edp.rowid = ed.fk_parent";
1811 $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";
1812 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
1813 $sql .=
" GROUP BY ed.fk_product, ed.qty, ed.fk_entrepot, ed.rowid, pai.incdec";
1814 $sql .= $this->db->order(
"ed.rowid",
"DESC");
1816 dol_syslog(get_class($this).
"::delete select details", LOG_DEBUG);
1817 $resql = $this->db->query($sql);
1819 $cpt = $this->db->num_rows($resql);
1823 for ($i = 0; $i < $cpt; $i++) {
1824 dol_syslog(get_class($this).
"::delete movement index ".$i);
1825 $obj = $this->db->fetch_object($resql);
1826 $line_id = (int) $obj->expeditiondet_id;
1828 if ($can_update_stock && (empty($obj->iskit) ||
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) && !empty($obj->incdec)) {
1831 $mouvS->origin =
'';
1835 $lotArray = $shipmentlinebatch->fetchAll($obj->expeditiondet_id);
1836 if (!is_array($lotArray)) {
1838 $this->errors[] =
"Error ".$this->db->lasterror();
1842 if (empty($lotArray)) {
1846 $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));
1849 $this->errors = array_merge($this->errors, $mouvS->errors);
1855 foreach ($lotArray as $lot) {
1856 $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));
1859 $this->errors = array_merge($this->errors, $mouvS->errors);
1872 $res = $shipment_line->fetch($line_id);
1874 $result = $shipment_line->delete($user);
1877 $this->errors[] =
"Error ".$shipment_line->errorsToString();
1881 $this->errors[] =
"Error ".$shipment_line->errorsToString();
1891 $this->errors[] =
"Error ".$this->db->lasterror();
1897 $sql =
"SELECT rowid FROM ".$this->db->prefix().
"expedition";
1898 $sql .=
" WHERE rowid = ".((int) $this->
id);
1900 if ($this->db->query($sql)) {
1901 if (!empty($this->origin) && $this->origin_id > 0) {
1904 '@phan-var-force Facture|Commande $origin_object';
1915 $this->db->commit();
1919 if (!empty(
$conf->expedition->dir_output)) {
1920 $dir =
$conf->expedition->dir_output.
'/sending/'.$ref;
1921 $file = $dir.
'/'.$ref.
'.pdf';
1922 if (file_exists($file)) {
1927 if (file_exists($dir)) {
1929 $this->error = $langs->trans(
"ErrorCanNotDeleteDir", $dir);
1937 $this->error = $this->db->lasterror().
" - sql=$sql";
1938 $this->db->rollback();
1942 $this->db->rollback();
1956 public function delete($user =
null, $notrigger = 0, $also_update_stock =
false)
1958 global
$conf, $langs;
1964 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1973 if (isset($this->linkedObjectsIds[
'delivery']) && count($this->linkedObjectsIds[
'delivery']) > 0) {
1974 $this->error =
'ErrorThereIsSomeDeliveries';
1978 if (!$error && !$notrigger) {
1980 $result = $this->call_trigger(
'SHIPPING_DELETE', $user);
1990 (
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT_CLOSE') && $this->
status == self::STATUS_CLOSED && $also_update_stock));
1992 require_once DOL_DOCUMENT_ROOT.
"/product/stock/class/mouvementstock.class.php";
1994 $langs->load(
"agenda");
2001 $sql .=
" ed.fk_product";
2002 $sql .=
", ed.qty, ed.fk_entrepot, ed.rowid as expeditiondet_id";
2003 $sql .=
", SUM(".$this->db->ifsql(
"pa.rowid IS NOT NULL",
"1",
"0").
") as iskit";
2004 $sql .=
", ".$this->db->ifsql(
"pai.incdec IS NULL",
"1",
"pai.incdec").
" as incdec";
2005 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet as ed";
2006 $sql .=
" LEFT JOIN ".$this->db->prefix().
"product_association as pa ON pa.fk_product_pere = ed.fk_product";
2007 $sql .=
" LEFT JOIN ".$this->db->prefix().
"expeditiondet as edp ON edp.rowid = ed.fk_parent";
2008 $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";
2009 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
2010 $sql .=
" GROUP BY ed.fk_product, ed.qty, ed.fk_entrepot, ed.rowid, pai.incdec";
2011 $sql .= $this->db->order(
"ed.rowid",
"DESC");
2013 dol_syslog(get_class($this).
"::delete select details", LOG_DEBUG);
2014 $resql = $this->db->query($sql);
2016 $cpt = $this->db->num_rows($resql);
2017 for ($i = 0; $i < $cpt; $i++) {
2018 dol_syslog(get_class($this).
"::delete movement index ".$i);
2019 $obj = $this->db->fetch_object($resql);
2020 $line_id = (int) $obj->expeditiondet_id;
2022 if ($can_update_stock && (empty($obj->iskit) ||
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) && !empty($obj->incdec)) {
2025 $mouvS->origin =
'';
2027 $lotArray = $shipmentlinebatch->fetchAll($line_id);
2028 if (!is_array($lotArray)) {
2030 $this->errors[] =
"Error ".$this->db->lasterror();
2032 if (empty($lotArray)) {
2036 $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));
2039 $this->errors = array_merge($this->errors, $mouvS->errors);
2045 foreach ($lotArray as $lot) {
2046 if (empty($lot->qty)) {
2049 $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));
2052 $this->errors = array_merge($this->errors, $mouvS->errors);
2065 $res = $shipment_line->fetch($line_id);
2067 $result = $shipment_line->delete($user);
2070 $this->errors[] =
"Error ".$shipment_line->errorsToString();
2074 $this->errors[] =
"Error ".$shipment_line->errorsToString();
2084 $this->errors[] =
"Error ".$this->db->lasterror();
2109 $sql =
"DELETE FROM ".$this->db->prefix().
"expedition";
2110 $sql .=
" WHERE rowid = ".((int) $this->
id);
2112 if ($this->db->query($sql)) {
2113 if (!empty($this->origin) && $this->origin_id > 0) {
2116 '@phan-var-force Facture|Commande $origin_object';
2126 $this->db->commit();
2134 if (!empty(
$conf->expedition->dir_output) && !empty($ref)) {
2135 $dir =
$conf->expedition->dir_output .
'/sending/' . $ref;
2136 $file = $dir .
'/' . $ref .
'.pdf';
2137 if (file_exists($file)) {
2142 if (file_exists($dir)) {
2144 $this->error = $langs->trans(
"ErrorCanNotDeleteDir", $dir);
2152 $this->error = $this->db->lasterror().
" - sql=$sql";
2153 $this->db->rollback();
2157 $this->db->rollback();
2161 $this->db->rollback();
2177 $this->lines = array();
2182 $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";
2183 $sql .=
", cd.total_ht, cd.total_localtax1, cd.total_localtax2, cd.total_ttc, cd.total_tva";
2184 $sql .=
", cd.fk_remise_except, cd.fk_product_fournisseur_price as fk_fournprice";
2185 $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";
2186 $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";
2187 $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";
2188 $sql .=
", p.ref as product_ref, p.label as product_label, p.fk_product_type, p.barcode as product_barcode";
2189 $sql .=
", p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units";
2190 $sql .=
", p.surface, p.surface_units, p.volume, p.volume_units, p.tosell as product_tosell, p.tobuy as product_tobuy";
2191 $sql .=
", p.tobatch as product_tobatch, p.stockable_product";
2192 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expeditiondet as ed, ".MAIN_DB_PREFIX.
"commandedet as cd";
2193 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"product as p ON p.rowid = cd.fk_product";
2194 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
2195 $sql .=
" AND ed.fk_elementdet = cd.rowid";
2196 $sql .=
" ORDER BY CASE WHEN ed.rang IS NULL OR ed.rang = 0 THEN cd.rang ELSE ed.rang END, ed.rowid";
2198 dol_syslog(get_class($this).
"::fetch_lines", LOG_DEBUG);
2199 $resql = $this->db->query($sql);
2201 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
2203 $num = $this->db->num_rows($resql);
2209 $this->total_ht = 0;
2210 $this->total_tva = 0;
2211 $this->total_ttc = 0;
2212 $this->total_localtax1 = 0;
2213 $this->total_localtax2 = 0;
2215 $this->multicurrency_total_ht = 0;
2216 $this->multicurrency_total_tva = 0;
2217 $this->multicurrency_total_ttc = 0;
2223 $obj = $this->db->fetch_object($resql);
2225 if ($originline > 0 && $originline == $obj->fk_elementdet) {
2227 $line->entrepot_id = 0;
2228 $line->qty_shipped += $obj->qty_shipped;
2231 $line->entrepot_id = $obj->fk_entrepot;
2232 $line->qty_shipped = $obj->qty_shipped;
2236 $detail_entrepot->entrepot_id = $obj->fk_entrepot;
2237 $detail_entrepot->qty_shipped = $obj->qty_shipped;
2238 $detail_entrepot->line_id = $obj->line_id;
2239 $line->details_entrepot[] = $detail_entrepot;
2241 $line->line_id = $obj->line_id;
2242 $line->rowid = $obj->line_id;
2243 $line->id = $obj->line_id;
2245 $line->fk_origin =
'orderline';
2247 $line->fk_element = $obj->fk_element;
2248 $line->origin_id = $obj->fk_element;
2249 $line->fk_elementdet = $obj->fk_elementdet;
2250 $line->origin_line_id = $obj->fk_elementdet;
2251 $line->element_type = $obj->element_type;
2253 $line->fk_expedition = $this->id;
2255 $line->stockable_product = $obj->stockable_product;
2256 $line->product_type = $obj->product_type;
2257 $line->fk_product = $obj->fk_product;
2258 $line->fk_product_type = $obj->fk_product_type;
2259 $line->ref = $obj->product_ref;
2260 $line->product_ref = $obj->product_ref;
2261 $line->product_label = $obj->product_label;
2262 $line->libelle = $obj->product_label;
2263 $line->product_barcode = $obj->product_barcode;
2264 $line->product_tosell = $obj->product_tosell;
2265 $line->product_tobuy = $obj->product_tobuy;
2266 $line->product_tobatch = $obj->product_tobatch;
2267 $line->fk_fournprice = $obj->fk_fournprice;
2268 $line->label = $obj->custom_label;
2269 $line->description = $obj->description;
2270 $line->qty_asked = $obj->qty_asked;
2271 $line->rang = $obj->rang;
2272 $line->weight = $obj->weight;
2273 $line->weight_units = $obj->weight_units;
2274 $line->length = $obj->length;
2275 $line->length_units = $obj->length_units;
2276 $line->width = $obj->width;
2277 $line->width_units = $obj->width_units;
2278 $line->height = $obj->height;
2279 $line->height_units = $obj->height_units;
2280 $line->surface = $obj->surface;
2281 $line->surface_units = $obj->surface_units;
2282 $line->volume = $obj->volume;
2283 $line->volume_units = $obj->volume_units;
2284 $line->stockable_product = $obj->stockable_product;
2285 $line->fk_unit = $obj->fk_unit;
2287 $line->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
2289 $line->pa_ht = $obj->pa_ht;
2292 $localtax_array = array(0 => $obj->localtax1_type, 1 => $obj->localtax1_tx, 2 => $obj->localtax2_type, 3 => $obj->localtax2_tx);
2293 $localtax1_tx =
get_localtax($obj->tva_tx, 1, $this->thirdparty);
2294 $localtax2_tx =
get_localtax($obj->tva_tx, 2, $this->thirdparty);
2297 $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);
2298 $line->desc = $obj->description;
2299 $line->qty = $line->qty_shipped;
2300 $line->total_ht = (float) $tabprice[0];
2301 $line->total_localtax1 = (float) $tabprice[9];
2302 $line->total_localtax2 = (float) $tabprice[10];
2303 $line->total_ttc = (float) $tabprice[2];
2304 $line->total_tva = (float) $tabprice[1];
2305 $line->vat_src_code = $obj->vat_src_code;
2306 $line->tva_tx = $obj->tva_tx;
2307 $line->localtax1_tx = $obj->localtax1_tx;
2308 $line->localtax2_tx = $obj->localtax2_tx;
2309 $line->info_bits = $obj->info_bits;
2310 $line->price = $obj->price;
2311 $line->subprice = $obj->subprice;
2312 $line->fk_remise_except = $obj->fk_remise_except;
2313 $line->remise_percent = $obj->remise_percent;
2315 $this->total_ht += $tabprice[0];
2316 $this->total_tva += $tabprice[1];
2317 $this->total_ttc += $tabprice[2];
2318 $this->total_localtax1 += $tabprice[9];
2319 $this->total_localtax2 += $tabprice[10];
2321 $line->date_start = $this->db->jdate($obj->date_start);
2322 $line->date_end = $this->db->jdate($obj->date_end);
2324 $line->special_code = $obj->special_code;
2327 $this->fk_multicurrency = $obj->fk_multicurrency;
2328 $this->multicurrency_code = $obj->multicurrency_code;
2329 $line->multicurrency_subprice = $obj->multicurrency_subprice;
2330 $line->multicurrency_total_ht = $obj->multicurrency_total_ht;
2331 $line->multicurrency_total_tva = $obj->multicurrency_total_tva;
2332 $line->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
2334 $this->multicurrency_total_ht += $obj->multicurrency_total_ht;
2335 $this->multicurrency_total_tva += $obj->multicurrency_total_tva;
2336 $this->multicurrency_total_ttc += $obj->multicurrency_total_ttc;
2339 if (
isModEnabled(
'productbatch') && $obj->line_id > 0 && $obj->product_tobatch > 0) {
2340 if ($originline != $obj->fk_elementdet) {
2341 $line->detail_batch = array();
2343 $newdetailbatch = $shipmentlinebatch->fetchAll($obj->line_id, $obj->fk_product);
2345 if (is_array($newdetailbatch)) {
2346 if ($originline != $obj->fk_elementdet) {
2347 $line->detail_batch = $newdetailbatch;
2349 $line->detail_batch = array_merge($line->detail_batch, $newdetailbatch);
2356 $detail_children = array();
2357 $line_child_list = array();
2358 $res = $line->findAllChild($line->id, $line_child_list, 1);
2360 foreach ($line_child_list as $child_line) {
2361 foreach ($child_line as $child_obj) {
2362 $child_product_id = (int) $child_obj->fk_product;
2363 $child_warehouse_id = (int) $child_obj->fk_warehouse;
2365 if ($child_warehouse_id > 0) {
2367 if (!isset($detail_children[$child_product_id])) {
2368 $detail_children[$child_product_id] = array();
2370 if (!isset($detail_children[$child_product_id][$child_warehouse_id])) {
2371 $detail_children[$child_product_id][$child_warehouse_id] = 0;
2373 $detail_children[$child_product_id][$child_warehouse_id] += $child_obj->qty;
2378 $line->detail_children = $detail_children;
2381 $line->fetch_optionals();
2383 if ($originline != $obj->fk_elementdet) {
2384 $this->lines[$lineindex] = $line;
2387 $line->total_ht += $tabprice[0];
2388 $line->total_localtax1 += $tabprice[9];
2389 $line->total_localtax2 += $tabprice[10];
2390 $line->total_ttc += $tabprice[2];
2391 $line->total_tva += $tabprice[1];
2395 $originline = $obj->fk_elementdet;
2397 $this->db->free($resql);
2400 $this->error = $this->db->error();
2417 $this->lines = array();
2419 $sql =
'SELECT ed.rowid, ed.fk_expedition, ed.fk_entrepot, ed.fk_product, ed.fk_unit, ed.description, ed.fk_elementdet, ed.fk_element, ed.element_type, ed.qty, ed.rang';
2420 $sql .=
' FROM '.MAIN_DB_PREFIX.$this->table_element_line.
' as ed';
2421 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON (p.rowid = ed.fk_product)';
2422 $sql .=
' WHERE ed.fk_expedition = '.((int) $this->
id);
2423 $sql .=
' ORDER BY ed.rang, ed.rowid';
2425 dol_syslog(get_class($this).
"::fetch_lines_free", LOG_DEBUG);
2426 $result = $this->db->query($sql);
2428 $num = $this->db->num_rows($result);
2432 $objp = $this->db->fetch_object($result);
2436 $line->rowid = $objp->rowid;
2437 $line->id = $objp->rowid;
2438 $line->fk_expedition = $this->id;
2439 $line->description = $objp->description;
2440 $line->qty = $objp->qty;
2441 $line->fk_entrepot = $objp->fk_entrepot;
2442 $line->fk_product = $objp->fk_product;
2443 $line->rang = $objp->rang;
2444 $line->fk_element = $objp->fk_element;
2445 $line->fk_unit = $objp->fk_unit;
2446 $line->fk_elementdet = $objp->fk_elementdet;
2447 $line->fk_element_type = $objp->element_type;
2448 $line->fetch_optionals();
2450 $this->lines[$i] = $line;
2455 $this->db->free($result);
2459 $this->error = $this->db->error();
2485 if ($this->
status == self::STATUS_DRAFT) {
2491 $line->fetch($lineid);
2493 if ($line->delete($user) > 0) {
2496 $this->db->commit();
2499 $this->db->rollback();
2503 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
2517 global
$conf, $langs;
2519 $langs->load(
'sendings');
2521 $nofetch = !empty($params[
'nofetch']);
2524 $datas[
'picto'] =
img_picto(
'', $this->picto).
' <u class="paddingrightonly">'.$langs->trans(
"Shipment").
'</u>';
2525 if (isset($this->
status)) {
2526 $datas[
'picto'] .=
' '.$this->getLibStatut(5);
2528 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
2529 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.($this->ref_customer ? $this->ref_customer : $this->ref_client);
2531 $langs->load(
'companies');
2532 if (empty($this->thirdparty)) {
2535 $datas[
'customer'] =
'<br><b>'.$langs->trans(
'Customer').
':</b> '.$this->thirdparty->getNomUrl(1,
'', 0, 1);
2552 public function getNomUrl($withpicto = 0, $option =
'', $max = 0, $short = 0, $notooltip = 0, $save_lastsearch_value = -1)
2554 global $langs, $hookmanager;
2559 'objecttype' => $this->element,
2560 'option' => $option,
2563 $classfortooltip =
'classfortooltip';
2566 $classfortooltip =
'classforajaxtooltip';
2567 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
2573 $url = DOL_URL_ROOT.
'/expedition/card.php?id='.$this->id;
2579 if ($option !==
'nolink') {
2581 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2582 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
2583 $add_save_lastsearch_values = 1;
2585 if ($add_save_lastsearch_values) {
2586 $url .=
'&save_lastsearch_values=1';
2591 if (empty($notooltip)) {
2593 $label = $langs->trans(
"Shipment");
2594 $linkclose .=
' alt="'.dolPrintHTMLForAttribute($label).
'"';
2596 $linkclose .= ($label ?
' title="'.dolPrintHTMLForAttribute($label).
'"' :
' title="tocomplete"');
2597 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
2600 $linkstart =
'<a href="'.$url.
'"';
2601 $linkstart .= $linkclose.
'>';
2604 $result .= $linkstart;
2606 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), ($notooltip ? (($withpicto != 2) ?
'class="paddingright"' :
'') :
'class="'.(($withpicto != 2) ?
'paddingright ' :
'').
'"'), 0, 0, $notooltip ? 0 : 1);
2608 if ($withpicto != 2) {
2609 $result .= $this->ref;
2611 $result .= $linkend;
2613 $hookmanager->initHooks(array($this->element .
'dao'));
2614 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result);
2615 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
2617 $result = $hookmanager->resPrint;
2619 $result .= $hookmanager->resPrint;
2648 $labelStatus = $langs->transnoentitiesnoconv($this->labelStatus[$status]);
2649 $labelStatusShort = $langs->transnoentitiesnoconv($this->labelStatusShort[$status]);
2651 $statusType =
'status'.$status;
2652 if ($status == self::STATUS_VALIDATED) {
2653 $statusType =
'status4';
2655 if ($status == self::STATUS_CLOSED) {
2656 $statusType =
'status6';
2658 if ($status == self::STATUS_CANCELED) {
2659 $statusType =
'status9';
2663 $status_label = $this->signed_status ? $labelStatus . $signed_label : $labelStatus;
2664 $status_label_short = $this->signed_status ? $labelStatusShort . $signed_label : $labelStatusShort;
2666 return dolGetStatus($status_label, $status_label_short,
'', $statusType, $mode);
2678 global $langs,
$conf;
2680 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
2682 $return =
'<div class="box-flex-item box-flex-grow-zero">';
2683 $return .=
'<div class="info-box info-box-sm">';
2684 $return .=
'<div class="info-box-icon bg-infobox-action">';
2686 $return .=
'</div>';
2687 $return .=
'<div class="info-box-content">';
2688 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->
getNomUrl() .
'</span>';
2689 if ($selected >= 0) {
2690 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
2692 $return .=
'<br><div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).
'</div>';
2693 $return .=
'<div class="info-box-ref amount">'.price($this->total_ht, 0, $langs, 0, -1, -1,
getDolCurrency()).
' '.$langs->trans(
'HT').
'</div>';
2694 $return .=
'<div class="info-box-status">'.$this->getLibStatut(3).
'</div>';
2695 $return .=
'</div>';
2696 $return .=
'</div>';
2697 $return .=
'</div>';
2715 dol_syslog(get_class($this).
"::initAsSpecimen");
2718 $order->initAsSpecimen();
2722 $this->
ref =
'SPECIMEN';
2723 $this->specimen = 1;
2725 $this->livraison_id = 0;
2727 $this->date_creation = $now;
2728 $this->date_valid = $now;
2729 $this->date_delivery = $now + 24 * 3600;
2730 $this->date_expedition = $now + 24 * 3600;
2732 $this->entrepot_id = 0;
2733 $this->fk_delivery_address = 0;
2736 $this->commande_id = 0;
2737 $this->commande = $order;
2739 $this->origin_id = 1;
2740 $this->origin_type =
'commande';
2742 $this->note_private =
'Private note';
2743 $this->note_public =
'Public note';
2747 while ($xnbp < $nbp) {
2749 $line->product_desc = $langs->trans(
"Description").
" ".$xnbp;
2750 $line->product_label = $langs->trans(
"Description").
" ".$xnbp;
2752 $line->qty_asked = 5;
2753 $line->qty_shipped = 4;
2754 $line->fk_product = $this->commande->lines[$xnbp]->fk_product;
2756 $line->weight = 1.123456;
2757 $line->weight_units = 0;
2759 $line->volume = 2.34567;
2760 $line->volume_unit = 0;
2762 $this->lines[] = $line;
2794 if ($user->hasRight(
'expedition',
'creer')) {
2797 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
2798 $sql .=
" SET date_delivery = ".($delivery_date ?
"'".$this->db->idate($delivery_date).
"'" :
'null');
2799 $sql .=
" WHERE rowid = ".((int) $this->
id);
2801 dol_syslog(get_class($this).
"::setDeliveryDate", LOG_DEBUG);
2802 $resql = $this->db->query($sql);
2804 $this->date_delivery = $delivery_date;
2808 $result = $this->call_trigger(
'SHIPPING_MODIFY', $user);
2810 $this->db->rollback();
2816 $this->db->commit();
2819 $this->error = $this->db->error();
2820 $this->db->rollback();
2838 if ($user->hasRight(
'expedition',
'creer')) {
2841 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
2842 $sql .=
" SET date_expedition = ".($shipping_date ?
"'".$this->db->idate($shipping_date).
"'" :
'null');
2843 $sql .=
" WHERE rowid = ".((int) $this->
id);
2845 dol_syslog(get_class($this).
"::setShippingDate", LOG_DEBUG);
2846 $resql = $this->db->query($sql);
2848 $this->date_shipping = $shipping_date;
2852 $result = $this->call_trigger(
'SHIPPING_MODIFY', $user);
2854 $this->db->rollback();
2860 $this->db->commit();
2863 $this->error = $this->db->error();
2864 $this->db->rollback();
2884 $sql =
"SELECT em.rowid, em.code, em.libelle as label";
2885 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2886 $sql .=
" WHERE em.active = 1";
2887 $sql .=
" ORDER BY em.libelle ASC";
2889 $resql = $this->db->query($sql);
2891 while ($obj = $this->db->fetch_object($resql)) {
2892 $label = $langs->trans(
'SendingMethod'.$obj->code);
2893 $this->meths[(int) $obj->rowid] = ($label !=
'SendingMethod'.$obj->code ? $label : $obj->label);
2910 $this->listmeths = [];
2913 $sql =
"SELECT em.rowid, em.code, em.libelle as label, em.description, em.tracking, em.active";
2914 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2916 $sql .=
" WHERE em.rowid=".((int) $id);
2919 $resql = $this->db->query($sql);
2921 while ($obj = $this->db->fetch_object($resql)) {
2922 $label = $langs->trans(
'SendingMethod'.$obj->code);
2923 $this->listmeths[$i] = [
2924 'rowid' => (int) $obj->rowid,
2925 'code' => $obj->code,
2926 'libelle' => ($label !=
'SendingMethod'.$obj->code ? $label : $obj->label),
2927 'description' => $obj->description,
2928 'tracking' => $obj->tracking,
2929 'active' => (
int) $obj->active,
2945 if (!empty($this->shipping_method_id)) {
2946 $sql =
"SELECT em.code, em.tracking";
2947 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2948 $sql .=
" WHERE em.rowid = ".((int) $this->shipping_method_id);
2950 $resql = $this->db->query($sql);
2952 if ($obj = $this->db->fetch_object($resql)) {
2953 $tracking = (
string) $obj->tracking;
2958 if (!empty($tracking) && !empty($value)) {
2959 $url = str_replace(
'{TRACKID}', $value, $tracking);
2960 $this->tracking_url = sprintf(
'<a target="_blank" rel="noopener noreferrer" href="%s">%s</a>', $url, $value);
2962 $this->tracking_url = $value;
2978 if ($this->
status == self::STATUS_CLOSED) {
2983 if ($this->
status == self::STATUS_DRAFT) {
2984 $this->
valid($user);
2990 if (empty($this->date_shipping)) {
2991 $sql .=
", date_expedition = '".$this->db->escape($this->db->idate(
dol_now())).
"'";
2993 $sql .=
" WHERE rowid = ".((int) $this->
id).
" AND fk_statut > 0";
2995 $resql = $this->db->query($sql);
2998 if ($this->origin_type ==
'commande' && $this->origin_id > 0) {
3000 $order->fetch($this->origin_id);
3002 $order->loadExpeditions(self::STATUS_CLOSED);
3004 $shipments_match_order = 1;
3005 foreach ($order->lines as $line) {
3006 $lineid = $line->id;
3008 if (($line->product_type == 0 ||
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES')) && $order->expeditions[$lineid] != $qty) {
3009 $shipments_match_order = 0;
3010 $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';
3015 if ($shipments_match_order) {
3016 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');
3018 $order->cloture($user);
3036 $result = $this->call_trigger(
'SHIPPING_CLOSED', $user);
3047 $this->db->commit();
3053 $this->db->rollback();
3072 require_once DOL_DOCUMENT_ROOT .
'/product/stock/class/mouvementstock.class.php';
3074 $langs->load(
"agenda");
3078 $sql .=
" ed.rowid as edid, ed.fk_product, ed.qty, ed.fk_entrepot";
3079 $sql .=
", cd.rowid as cdid";
3080 $sql .=
", cd.subprice";
3081 $sql .=
", edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
3083 $sql .=
" FROM " . $this->db->prefix() .
"expeditiondet as ed";
3084 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"commandedet as cd ON cd.rowid = ed.fk_elementdet";
3085 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
3086 $sql .=
" INNER JOIN " . $this->db->prefix() .
"expedition as e ON ed.fk_expedition = e.rowid";
3087 $sql .=
" WHERE ed.fk_expedition = " . ((int) $this->
id);
3090 dol_syslog(get_class($this) .
"::valid select details", LOG_DEBUG);
3091 $resql = $this->db->query($sql);
3093 $cpt = $this->db->num_rows($resql);
3094 for ($i = 0; $i < $cpt; $i++) {
3095 $obj = $this->db->fetch_object($resql);
3096 if (empty($obj->edbrowid)) {
3099 $qty = $obj->edbqty;
3101 if ($qty <= 0 || ($qty < 0 && !
getDolGlobalInt(
'SHIPMENT_ALLOW_NEGATIVE_QTY'))) {
3104 dol_syslog(get_class($this) .
"::valid movement index " . $i .
" ed.rowid=" . $obj->edid .
" edb.rowid=" . $obj->edbrowid);
3107 $mouvS->origin = &$this;
3108 $mouvS->setOrigin($this->element, $this->
id, $obj->cdid, $obj->edid);
3110 if (empty($obj->edbrowid)) {
3114 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans($labelmovement, $obj->ref));
3124 $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);
3134 $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)";
3135 $resqldelete = $this->db->query($sqldelete);
3139 $this->error = $this->db->lasterror();
3140 $this->errors[] = $this->db->lasterror();
3163 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'expedition SET billed = 1';
3164 $sql .=
" WHERE rowid = ".((int) $this->
id).
' AND fk_statut > 0';
3166 $resql = $this->db->query($sql);
3171 $result = $this->call_trigger(
'SHIPPING_BILLED', $user);
3178 $this->errors[] = $this->db->lasterror;
3181 if (empty($error)) {
3182 $this->db->commit();
3185 $this->db->rollback();
3200 if ($this->
status <= self::STATUS_DRAFT) {
3204 return $this->
setStatusCommon($user, self::STATUS_DRAFT, $notrigger,
'SHIPMENT_UNVALIDATE');
3214 global $langs, $user;
3219 if ($this->
status == self::STATUS_VALIDATED) {
3225 $oldbilled = $this->billed;
3227 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'expedition SET fk_statut = 1';
3228 $sql .=
" WHERE rowid = ".((int) $this->
id).
' AND fk_statut > 0';
3230 $resql = $this->db->query($sql);
3238 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3240 $langs->load(
"agenda");
3244 $sql =
"SELECT cd.fk_product, cd.subprice,";
3245 $sql .=
" ed.rowid, ed.qty, ed.fk_entrepot,";
3246 $sql .=
" edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
3247 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commandedet as cd,";
3248 $sql .=
" ".MAIN_DB_PREFIX.
"expeditiondet as ed";
3249 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
3250 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
3251 $sql .=
" AND cd.rowid = ed.fk_elementdet";
3253 dol_syslog(get_class($this).
"::valid select details", LOG_DEBUG);
3254 $resql = $this->db->query($sql);
3256 $cpt = $this->db->num_rows($resql);
3257 for ($i = 0; $i < $cpt; $i++) {
3258 $obj = $this->db->fetch_object($resql);
3259 if (empty($obj->edbrowid)) {
3262 $qty = $obj->edbqty;
3267 dol_syslog(get_class($this).
"::reopen expedition movement index ".$i.
" ed.rowid=".$obj->rowid.
" edb.rowid=".$obj->edbrowid);
3271 $mouvS->origin = &$this;
3272 $mouvS->setOrigin($this->element, $this->
id);
3274 if (empty($obj->edbrowid)) {
3278 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans(
"ShipmentUnClassifyCloseddInDolibarr", $this->ref));
3288 $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);
3297 $this->error = $this->db->lasterror();
3304 $result = $this->call_trigger(
'SHIPPING_REOPEN', $user);
3311 $this->errors[] = $this->db->lasterror();
3315 $this->db->commit();
3320 $this->billed = $oldbilled;
3321 $this->db->rollback();
3337 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
3339 $outputlangs->load(
"products");
3344 if (!empty($this->model_pdf)) {
3345 $modele = $this->model_pdf;
3351 $modelpath =
"core/modules/expedition/doc/";
3355 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.
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...
line_order($renum=false, $rowidorder='ASC', $fk_parent_line=true)
Save a new position (field rang) for details lines.
deleteEcmFiles($mode=0)
Delete related files of object in database.
setStatut($status, $elementId=null, $elementType='', $trigkey='', $fieldstatus='')
Set status of an object.
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
updateRangOfLine($rowid, $rang)
Update position of line (rang)
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.
line_max($fk_parent_line=0)
Get max value used for position of line (rang)
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.
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.
setShippingDate($user, $shipping_date, $notrigger=0)
Set the shipping date.
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
addlinefree($qty, $element_type, $fk_product, $fk_unit, $rang, $description, $fk_parent, $array_options=[])
Add a simple expedition line.
getKanbanView($option='', $arraydata=null)
Return clickable link of object (with eventually picto)
const STATUS_DRAFT
Draft status.
setDeliveryDate($user, $delivery_date, $notrigger=0)
Set the planned delivery date.
line_ajaxorder($rows)
Override to keep every expeditiondet row that belongs to the displayed line in sync when drag & drop ...
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.
updatelinefree($rowid, $qty, $element_type, $fk_product, $fk_unit, $rang, $description, $fk_parent, $notrigger, $array_options=array())
Update a simple expedition line.
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.
fetch_lines_free()
Load lines of simple 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.
getLinesArray()
Create an array of shipment lines.
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.
dol_now($mode='gmt')
Return date for now.
setEntity($currentobject)
Set entity id to use when to create an object.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getDolCurrency()
Return the main currency ('EUR', 'USD', ...)
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
get_localtax($vatrate, $local, $thirdparty_buyer=null, $thirdparty_seller=null, $vatnpr=0)
Return localtax rate for a particular VAT rate, when selling a product with vat $vatrate,...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
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)
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $notused, $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.
print $langs trans('Date')." left Ref Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right Paid right PaymentTypeShortLIQ right SELECT p pos_change as p datep as date
$conf db user
Active Directory does not allow anonymous connections.