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;
352 $this->ismultientitymanaged = 1;
353 $this->isextrafieldmanaged = 1;
356 $this->labelStatus = array();
357 $this->labelStatus[-1] =
'StatusSendingCanceled';
358 $this->labelStatus[0] =
'StatusSendingDraft';
359 $this->labelStatus[1] =
'StatusSendingValidated';
360 $this->labelStatus[2] =
'StatusSendingProcessed';
363 $this->labelStatusShort = array();
364 $this->labelStatusShort[-1] =
'StatusSendingCanceledShort';
365 $this->labelStatusShort[0] =
'StatusSendingDraftShort';
366 $this->labelStatusShort[1] =
'StatusSendingValidatedShort';
367 $this->labelStatusShort[2] =
'StatusSendingProcessedShort';
376 public function getNextNumRef($soc)
378 global $langs, $conf;
379 $langs->load(
"sendings");
388 $dirmodels = array_merge(array(
'/'), (array) $conf->modules_parts[
'models']);
390 foreach ($dirmodels as $reldir) {
394 $mybool = ((bool) @include_once $dir.$file) || $mybool;
402 $obj =
new $classname();
403 '@phan-var-force ModelNumRefExpedition $obj';
405 $numref = $obj->getNextValue($soc, $this);
410 dol_print_error($this->db, get_class($this).
"::getNextNumRef ".$obj->error);
414 print $langs->trans(
"Error").
" ".$langs->trans(
"Error_EXPEDITION_ADDON_NUMBER_NotDefined");
426 public function create($user, $notrigger = 0)
430 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
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";
475 $sql .=
") VALUES (";
477 $sql .=
", ".((int) $this->entity);
478 $sql .=
", ".($this->ref_customer ?
"'".$this->db->escape($this->ref_customer).
"'" :
"null");
479 $sql .=
", ".($this->ref_ext ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
480 $sql .=
", '".$this->db->idate($this->date_creation).
"'";
481 $sql .=
", ".((int) $user->id);
482 $sql .=
", ".($this->date_shipping > 0 ?
"'".$this->db->idate($this->date_shipping).
"'" :
"null");
483 $sql .=
", ".($this->date_delivery > 0 ?
"'".$this->db->idate($this->date_delivery).
"'" :
"null");
484 $sql .=
", ".($this->socid > 0 ? ((int) $this->socid) :
"null");
485 $sql .=
", ".($this->fk_project > 0 ? ((int) $this->fk_project) :
"null");
486 $sql .=
", ".($this->fk_delivery_address > 0 ? ((int) $this->fk_delivery_address) :
"null");
487 $sql .=
", ".($this->shipping_method_id > 0 ? ((int) $this->shipping_method_id) :
"null");
488 $sql .=
", '".$this->db->escape($this->tracking_number).
"'";
489 $sql .=
", ".(is_numeric($this->weight) ? (float) $this->weight :
'NULL');
490 $sql .=
", ".(is_numeric($this->sizeS) ? (float) $this->sizeS :
'NULL');
491 $sql .=
", ".(is_numeric($this->sizeW) ? (float) $this->sizeW :
'NULL');
492 $sql .=
", ".(is_numeric($this->sizeH) ? (float) $this->sizeH :
'NULL');
493 $sql .=
", ".($this->weight_units !=
'' ? (int) $this->weight_units :
'NULL');
494 $sql .=
", ".($this->size_units !=
'' ? (int) $this->size_units :
'NULL');
495 $sql .=
", ".(!empty($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null");
496 $sql .=
", ".(!empty($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null");
497 $sql .=
", ".(!empty($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null");
498 $sql .=
", ".((int) $this->fk_incoterms);
499 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
500 $sql .=
", ".((int) $this->signed_status);
503 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
504 $resql = $this->db->query($sql);
506 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
"expedition");
509 $initialref =
'(PROV'.$this->id.
')';
510 if (!empty($this->
ref)) {
511 $initialref = $this->ref;
514 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
515 $sql .=
" SET ref = '".$this->db->escape($initialref).
"'";
516 $sql .=
" WHERE rowid = ".((int) $this->
id);
518 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
519 if ($this->db->query($sql)) {
520 $this->
ref = $initialref;
522 $num = count($this->lines);
523 $kits_list = array();
525 for ($i = 0; $i < $num; $i++) {
527 $objectsrc->fetch($this->lines[$i]->origin_line_id);
528 if ($this->lines[$i]->product_type ==
"9" && $objectsrc->special_code == SUBTOTALS_SPECIAL_CODE) {
529 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) {
536 $line = $this->lines[$i];
537 if ($line->fk_product > 0) {
543 if (!isset($kits_list[$line->fk_elementdet])) {
544 if (!is_object($line->product)) {
545 $line_product =
new Product($this->db);
546 $result = $line_product->fetch($line->fk_product,
'',
'',
'', 1, 1, 1);
551 $line_product = $line->product;
555 $line_product->get_sousproduits_arbo();
556 $prods_arbo = $line_product->get_arbo_each_prod($line->qty);
557 if (count($prods_arbo) > 0) {
558 $kits_list[$line->fk_elementdet] = array(
559 'arbo' => $prods_arbo,
560 'total_qty' => $line->qty,
564 $kits_list[$line->fk_elementdet][
'total_qty'] += $line->qty;
570 $kits_id_cached = array();
571 $sub_kits_id_cached = array();
572 $sub_parents_cached = array();
573 for ($i = 0; $i < $num; $i++) {
574 $line = $this->lines[$i];
577 if (!isset($kits_id_cached[$line->fk_elementdet])) {
578 if (!isset($line->detail_batch) || (isset($kits_list[$line->fk_elementdet]) && !
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE'))) {
579 $qty = isset($kits_list[$line->fk_elementdet]) ? $kits_list[$line->fk_elementdet][
'total_qty'] : $line->qty;
580 $warehouse_id = (isset($kits_list[$line->fk_elementdet]) && !
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) ? 0 : $line->entrepot_id;
581 $line_id = $this->
create_line($warehouse_id, $line->origin_line_id, $qty, $line->rang, $line->array_options, 0, $line->fk_product);
585 if (isset($kits_list[$line->fk_elementdet])) {
586 $kits_id_cached[$line->fk_elementdet] = $line_id;
594 $line_id = $kits_id_cached[$line->fk_elementdet];
598 if (isset($kits_list[$line->fk_elementdet]) && !
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) {
599 $prods_arbo = $kits_list[$line->fk_elementdet][
'arbo'];
602 $parent_line_id = $line_id;
604 $product_child_id = 0;
605 foreach ($prods_arbo as $index => $product_child_arr) {
620 $product_child_level = (int) $product_child_arr[
'level'];
621 $product_child_incdec = !empty($product_child_arr[
'incdec']);
624 if ($product_child_level != $level_last) {
625 $parent_line_id = $line_id;
626 $parent_product_id = $product_child_id;
627 if (isset($sub_parents_cached[$line->fk_elementdet][$parent_product_id])) {
628 $parent_line_id = $sub_parents_cached[$line->fk_elementdet][$parent_product_id];
630 $sub_parents_cached[$line->fk_elementdet][$parent_product_id] = $parent_line_id;
636 $next_level = $product_child_level;
637 $next_index = $index + 1;
638 if (isset($prods_arbo[$next_index])) {
639 $next_level = (int) $prods_arbo[$next_index][
'level'];
641 if ($next_level > $product_child_level) {
646 $product_child_id = (int) $product_child_arr[
'id'];
647 $product_child_qty = (float) $product_child_arr[
'nb_total'];
648 $warehouse_id = $line->entrepot_id;
649 if ($is_kit || !$product_child_incdec) {
650 if (!$product_child_incdec) {
651 $product_child_qty = 0;
657 if (!isset($sub_kits_id_cached[$line->fk_elementdet][$product_child_id]) || $warehouse_id > 0) {
658 $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);
666 if (empty($warehouse_id)) {
667 $sub_kits_id_cached[$line->fk_elementdet][$product_child_id] = $line_id;
671 $level_last = $product_child_level;
677 if (!$error && $this->
id && $this->origin_id) {
684 if (!$error && $this->
id &&
getDolGlobalInt(
'SHIPPING_USE_ITS_OWN_CONTACTS') &&
getDolGlobalString(
'MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN') && !empty($this->origin_type) && !empty($this->origin_id)) {
685 $originforcontact = $this->origin_type;
686 $originidforcontact = $this->origin_id;
688 $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";
689 $sqlcontact .=
" WHERE element_id = ".((int) $originidforcontact).
" AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$this->db->escape($originforcontact).
"'";
691 $resqlcontact = $this->db->query($sqlcontact);
693 while ($objcontact = $this->db->fetch_object($resqlcontact)) {
694 $this->
add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source);
709 if (!$error && !$notrigger) {
711 $result = $this->call_trigger(
'SHIPPING_CREATE', $user);
721 foreach ($this->errors as $errmsg) {
722 dol_syslog(get_class($this).
"::create ".$errmsg, LOG_ERR);
723 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
725 $this->db->rollback();
730 $this->db->rollback();
735 $this->error = $this->db->lasterror().
" - sql=$sql";
736 $this->db->rollback();
741 $this->error = $this->db->error().
" - sql=$sql";
742 $this->db->rollback();
760 public function create_line($entrepot_id, $origin_line_id, $qty, $rang = 0, $array_options = [], $parent_line_id = 0, $product_id = 0)
766 $expeditionline->fk_expedition = $this->id;
767 $expeditionline->entrepot_id = $entrepot_id;
768 $expeditionline->fk_elementdet = $origin_line_id;
769 $expeditionline->element_type = $this->origin;
770 $expeditionline->fk_parent = $parent_line_id;
771 $expeditionline->fk_product = $product_id;
772 $expeditionline->qty = $qty;
773 $expeditionline->rang = $rang;
774 $expeditionline->array_options = $array_options;
776 if (!($expeditionline->fk_product > 0)) {
778 $order_line->fetch($expeditionline->fk_elementdet);
779 $expeditionline->fk_product = $order_line->fk_product;
782 if (($lineId = $expeditionline->insert($user)) < 0) {
783 $this->errors[] = $expeditionline->error;
801 $stockLocationQty = array();
803 $tab = $line_ext->detail_batch;
805 foreach ($tab as $detbatch) {
806 if (!empty($detbatch->fk_warehouse)) {
807 if (empty($stockLocationQty[$detbatch->fk_warehouse])) {
808 $stockLocationQty[$detbatch->fk_warehouse] = 0;
810 $stockLocationQty[$detbatch->fk_warehouse] += $detbatch->qty;
814 foreach ($stockLocationQty as $stockLocation => $qty) {
815 $line_id = $this->
create_line($stockLocation, $line_ext->origin_line_id, $qty, $line_ext->rang, $array_options);
820 foreach ($tab as $detbatch) {
821 if ($detbatch->fk_warehouse == $stockLocation) {
822 if (!($detbatch->create($line_id) > 0)) {
823 $this->errors = $detbatch->errors;
847 public function fetch($id, $ref =
'', $ref_ext =
'', $notused =
'')
852 if (empty($id) && empty($ref) && empty($ref_ext)) {
856 $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";
857 $sql .=
", e.date_valid";
858 $sql .=
", e.weight, e.weight_units, e.size, e.size_units, e.width, e.height";
859 $sql .=
", e.date_expedition as date_expedition, e.model_pdf, e.fk_address, e.date_delivery";
860 $sql .=
", e.fk_shipping_method, e.tracking_number";
861 $sql .=
", e.note_private, e.note_public";
862 $sql .=
', e.fk_incoterms, e.location_incoterms';
863 $sql .=
', e.signed_status';
864 $sql .=
', i.libelle as label_incoterms';
865 $sql .=
', s.libelle as shipping_method';
866 $sql .=
", el.fk_source as origin_id, el.sourcetype as origin_type";
867 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expedition as e";
868 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"element_element as el ON el.fk_target = e.rowid AND el.targettype = '".$this->db->escape($this->element).
"'";
869 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON e.fk_incoterms = i.rowid';
870 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_shipment_mode as s ON e.fk_shipping_method = s.rowid';
871 $sql .=
" WHERE e.entity IN (".getEntity(
'expedition').
")";
873 $sql .=
" AND e.rowid = ".((int) $id);
876 $sql .=
" AND e.ref='".$this->db->escape($ref).
"'";
879 $sql .=
" AND e.ref_ext='".$this->db->escape($ref_ext).
"'";
882 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
883 $result = $this->db->query($sql);
885 if ($this->db->num_rows($result)) {
886 $obj = $this->db->fetch_object($result);
888 $this->
id = (int) $obj->rowid;
889 $this->entity = $obj->entity;
890 $this->
ref = $obj->ref;
891 $this->socid = $obj->socid;
892 $this->ref_customer = $obj->ref_customer;
893 $this->ref_ext = $obj->ref_ext;
894 $this->
status = $obj->fk_statut;
895 $this->statut = $this->status;
896 $this->signed_status = $obj->signed_status;
897 $this->user_author_id = $obj->fk_user_author;
898 $this->fk_user_author = $obj->fk_user_author;
899 $this->user_creation_id = $obj->fk_user_author;
900 $this->date_creation = $this->db->jdate($obj->date_creation);
901 $this->date_valid = $this->db->jdate($obj->date_valid);
902 $this->
date = $this->db->jdate($obj->date_expedition);
903 $this->date_expedition = $this->db->jdate($obj->date_expedition);
904 $this->date_shipping = $this->db->jdate($obj->date_expedition);
905 $this->date_delivery = $this->db->jdate($obj->date_delivery);
906 $this->fk_delivery_address = $obj->fk_address;
907 $this->model_pdf = $obj->model_pdf;
908 $this->shipping_method_id = $obj->fk_shipping_method;
909 $this->shipping_method = $obj->shipping_method;
910 $this->tracking_number = $obj->tracking_number;
911 $this->origin = ($obj->origin_type ? $obj->origin_type :
'commande');
912 $this->origin_type = ($obj->origin_type ? $obj->origin_type :
'commande');
913 $this->origin_id = $obj->origin_id;
914 $this->billed = $obj->billed;
915 $this->fk_project = $obj->fk_project;
916 $this->signed_status = $obj->signed_status;
917 $this->trueWeight = $obj->weight;
918 $this->weight_units = $obj->weight_units;
920 $this->trueWidth = $obj->width;
921 $this->width_units = $obj->size_units;
922 $this->trueHeight = $obj->height;
923 $this->height_units = $obj->size_units;
924 $this->trueDepth = $obj->size;
925 $this->depth_units = $obj->size_units;
927 $this->note_public = $obj->note_public;
928 $this->note_private = $obj->note_private;
931 $this->trueSize = $obj->size.
"x".$obj->width.
"x".$obj->height;
932 $this->size_units = $obj->size_units;
935 $this->fk_incoterms = $obj->fk_incoterms;
936 $this->location_incoterms = $obj->location_incoterms;
937 $this->label_incoterms = $obj->label_incoterms;
939 $this->db->free($result);
952 if (!empty($this->multicurrency_code)) {
953 $this->multicurrency_code = $this->thirdparty->multicurrency_code;
955 if (
getDolGlobalString(
'MULTICURRENCY_USE_ORIGIN_TX') && !empty($this->thirdparty->multicurrency_tx)) {
956 $this->multicurrency_tx = $this->thirdparty->multicurrency_tx;
963 if (empty($obj->origin_id)) {
974 dol_syslog(get_class($this).
'::Fetch no expedition found', LOG_ERR);
975 $this->error =
'Shipment with id '.$id.
' not found';
979 $this->error = $this->db->error();
991 public function valid($user, $notrigger = 0)
995 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1001 dol_syslog(get_class($this).
"::valid not in draft status", LOG_WARNING);
1005 if (!isset($this->socid)) {
1006 dol_syslog(get_class($this).
"::can't valid socid not set", LOG_WARNING);
1010 if (!((!
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'expedition',
'creer'))
1011 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'expedition',
'shipping_advance',
'validate')))) {
1012 $this->error =
'Permission denied';
1013 dol_syslog(get_class($this).
"::valid ".$this->error, LOG_ERR);
1022 $soc =
new Societe($this->db);
1023 $soc->fetch($this->socid);
1026 $result = $soc->setAsCustomer();
1029 if (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
1030 $numref = $this->getNextNumRef($soc);
1031 } elseif (!empty($this->
ref)) {
1032 $numref = (string) $this->
ref;
1034 $numref =
"EXP".$this->id;
1041 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition SET";
1042 $sql .=
" ref = '".$this->db->escape($numref).
"'";
1043 $sql .=
", fk_statut = 1";
1044 $sql .=
", date_valid = '".$this->db->idate($now).
"'";
1045 $sql .=
", fk_user_valid = ".((int) $user->id);
1046 $sql .=
" WHERE rowid = ".((int) $this->
id);
1048 dol_syslog(get_class($this).
"::valid update expedition", LOG_DEBUG);
1049 $resql = $this->db->query($sql);
1051 $this->error = $this->db->lasterror();
1065 $triggerKey =
'SHIPPING_';
1066 if ($this->origin ==
'commande') {
1067 $triggerKey.=
'ORDER_SHIPMENTONPROCESS';
1069 $triggerKey.= strtoupper($this->origin).
'_SHIPMENTONPROCESS';
1079 if (!$error && !$notrigger) {
1081 $result = $this->call_trigger(
'SHIPPING_VALIDATE', $user);
1089 $this->oldref = $this->ref;
1092 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
1094 $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).
"'";
1095 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'expedition/sending/".$this->db->escape($this->
ref).
"' and entity = ".((int) $conf->entity);
1096 $resql = $this->db->query($sql);
1099 $this->error = $this->db->lasterror();
1101 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'expedition/sending/".$this->db->escape($this->newref).
"'";
1102 $sql .=
" WHERE filepath = 'expedition/sending/".$this->db->escape($this->
ref).
"' and entity = ".((int) $conf->entity);
1103 $resql = $this->db->query($sql);
1106 $this->error = $this->db->lasterror();
1112 $dirsource = $conf->expedition->dir_output.
'/sending/'.$oldref;
1113 $dirdest = $conf->expedition->dir_output.
'/sending/'.$newref;
1114 if (!$error && file_exists($dirsource)) {
1115 dol_syslog(get_class($this).
"::valid rename dir ".$dirsource.
" into ".$dirdest);
1117 if (@rename($dirsource, $dirdest)) {
1120 $listoffiles =
dol_dir_list($conf->expedition->dir_output.
'/sending/'.$newref,
'files', 1,
'^'.preg_quote($oldref,
'/'));
1121 foreach ($listoffiles as $fileentry) {
1122 $dirsource = $fileentry[
'name'];
1123 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
1124 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
1125 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
1126 @rename($dirsource, $dirdest);
1135 $this->
ref = $numref;
1141 $this->db->commit();
1144 $this->db->rollback();
1161 if ($this->
status == self::STATUS_VALIDATED || $this->
status == self::STATUS_CLOSED) {
1163 include_once DOL_DOCUMENT_ROOT.
'/delivery/class/delivery.class.php';
1164 $delivery =
new Delivery($this->db);
1165 $result = $delivery->create_from_sending($user, $this->
id);
1190 public function addline($entrepot_id, $id, $qty, $array_options = [], $fk_product = 0, $fk_parent = 0)
1194 $num = count($this->lines);
1197 $line->entrepot_id = $entrepot_id;
1198 $line->origin_line_id = $id;
1199 $line->fk_elementdet = $id;
1200 $line->element_type =
'order';
1201 $line->fk_parent = $fk_parent;
1202 $line->fk_product = $fk_product;
1206 $orderline->fetch($id);
1209 $line->rang = $orderline->rang;
1210 $line->product_type = $orderline->product_type;
1211 if (!($line->fk_product > 0)) {
1212 $line->fk_product = $orderline->fk_product;
1215 if (
isModEnabled(
'stock') && !empty($orderline->fk_product)) {
1216 $product =
new Product($this->db);
1217 $product->fetch($orderline->fk_product);
1220 $langs->load(
"errors");
1221 $this->error = $langs->trans(
"ErrorWarehouseRequiredIntoShipmentLine");
1226 $productChildrenNb = 0;
1228 $productChildrenNb = $product->hasFatherOrChild(1);
1230 if ($productChildrenNb > 0) {
1231 $product_stock =
null;
1232 $product->loadStockForVirtualProduct(
'warehouseopen', $line->qty);
1233 if ($entrepot_id > 0) {
1234 if (isset($product->stock_warehouse[$entrepot_id])) {
1235 $product_stock = $product->stock_warehouse[$entrepot_id]->real;
1238 foreach ($product->stock_warehouse as $componentStockWarehouse) {
1239 if ($product_stock ===
null) {
1240 $product_stock = $componentStockWarehouse->real;
1242 $product_stock = min($product_stock, $componentStockWarehouse->real);
1246 if ($product_stock ===
null) {
1251 if ($entrepot_id > 0) {
1252 $product->load_stock(
'warehouseopen');
1253 $product_stock = $product->stock_warehouse[$entrepot_id]->real;
1255 $product_stock = $product->stock_reel;
1259 $product_type = $product->type;
1261 $isavirtualproduct = ($productChildrenNb > 0);
1266 || ($isavirtualproduct && !
getDolGlobalInt(
'STOCK_EXCLUDE_VIRTUAL_PRODUCTS'))
1269 if ($product->stockable_product == Product::ENABLED_STOCK && $product_stock < $qty) {
1270 $langs->load(
"errors");
1271 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnShipment', $product->ref);
1272 $this->errorhidden =
'ErrorStockIsNotEnoughToAddProductOnShipment';
1283 if (
isModEnabled(
'productbatch') && !empty($line->fk_product) && !empty($orderline->product_tobatch)) {
1284 $this->error =
'ADDLINE_WAS_CALLED_INSTEAD_OF_ADDLINEBATCH '.$orderline->id.
' '.$line->fk_product;
1289 if (!
getDolGlobalString(
'MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) {
1290 $line->array_options = $array_options;
1293 $this->lines[$num] = $line;
1311 public function addlinefree($qty, $element_type, $fk_product, $fk_unit, $rang, $description, $fk_parent, $array_options = [])
1313 global
$mysoc, $langs, $user;
1315 if ($this->
status == self::STATUS_DRAFT) {
1326 if ($ranktouse == -1) {
1327 $rangmax = $this->
line_max($fk_parent);
1328 $ranktouse = $rangmax + 1;
1333 $this->line->fk_expedition = $this->id;
1334 $this->line->element_type = $element_type;
1335 $this->line->fk_product = $fk_product;
1336 $this->line->description = $description;
1337 $this->line->desc = $description;
1338 $this->line->fk_parent = $fk_parent;
1339 $this->line->qty = (float) $qty;
1340 $this->line->fk_unit = $fk_unit;
1341 $this->line->rang = $ranktouse;
1343 if (is_array($array_options) && count($array_options) > 0) {
1344 $this->line->array_options = $array_options;
1347 $result = $this->line->insert($user);
1349 if (!isset($this->context[
'createfromclone'])) {
1350 if (!empty($fk_parent)) {
1352 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
1353 $linecount = count($this->lines);
1354 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
1358 $this->lines[] = $this->line;
1361 $this->db->commit();
1362 return $this->line->id;
1364 $this->error = $this->line->error;
1365 dol_syslog(get_class($this).
"::addlinefree error=".$this->error, LOG_ERR);
1366 $this->db->rollback();
1370 dol_syslog(get_class($this).
"::addlinefree status of shipment must be Draft to allow use of ->addlinefree()", LOG_ERR);
1390 public function updatelinefree($rowid, $qty, $element_type, $fk_product, $fk_unit, $rang, $description, $fk_parent, $notrigger, $array_options = array())
1392 global
$mysoc, $langs, $user;
1394 if ($this->
status == self::STATUS_DRAFT) {
1404 $qty = (float) $qty;
1405 $description = trim($description);
1410 $line->fetch($rowid);
1411 $line->fetch_optionals();
1413 if (!empty($line->fk_product)) {
1414 $product =
new Product($this->db);
1415 $result = $product->fetch($line->fk_product);
1416 $product_type = $product->type;
1419 $staticline = clone $line;
1421 $line->oldline = $staticline;
1422 $this->line = $line;
1423 $this->line->context = $this->context;
1424 $this->line->rang = $rang;
1425 $this->line->fk_expedition = $this->id;
1426 $this->line->element_type = $element_type;
1427 $this->line->fk_product = $fk_product;
1428 $this->line->qty = $qty;
1429 $this->line->fk_unit = $fk_unit;
1430 $this->line->fk_parent = $fk_parent;
1431 $this->line->description = $description;
1433 if (is_array($array_options) && count($array_options) > 0) {
1435 foreach ($array_options as $key => $value) {
1436 $this->line->array_options[$key] = $array_options[$key];
1440 $result = $this->line->update($user, $notrigger);
1443 if (!empty($fk_parent)) {
1447 $this->db->commit();
1450 $this->error = $this->line->error;
1452 $this->db->rollback();
1456 $this->error = get_class($this).
"::updatelinefree Shipment status makes operation forbidden";
1457 $this->errors = array(
'ShipmentStatusMakeOperationForbidden');
1471 public function addline_batch($dbatch, $array_options = [], $origin_line =
null)
1476 $num = count($this->lines);
1478 if ($dbatch[
'qty'] > 0 || ($dbatch[
'qty'] == 0 &&
getDolGlobalString(
'SHIPMENT_GETS_ALL_ORDER_PRODUCTS'))) {
1481 foreach ($dbatch[
'detail'] as $key => $value) {
1482 if ($value[
'q'] > 0 || ($value[
'q'] == 0 &&
getDolGlobalString(
'SHIPMENT_GETS_ALL_ORDER_PRODUCTS'))) {
1488 $ret = $linebatch->fetchFromStock($value[
'id_batch']);
1493 $linebatch->qty = $value[
'q'];
1494 if ($linebatch->qty == 0 &&
getDolGlobalString(
'SHIPMENT_GETS_ALL_ORDER_PRODUCTS')) {
1495 $linebatch->batch =
null;
1497 $tab[] = $linebatch;
1500 require_once DOL_DOCUMENT_ROOT.
'/product/class/productbatch.class.php';
1502 $prod_batch->fetch($value[
'id_batch']);
1504 if ($prod_batch->qty < $linebatch->qty) {
1505 $langs->load(
"errors");
1506 $this->errors[] = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnShipment', $prod_batch->fk_product);
1507 dol_syslog(get_class($this).
"::addline_batch error=Product ".$prod_batch->batch.
": ".$this->errorsToString(), LOG_ERR);
1513 if (is_object($linebatch)) {
1514 $line->entrepot_id = $linebatch->fk_warehouse;
1516 $line->origin_line_id = $dbatch[
'ix_l'];
1517 $line->fk_elementdet = $dbatch[
'ix_l'];
1518 $line->qty = $dbatch[
'qty'];
1519 $line->detail_batch = $tab;
1520 if (!($line->rang > 0)) {
1521 $line->rang = $origin_line->rang;
1523 if (!($line->fk_product > 0)) {
1524 $line->fk_product = $origin_line->fk_product;
1528 if (!
getDolGlobalString(
'MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) {
1529 $line->array_options = $array_options;
1533 $this->lines[$num] = $line;
1546 public function update($user =
null, $notrigger = 0)
1553 if (isset($this->
ref)) {
1554 $this->
ref = trim($this->
ref);
1556 if (isset($this->entity)) {
1557 $this->entity = (int) $this->entity;
1559 if (isset($this->ref_customer)) {
1560 $this->ref_customer = trim($this->ref_customer);
1562 if (isset($this->socid)) {
1563 $this->socid = (int) $this->socid;
1565 if (isset($this->fk_user_author)) {
1566 $this->fk_user_author = (int) $this->fk_user_author;
1568 if (isset($this->fk_user_valid)) {
1569 $this->fk_user_valid = (int) $this->fk_user_valid;
1571 if (isset($this->fk_delivery_address)) {
1572 $this->fk_delivery_address = (int) $this->fk_delivery_address;
1574 if (isset($this->shipping_method_id)) {
1575 $this->shipping_method_id = (int) $this->shipping_method_id;
1577 if (isset($this->tracking_number)) {
1578 $this->tracking_number = trim($this->tracking_number);
1580 if (isset($this->statut)) {
1581 $this->statut = (int) $this->statut;
1583 if (isset($this->
status)) {
1586 if (isset($this->trueDepth)) {
1587 $this->trueDepth = trim($this->trueDepth);
1589 if (isset($this->trueWidth)) {
1590 $this->trueWidth = trim($this->trueWidth);
1592 if (isset($this->trueHeight)) {
1593 $this->trueHeight = trim($this->trueHeight);
1595 if (isset($this->size_units)) {
1596 $this->size_units = trim($this->size_units);
1598 if (isset($this->weight_units)) {
1599 $this->weight_units = (int) $this->weight_units;
1601 if (isset($this->trueWeight)) {
1602 $this->weight = trim((
string) $this->trueWeight);
1604 if (isset($this->note_private)) {
1605 $this->note_private = trim($this->note_private);
1607 if (isset($this->note_public)) {
1608 $this->note_public = trim($this->note_public);
1610 if (isset($this->model_pdf)) {
1611 $this->model_pdf = trim($this->model_pdf);
1613 if (!empty($this->date_expedition)) {
1614 $this->date_shipping = $this->date_expedition;
1621 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition SET";
1622 $sql .=
" ref = ".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
1623 $sql .=
" ref_ext = ".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
1624 $sql .=
" ref_customer = ".(isset($this->ref_customer) ?
"'".$this->db->escape($this->ref_customer).
"'" :
"null").
",";
1625 $sql .=
" fk_soc = ".(isset($this->socid) ? ((int) $this->socid) :
"null").
",";
1626 $sql .=
" date_creation = ".(dol_strlen($this->date_creation) != 0 ?
"'".$this->db->idate($this->date_creation).
"'" :
'null').
",";
1627 $sql .=
" fk_user_author = ".(isset($this->fk_user_author) ? ((int) $this->fk_user_author) :
"null").
",";
1628 $sql .=
" date_valid = ".(dol_strlen($this->date_valid) != 0 ?
"'".$this->db->idate($this->date_valid).
"'" :
'null').
",";
1629 $sql .=
" fk_user_valid = ".(isset($this->fk_user_valid) ? ((int) $this->fk_user_valid) :
"null").
",";
1630 $sql .=
" date_expedition = ".(dol_strlen($this->date_shipping) != 0 ?
"'".$this->db->idate($this->date_shipping).
"'" :
'null').
",";
1631 $sql .=
" date_delivery = ".(dol_strlen($this->date_delivery) != 0 ?
"'".$this->db->idate($this->date_delivery).
"'" :
'null').
",";
1632 $sql .=
" fk_address = ".(isset($this->fk_delivery_address) ? ((int) $this->fk_delivery_address) :
"null").
",";
1633 $sql .=
" fk_shipping_method = ".((isset($this->shipping_method_id) && $this->shipping_method_id > 0) ? ((
int) $this->shipping_method_id) :
"null").
",";
1634 $sql .=
" tracking_number = ".(isset($this->tracking_number) ?
"'".$this->db->escape($this->tracking_number).
"'" :
"null").
",";
1635 $sql .=
" fk_statut = ".(isset($this->
status) ? ((int) $this->
status) :
"null").
",";
1636 $sql .=
" fk_projet = ".(isset($this->fk_project) ? ((int) $this->fk_project) :
"null").
",";
1637 $sql .=
" height = ".(($this->trueHeight !=
'') ? ((
float) $this->trueHeight) :
"null").
",";
1638 $sql .=
" width = ".(($this->trueWidth !=
'') ? ((
float) $this->trueWidth) :
"null").
",";
1639 $sql .=
" size_units = ".(isset($this->size_units) ? ((int) $this->size_units) :
"null").
",";
1640 $sql .=
" size = ".(($this->trueDepth !=
'') ? ((
float) $this->trueDepth) :
"null").
",";
1641 $sql .=
" weight_units = ".(isset($this->weight_units) ? ((int) $this->weight_units) :
"null").
",";
1642 $sql .=
" weight = ".(($this->trueWeight !=
'') ? ((
float) $this->trueWeight) :
"null").
",";
1643 $sql .=
" note_private = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
1644 $sql .=
" note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
1645 $sql .=
" model_pdf = ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
1646 $sql .=
" entity = ".((int) $conf->entity);
1647 $sql .=
" WHERE rowid = ".((int) $this->
id);
1651 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1652 $resql = $this->db->query($sql);
1655 $this->errors[] =
"Error ".$this->db->lasterror();
1666 if (!$error && !$notrigger) {
1668 $result = $this->call_trigger(
'SHIPPING_MODIFY', $user);
1677 foreach ($this->errors as $errmsg) {
1678 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
1679 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1681 $this->db->rollback();
1684 $this->db->commit();
1698 public function cancel($user, $notrigger = 0, $also_update_stock =
false)
1700 global $conf, $langs, $user;
1702 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1711 if (isset($this->linkedObjectsIds[
'delivery']) && count($this->linkedObjectsIds[
'delivery']) > 0) {
1712 $this->error =
'ErrorThereIsSomeDeliveries';
1716 if (!$error && !$notrigger) {
1718 $result = $this->call_trigger(
'SHIPPING_CANCEL', $user);
1728 (
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT_CLOSE') && $this->
status == self::STATUS_CLOSED && $also_update_stock));
1730 require_once DOL_DOCUMENT_ROOT.
"/product/stock/class/mouvementstock.class.php";
1732 $langs->load(
"agenda");
1736 $sql .=
" ed.fk_product";
1737 $sql .=
", ed.qty, ed.fk_entrepot, ed.rowid as expeditiondet_id";
1738 $sql .=
", SUM(".$this->db->ifsql(
"pa.rowid IS NOT NULL",
"1",
"0").
") as iskit";
1739 $sql .=
", ".$this->db->ifsql(
"pai.incdec IS NULL",
"1",
"pai.incdec").
" as incdec";
1740 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet as ed";
1741 $sql .=
" LEFT JOIN ".$this->db->prefix().
"product_association as pa ON pa.fk_product_pere = ed.fk_product";
1742 $sql .=
" LEFT JOIN ".$this->db->prefix().
"expeditiondet as edp ON edp.rowid = ed.fk_parent";
1743 $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";
1744 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
1745 $sql .=
" GROUP BY ed.fk_product, ed.qty, ed.fk_entrepot, ed.rowid, pai.incdec";
1746 $sql .= $this->db->order(
"ed.rowid",
"DESC");
1748 dol_syslog(get_class($this).
"::delete select details", LOG_DEBUG);
1749 $resql = $this->db->query($sql);
1751 $cpt = $this->db->num_rows($resql);
1755 for ($i = 0; $i < $cpt; $i++) {
1756 dol_syslog(get_class($this).
"::delete movement index ".$i);
1757 $obj = $this->db->fetch_object($resql);
1758 $line_id = (int) $obj->expeditiondet_id;
1760 if ($can_update_stock && (empty($obj->iskit) ||
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) && !empty($obj->incdec)) {
1763 $mouvS->origin =
'';
1767 $lotArray = $shipmentlinebatch->fetchAll($obj->expeditiondet_id);
1768 if (!is_array($lotArray)) {
1770 $this->errors[] =
"Error ".$this->db->lasterror();
1774 if (empty($lotArray)) {
1778 $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));
1781 $this->errors = array_merge($this->errors, $mouvS->errors);
1787 foreach ($lotArray as $lot) {
1788 $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));
1791 $this->errors = array_merge($this->errors, $mouvS->errors);
1804 $res = $shipment_line->fetch($line_id);
1806 $result = $shipment_line->delete($user);
1809 $this->errors[] =
"Error ".$shipment_line->errorsToString();
1813 $this->errors[] =
"Error ".$shipment_line->errorsToString();
1823 $this->errors[] =
"Error ".$this->db->lasterror();
1836 $sql =
"SELECT rowid FROM ".$this->db->prefix().
"expedition";
1837 $sql .=
" WHERE rowid = ".((int) $this->
id);
1839 if ($this->db->query($sql)) {
1840 if (!empty($this->origin) && $this->origin_id > 0) {
1843 '@phan-var-force Facture|Commande $origin_object';
1854 $this->db->commit();
1858 if (!empty($conf->expedition->dir_output)) {
1859 $dir = $conf->expedition->dir_output.
'/sending/'.$ref;
1860 $file = $dir.
'/'.$ref.
'.pdf';
1861 if (file_exists($file)) {
1866 if (file_exists($dir)) {
1868 $this->error = $langs->trans(
"ErrorCanNotDeleteDir", $dir);
1876 $this->error = $this->db->lasterror().
" - sql=$sql";
1877 $this->db->rollback();
1881 $this->db->rollback();
1885 $this->db->rollback();
1899 public function delete($user =
null, $notrigger = 0, $also_update_stock =
false)
1901 global $conf, $langs;
1907 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1916 if (isset($this->linkedObjectsIds[
'delivery']) && count($this->linkedObjectsIds[
'delivery']) > 0) {
1917 $this->error =
'ErrorThereIsSomeDeliveries';
1921 if (!$error && !$notrigger) {
1923 $result = $this->call_trigger(
'SHIPPING_DELETE', $user);
1933 (
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT_CLOSE') && $this->
status == self::STATUS_CLOSED && $also_update_stock));
1935 require_once DOL_DOCUMENT_ROOT.
"/product/stock/class/mouvementstock.class.php";
1937 $langs->load(
"agenda");
1944 $sql .=
" ed.fk_product";
1945 $sql .=
", ed.qty, ed.fk_entrepot, ed.rowid as expeditiondet_id";
1946 $sql .=
", SUM(".$this->db->ifsql(
"pa.rowid IS NOT NULL",
"1",
"0").
") as iskit";
1947 $sql .=
", ".$this->db->ifsql(
"pai.incdec IS NULL",
"1",
"pai.incdec").
" as incdec";
1948 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet as ed";
1949 $sql .=
" LEFT JOIN ".$this->db->prefix().
"product_association as pa ON pa.fk_product_pere = ed.fk_product";
1950 $sql .=
" LEFT JOIN ".$this->db->prefix().
"expeditiondet as edp ON edp.rowid = ed.fk_parent";
1951 $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";
1952 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
1953 $sql .=
" GROUP BY ed.fk_product, ed.qty, ed.fk_entrepot, ed.rowid, pai.incdec";
1954 $sql .= $this->db->order(
"ed.rowid",
"DESC");
1956 dol_syslog(get_class($this).
"::delete select details", LOG_DEBUG);
1957 $resql = $this->db->query($sql);
1959 $cpt = $this->db->num_rows($resql);
1960 for ($i = 0; $i < $cpt; $i++) {
1961 dol_syslog(get_class($this).
"::delete movement index ".$i);
1962 $obj = $this->db->fetch_object($resql);
1963 $line_id = (int) $obj->expeditiondet_id;
1965 if ($can_update_stock && (empty($obj->iskit) ||
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) && !empty($obj->incdec)) {
1968 $mouvS->origin =
'';
1970 $lotArray = $shipmentlinebatch->fetchAll($line_id);
1971 if (!is_array($lotArray)) {
1973 $this->errors[] =
"Error ".$this->db->lasterror();
1975 if (empty($lotArray)) {
1979 $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));
1982 $this->errors = array_merge($this->errors, $mouvS->errors);
1988 foreach ($lotArray as $lot) {
1989 if (empty($lot->qty)) {
1992 $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));
1995 $this->errors = array_merge($this->errors, $mouvS->errors);
2008 $res = $shipment_line->fetch($line_id);
2010 $result = $shipment_line->delete($user);
2013 $this->errors[] =
"Error ".$shipment_line->errorsToString();
2017 $this->errors[] =
"Error ".$shipment_line->errorsToString();
2027 $this->errors[] =
"Error ".$this->db->lasterror();
2052 $sql =
"DELETE FROM ".$this->db->prefix().
"expedition";
2053 $sql .=
" WHERE rowid = ".((int) $this->
id);
2055 if ($this->db->query($sql)) {
2056 if (!empty($this->origin) && $this->origin_id > 0) {
2059 '@phan-var-force Facture|Commande $origin_object';
2069 $this->db->commit();
2077 if (!empty($conf->expedition->dir_output) && !empty($ref)) {
2078 $dir = $conf->expedition->dir_output .
'/sending/' . $ref;
2079 $file = $dir .
'/' . $ref .
'.pdf';
2080 if (file_exists($file)) {
2085 if (file_exists($dir)) {
2087 $this->error = $langs->trans(
"ErrorCanNotDeleteDir", $dir);
2095 $this->error = $this->db->lasterror().
" - sql=$sql";
2096 $this->db->rollback();
2100 $this->db->rollback();
2104 $this->db->rollback();
2120 $this->lines = array();
2125 $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";
2126 $sql .=
", cd.total_ht, cd.total_localtax1, cd.total_localtax2, cd.total_ttc, cd.total_tva";
2127 $sql .=
", cd.fk_remise_except, cd.fk_product_fournisseur_price as fk_fournprice";
2128 $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";
2129 $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";
2130 $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";
2131 $sql .=
", p.ref as product_ref, p.label as product_label, p.fk_product_type, p.barcode as product_barcode";
2132 $sql .=
", p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units";
2133 $sql .=
", p.surface, p.surface_units, p.volume, p.volume_units, p.tosell as product_tosell, p.tobuy as product_tobuy";
2134 $sql .=
", p.tobatch as product_tobatch, p.stockable_product";
2135 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expeditiondet as ed, ".MAIN_DB_PREFIX.
"commandedet as cd";
2136 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"product as p ON p.rowid = cd.fk_product";
2137 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
2138 $sql .=
" AND ed.fk_elementdet = cd.rowid";
2139 $sql .=
" ORDER BY cd.rang, ed.fk_elementdet";
2141 dol_syslog(get_class($this).
"::fetch_lines", LOG_DEBUG);
2142 $resql = $this->db->query($sql);
2144 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
2146 $num = $this->db->num_rows($resql);
2152 $this->total_ht = 0;
2153 $this->total_tva = 0;
2154 $this->total_ttc = 0;
2155 $this->total_localtax1 = 0;
2156 $this->total_localtax2 = 0;
2158 $this->multicurrency_total_ht = 0;
2159 $this->multicurrency_total_tva = 0;
2160 $this->multicurrency_total_ttc = 0;
2166 $obj = $this->db->fetch_object($resql);
2168 if ($originline > 0 && $originline == $obj->fk_elementdet) {
2170 $line->entrepot_id = 0;
2171 $line->qty_shipped += $obj->qty_shipped;
2174 $line->entrepot_id = $obj->fk_entrepot;
2175 $line->qty_shipped = $obj->qty_shipped;
2179 $detail_entrepot->entrepot_id = $obj->fk_entrepot;
2180 $detail_entrepot->qty_shipped = $obj->qty_shipped;
2181 $detail_entrepot->line_id = $obj->line_id;
2182 $line->details_entrepot[] = $detail_entrepot;
2184 $line->line_id = $obj->line_id;
2185 $line->rowid = $obj->line_id;
2186 $line->id = $obj->line_id;
2188 $line->fk_origin =
'orderline';
2190 $line->fk_element = $obj->fk_element;
2191 $line->origin_id = $obj->fk_element;
2192 $line->fk_elementdet = $obj->fk_elementdet;
2193 $line->origin_line_id = $obj->fk_elementdet;
2194 $line->element_type = $obj->element_type;
2196 $line->fk_expedition = $this->id;
2198 $line->stockable_product = $obj->stockable_product;
2199 $line->product_type = $obj->product_type;
2200 $line->fk_product = $obj->fk_product;
2201 $line->fk_product_type = $obj->fk_product_type;
2202 $line->ref = $obj->product_ref;
2203 $line->product_ref = $obj->product_ref;
2204 $line->product_label = $obj->product_label;
2205 $line->libelle = $obj->product_label;
2206 $line->product_barcode = $obj->product_barcode;
2207 $line->product_tosell = $obj->product_tosell;
2208 $line->product_tobuy = $obj->product_tobuy;
2209 $line->product_tobatch = $obj->product_tobatch;
2210 $line->fk_fournprice = $obj->fk_fournprice;
2211 $line->label = $obj->custom_label;
2212 $line->description = $obj->description;
2213 $line->qty_asked = $obj->qty_asked;
2214 $line->rang = $obj->rang;
2215 $line->weight = $obj->weight;
2216 $line->weight_units = $obj->weight_units;
2217 $line->length = $obj->length;
2218 $line->length_units = $obj->length_units;
2219 $line->width = $obj->width;
2220 $line->width_units = $obj->width_units;
2221 $line->height = $obj->height;
2222 $line->height_units = $obj->height_units;
2223 $line->surface = $obj->surface;
2224 $line->surface_units = $obj->surface_units;
2225 $line->volume = $obj->volume;
2226 $line->volume_units = $obj->volume_units;
2227 $line->stockable_product = $obj->stockable_product;
2228 $line->fk_unit = $obj->fk_unit;
2230 $line->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
2232 $line->pa_ht = $obj->pa_ht;
2235 $localtax_array = array(0 => $obj->localtax1_type, 1 => $obj->localtax1_tx, 2 => $obj->localtax2_type, 3 => $obj->localtax2_tx);
2236 $localtax1_tx =
get_localtax($obj->tva_tx, 1, $this->thirdparty);
2237 $localtax2_tx =
get_localtax($obj->tva_tx, 2, $this->thirdparty);
2240 $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);
2241 $line->desc = $obj->description;
2242 $line->qty = $line->qty_shipped;
2243 $line->total_ht = (float) $tabprice[0];
2244 $line->total_localtax1 = (float) $tabprice[9];
2245 $line->total_localtax2 = (float) $tabprice[10];
2246 $line->total_ttc = (float) $tabprice[2];
2247 $line->total_tva = (float) $tabprice[1];
2248 $line->vat_src_code = $obj->vat_src_code;
2249 $line->tva_tx = $obj->tva_tx;
2250 $line->localtax1_tx = $obj->localtax1_tx;
2251 $line->localtax2_tx = $obj->localtax2_tx;
2252 $line->info_bits = $obj->info_bits;
2253 $line->price = $obj->price;
2254 $line->subprice = $obj->subprice;
2255 $line->fk_remise_except = $obj->fk_remise_except;
2256 $line->remise_percent = $obj->remise_percent;
2258 $this->total_ht += $tabprice[0];
2259 $this->total_tva += $tabprice[1];
2260 $this->total_ttc += $tabprice[2];
2261 $this->total_localtax1 += $tabprice[9];
2262 $this->total_localtax2 += $tabprice[10];
2264 $line->date_start = $this->db->jdate($obj->date_start);
2265 $line->date_end = $this->db->jdate($obj->date_end);
2267 $line->special_code = $obj->special_code;
2270 $this->fk_multicurrency = $obj->fk_multicurrency;
2271 $this->multicurrency_code = $obj->multicurrency_code;
2272 $line->multicurrency_subprice = $obj->multicurrency_subprice;
2273 $line->multicurrency_total_ht = $obj->multicurrency_total_ht;
2274 $line->multicurrency_total_tva = $obj->multicurrency_total_tva;
2275 $line->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
2277 $this->multicurrency_total_ht += $obj->multicurrency_total_ht;
2278 $this->multicurrency_total_tva += $obj->multicurrency_total_tva;
2279 $this->multicurrency_total_ttc += $obj->multicurrency_total_ttc;
2281 if ($originline != $obj->fk_elementdet) {
2282 $line->detail_batch = array();
2286 if (
isModEnabled(
'productbatch') && $obj->line_id > 0 && $obj->product_tobatch > 0) {
2287 $newdetailbatch = $shipmentlinebatch->fetchAll($obj->line_id, $obj->fk_product);
2289 if (is_array($newdetailbatch)) {
2290 if ($originline != $obj->fk_elementdet) {
2291 $line->detail_batch = $newdetailbatch;
2293 $line->detail_batch = array_merge($line->detail_batch, $newdetailbatch);
2300 $detail_children = array();
2301 $line_child_list = array();
2302 $res = $line->findAllChild($line->id, $line_child_list, 1);
2304 foreach ($line_child_list as $child_line) {
2305 foreach ($child_line as $child_obj) {
2306 $child_product_id = (int) $child_obj->fk_product;
2307 $child_warehouse_id = (int) $child_obj->fk_warehouse;
2309 if ($child_warehouse_id > 0) {
2311 if (!isset($detail_children[$child_product_id])) {
2312 $detail_children[$child_product_id] = array();
2314 if (!isset($detail_children[$child_product_id][$child_warehouse_id])) {
2315 $detail_children[$child_product_id][$child_warehouse_id] = 0;
2317 $detail_children[$child_product_id][$child_warehouse_id] += $child_obj->qty;
2322 $line->detail_children = $detail_children;
2325 $line->fetch_optionals();
2327 if ($originline != $obj->fk_elementdet) {
2328 $this->lines[$lineindex] = $line;
2331 $line->total_ht += $tabprice[0];
2332 $line->total_localtax1 += $tabprice[9];
2333 $line->total_localtax2 += $tabprice[10];
2334 $line->total_ttc += $tabprice[2];
2335 $line->total_tva += $tabprice[1];
2339 $originline = $obj->fk_elementdet;
2341 $this->db->free($resql);
2344 $this->error = $this->db->error();
2361 $this->lines = array();
2363 $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';
2364 $sql .=
' FROM '.MAIN_DB_PREFIX.$this->table_element_line.
' as ed';
2365 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON (p.rowid = ed.fk_product)';
2366 $sql .=
' WHERE ed.fk_expedition = '.((int) $this->
id);
2367 $sql .=
' ORDER BY ed.rang, ed.rowid';
2369 dol_syslog(get_class($this).
"::fetch_lines_free", LOG_DEBUG);
2370 $result = $this->db->query($sql);
2372 $num = $this->db->num_rows($result);
2376 $objp = $this->db->fetch_object($result);
2380 $line->rowid = $objp->rowid;
2381 $line->id = $objp->rowid;
2382 $line->fk_expedition = $this->id;
2383 $line->description = $objp->description;
2384 $line->qty = $objp->qty;
2385 $line->fk_entrepot = $objp->fk_entrepot;
2386 $line->fk_product = $objp->fk_product;
2387 $line->rang = $objp->rang;
2388 $line->fk_element = $objp->fk_element;
2389 $line->fk_unit = $objp->fk_unit;
2390 $line->fk_elementdet = $objp->fk_elementdet;
2391 $line->fk_element_type = $objp->element_type;
2392 $line->fetch_optionals();
2394 $this->lines[$i] = $line;
2399 $this->db->free($result);
2403 $this->error = $this->db->error();
2429 if ($this->
status == self::STATUS_DRAFT) {
2435 $line->fetch($lineid);
2437 if ($this->
id > 0 && (
int) $line->fk_expedition !== (
int) $this->id) {
2438 $this->db->rollback();
2439 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
2443 if ($line->delete($user) > 0) {
2446 $this->db->commit();
2449 $this->db->rollback();
2453 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
2467 global $conf, $langs;
2469 $langs->load(
'sendings');
2471 $nofetch = !empty($params[
'nofetch']);
2474 $datas[
'picto'] =
img_picto(
'', $this->picto).
' <u class="paddingrightonly">'.$langs->trans(
"Shipment").
'</u>';
2475 if (isset($this->
status)) {
2476 $datas[
'picto'] .=
' '.$this->getLibStatut(5);
2478 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
2479 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.($this->ref_customer ? $this->ref_customer : $this->ref_client);
2481 $langs->load(
'companies');
2482 if (empty($this->thirdparty)) {
2485 $datas[
'customer'] =
'<br><b>'.$langs->trans(
'Customer').
':</b> '.$this->thirdparty->getNomUrl(1,
'', 0, 1);
2502 public function getNomUrl($withpicto = 0, $option =
'', $max = 0, $short = 0, $notooltip = 0, $save_lastsearch_value = -1)
2504 global $langs, $hookmanager;
2509 'objecttype' => $this->element,
2510 'option' => $option,
2513 $classfortooltip =
'classfortooltip';
2516 $classfortooltip =
'classforajaxtooltip';
2517 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
2523 $url = DOL_URL_ROOT.
'/expedition/card.php?id='.$this->id;
2529 if ($option !==
'nolink') {
2531 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2532 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
2533 $add_save_lastsearch_values = 1;
2535 if ($add_save_lastsearch_values) {
2536 $url .=
'&save_lastsearch_values=1';
2541 if (empty($notooltip)) {
2543 $label = $langs->trans(
"Shipment");
2544 $linkclose .=
' alt="'.dolPrintHTMLForAttribute($label).
'"';
2546 $linkclose .= ($label ?
' title="'.dolPrintHTMLForAttribute($label).
'"' :
' title="tocomplete"');
2547 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
2550 $linkstart =
'<a href="'.$url.
'"';
2551 $linkstart .= $linkclose.
'>';
2554 $result .= $linkstart;
2556 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), ($notooltip ? (($withpicto != 2) ?
'class="paddingright"' :
'') :
'class="'.(($withpicto != 2) ?
'paddingright ' :
'').
'"'), 0, 0, $notooltip ? 0 : 1);
2558 if ($withpicto != 2) {
2559 $result .= $this->ref;
2561 $result .= $linkend;
2563 $hookmanager->initHooks(array($this->element .
'dao'));
2564 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result);
2565 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
2567 $result = $hookmanager->resPrint;
2569 $result .= $hookmanager->resPrint;
2598 $labelStatus = $langs->transnoentitiesnoconv($this->labelStatus[$status]);
2599 $labelStatusShort = $langs->transnoentitiesnoconv($this->labelStatusShort[$status]);
2601 $statusType =
'status'.$status;
2602 if ($status == self::STATUS_VALIDATED) {
2603 $statusType =
'status4';
2605 if ($status == self::STATUS_CLOSED) {
2606 $statusType =
'status6';
2608 if ($status == self::STATUS_CANCELED) {
2609 $statusType =
'status9';
2613 $status_label = $this->signed_status ? $labelStatus . $signed_label : $labelStatus;
2614 $status_label_short = $this->signed_status ? $labelStatusShort . $signed_label : $labelStatusShort;
2616 return dolGetStatus($status_label, $status_label_short,
'', $statusType, $mode);
2628 global $langs, $conf;
2630 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
2632 $return =
'<div class="box-flex-item box-flex-grow-zero">';
2633 $return .=
'<div class="info-box info-box-sm">';
2634 $return .=
'<div class="info-box-icon bg-infobox-action">';
2636 $return .=
'</div>';
2637 $return .=
'<div class="info-box-content">';
2638 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->
getNomUrl() .
'</span>';
2639 if ($selected >= 0) {
2640 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
2642 $return .=
'<br><div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).
'</div>';
2643 $return .=
'<div class="info-box-ref amount">'.price($this->total_ht, 0, $langs, 0, -1, -1,
getDolCurrency()).
' '.$langs->trans(
'HT').
'</div>';
2644 $return .=
'<div class="info-box-status">'.$this->getLibStatut(3).
'</div>';
2645 $return .=
'</div>';
2646 $return .=
'</div>';
2647 $return .=
'</div>';
2665 dol_syslog(get_class($this).
"::initAsSpecimen");
2668 $order->initAsSpecimen();
2672 $this->
ref =
'SPECIMEN';
2673 $this->specimen = 1;
2675 $this->livraison_id = 0;
2677 $this->date_creation = $now;
2678 $this->date_valid = $now;
2679 $this->date_delivery = $now + 24 * 3600;
2680 $this->date_expedition = $now + 24 * 3600;
2682 $this->entrepot_id = 0;
2683 $this->fk_delivery_address = 0;
2686 $this->commande_id = 0;
2687 $this->commande = $order;
2689 $this->origin_id = 1;
2690 $this->origin_type =
'commande';
2692 $this->note_private =
'Private note';
2693 $this->note_public =
'Public note';
2697 while ($xnbp < $nbp) {
2699 $line->product_desc = $langs->trans(
"Description").
" ".$xnbp;
2700 $line->product_label = $langs->trans(
"Description").
" ".$xnbp;
2702 $line->qty_asked = 5;
2703 $line->qty_shipped = 4;
2704 $line->fk_product = $this->commande->lines[$xnbp]->fk_product;
2706 $line->weight = 1.123456;
2707 $line->weight_units = 0;
2709 $line->volume = 2.34567;
2710 $line->volume_unit = 0;
2712 $this->lines[] = $line;
2743 if ($user->hasRight(
'expedition',
'creer')) {
2744 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
2745 $sql .=
" SET date_delivery = ".($delivery_date ?
"'".$this->db->idate($delivery_date).
"'" :
'null');
2746 $sql .=
" WHERE rowid = ".((int) $this->
id);
2748 dol_syslog(get_class($this).
"::setDeliveryDate", LOG_DEBUG);
2749 $resql = $this->db->query($sql);
2751 $this->date_delivery = $delivery_date;
2754 $this->error = $this->db->error();
2771 if ($user->hasRight(
'expedition',
'creer')) {
2772 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
2773 $sql .=
" SET date_expedition = ".($shipping_date ?
"'".$this->db->idate($shipping_date).
"'" :
'null');
2774 $sql .=
" WHERE rowid = ".((int) $this->
id);
2776 dol_syslog(get_class($this).
"::setShippingDate", LOG_DEBUG);
2777 $resql = $this->db->query($sql);
2779 $this->date_shipping = $shipping_date;
2782 $this->error = $this->db->error();
2802 $sql =
"SELECT em.rowid, em.code, em.libelle as label";
2803 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2804 $sql .=
" WHERE em.active = 1";
2805 $sql .=
" ORDER BY em.libelle ASC";
2807 $resql = $this->db->query($sql);
2809 while ($obj = $this->db->fetch_object($resql)) {
2810 $label = $langs->trans(
'SendingMethod'.$obj->code);
2811 $this->meths[(int) $obj->rowid] = ($label !=
'SendingMethod'.$obj->code ? $label : $obj->label);
2828 $this->listmeths = [];
2831 $sql =
"SELECT em.rowid, em.code, em.libelle as label, em.description, em.tracking, em.active";
2832 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2834 $sql .=
" WHERE em.rowid=".((int) $id);
2837 $resql = $this->db->query($sql);
2839 while ($obj = $this->db->fetch_object($resql)) {
2840 $label = $langs->trans(
'SendingMethod'.$obj->code);
2841 $this->listmeths[$i] = [
2842 'rowid' => (int) $obj->rowid,
2843 'code' => $obj->code,
2844 'libelle' => ($label !=
'SendingMethod'.$obj->code ? $label : $obj->label),
2845 'description' => $obj->description,
2846 'tracking' => $obj->tracking,
2847 'active' => (
int) $obj->active,
2863 if (!empty($this->shipping_method_id)) {
2864 $sql =
"SELECT em.code, em.tracking";
2865 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2866 $sql .=
" WHERE em.rowid = ".((int) $this->shipping_method_id);
2868 $resql = $this->db->query($sql);
2870 if ($obj = $this->db->fetch_object($resql)) {
2871 $tracking = (string) $obj->tracking;
2876 if (!empty($tracking) && !empty($value)) {
2877 $url = str_replace(
'{TRACKID}', $value, $tracking);
2878 $this->tracking_url = sprintf(
'<a target="_blank" rel="noopener noreferrer" href="%s">%s</a>', $url, $value);
2880 $this->tracking_url = $value;
2896 if ($this->
status == self::STATUS_CLOSED) {
2903 if (empty($this->date_shipping)) {
2904 $sql .=
", date_expedition = '".$this->db->escape($this->db->idate(
dol_now())).
"'";
2906 $sql .=
" WHERE rowid = ".((int) $this->
id).
" AND fk_statut > 0";
2908 $resql = $this->db->query($sql);
2911 if ($this->origin_type ==
'commande' && $this->origin_id > 0) {
2913 $order->fetch($this->origin_id);
2915 $order->loadExpeditions(self::STATUS_CLOSED);
2917 $shipments_match_order = 1;
2918 foreach ($order->lines as $line) {
2919 $lineid = $line->id;
2921 if (($line->product_type == 0 ||
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES')) && $order->expeditions[$lineid] != $qty) {
2922 $shipments_match_order = 0;
2923 $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';
2928 if ($shipments_match_order) {
2929 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');
2931 $order->cloture($user, 0, 0);
2949 $result = $this->call_trigger(
'SHIPPING_CLOSED', $user);
2960 $this->db->commit();
2966 $this->db->rollback();
2985 require_once DOL_DOCUMENT_ROOT .
'/product/stock/class/mouvementstock.class.php';
2987 $langs->load(
"agenda");
2991 $sql .=
" ed.rowid as edid, ed.fk_product, ed.qty, ed.fk_entrepot";
2992 $sql .=
", cd.rowid as cdid";
2993 $sql .=
", cd.subprice";
2994 $sql .=
", edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
2996 $sql .=
" FROM " . $this->db->prefix() .
"expeditiondet as ed";
2997 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"commandedet as cd ON cd.rowid = ed.fk_elementdet";
2998 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
2999 $sql .=
" INNER JOIN " . $this->db->prefix() .
"expedition as e ON ed.fk_expedition = e.rowid";
3000 $sql .=
" WHERE ed.fk_expedition = " . ((int) $this->
id);
3003 dol_syslog(get_class($this) .
"::valid select details", LOG_DEBUG);
3004 $resql = $this->db->query($sql);
3006 $cpt = $this->db->num_rows($resql);
3007 for ($i = 0; $i < $cpt; $i++) {
3008 $obj = $this->db->fetch_object($resql);
3009 if (empty($obj->edbrowid)) {
3012 $qty = $obj->edbqty;
3014 if ($qty <= 0 || ($qty < 0 && !
getDolGlobalInt(
'SHIPMENT_ALLOW_NEGATIVE_QTY'))) {
3017 dol_syslog(get_class($this) .
"::valid movement index " . $i .
" ed.rowid=" . $obj->edid .
" edb.rowid=" . $obj->edbrowid);
3020 $mouvS->origin = &$this;
3021 $mouvS->setOrigin($this->element, $this->
id, $obj->cdid, $obj->edid);
3023 if (empty($obj->edbrowid)) {
3027 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans($labelmovement, $obj->ref));
3037 $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);
3047 $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)";
3048 $resqldelete = $this->db->query($sqldelete);
3052 $this->error = $this->db->lasterror();
3053 $this->errors[] = $this->db->lasterror();
3076 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'expedition SET billed = 1';
3077 $sql .=
" WHERE rowid = ".((int) $this->
id).
' AND fk_statut > 0';
3079 $resql = $this->db->query($sql);
3084 $result = $this->call_trigger(
'SHIPPING_BILLED', $user);
3091 $this->errors[] = $this->db->lasterror;
3094 if (empty($error)) {
3095 $this->db->commit();
3098 $this->db->rollback();
3113 if ($this->
status <= self::STATUS_DRAFT) {
3117 return $this->
setStatusCommon($user, self::STATUS_DRAFT, $notrigger,
'SHIPMENT_UNVALIDATE');
3127 global $langs, $user;
3132 if ($this->
status == self::STATUS_VALIDATED) {
3138 $oldbilled = $this->billed;
3140 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'expedition SET fk_statut = 1';
3141 $sql .=
" WHERE rowid = ".((int) $this->
id).
' AND fk_statut > 0';
3143 $resql = $this->db->query($sql);
3151 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3153 $langs->load(
"agenda");
3157 $sql =
"SELECT cd.fk_product, cd.subprice,";
3158 $sql .=
" ed.rowid, ed.qty, ed.fk_entrepot,";
3159 $sql .=
" edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
3160 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commandedet as cd,";
3161 $sql .=
" ".MAIN_DB_PREFIX.
"expeditiondet as ed";
3162 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
3163 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
3164 $sql .=
" AND cd.rowid = ed.fk_elementdet";
3166 dol_syslog(get_class($this).
"::valid select details", LOG_DEBUG);
3167 $resql = $this->db->query($sql);
3169 $cpt = $this->db->num_rows($resql);
3170 for ($i = 0; $i < $cpt; $i++) {
3171 $obj = $this->db->fetch_object($resql);
3172 if (empty($obj->edbrowid)) {
3175 $qty = $obj->edbqty;
3180 dol_syslog(get_class($this).
"::reopen expedition movement index ".$i.
" ed.rowid=".$obj->rowid.
" edb.rowid=".$obj->edbrowid);
3184 $mouvS->origin = &$this;
3185 $mouvS->setOrigin($this->element, $this->
id);
3187 if (empty($obj->edbrowid)) {
3191 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans(
"ShipmentUnClassifyCloseddInDolibarr", $this->ref));
3201 $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);
3210 $this->error = $this->db->lasterror();
3217 $result = $this->call_trigger(
'SHIPPING_REOPEN', $user);
3224 $this->errors[] = $this->db->lasterror();
3228 $this->db->commit();
3233 $this->billed = $oldbilled;
3234 $this->db->rollback();
3250 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
3252 $outputlangs->load(
"products");
3257 if (!empty($this->model_pdf)) {
3258 $modele = $this->model_pdf;
3264 $modelpath =
"core/modules/expedition/doc/";
3268 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...
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.
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.
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.
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.
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.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
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', ...)
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...
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.
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.
if(getDolGlobalString( 'TAKEPOS_SHOW_CUSTOMER')) print $langs trans('Date')." left 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 PaymentTypeShortLIQ right SELECT p pos_change as p datep as date
$conf db user
Active Directory does not allow anonymous connections.