39require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
40require_once DOL_DOCUMENT_ROOT.
"/expedition/class/expeditionligne.class.php";
41require_once DOL_DOCUMENT_ROOT.
'/core/class/commonincoterm.class.php';
42if (isModEnabled(
"propal")) {
43 require_once DOL_DOCUMENT_ROOT.
'/comm/propal/class/propal.class.php';
45if (isModEnabled(
'order')) {
46 require_once DOL_DOCUMENT_ROOT.
'/commande/class/commande.class.php';
48require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expeditionlinebatch.class.php';
49require_once DOL_DOCUMENT_ROOT.
'/core/class/commonsignedobject.class.php';
50require_once DOL_DOCUMENT_ROOT.
'/subtotals/class/commonsubtotal.class.php';
60 use CommonSignedObject;
66 public $element =
"shipping";
71 public $fk_element =
"fk_expedition";
76 public $table_element =
"expedition";
81 public $table_element_line =
"expeditiondet";
86 public $picto =
'dolly';
92 public $fields = array();
97 public $user_author_id;
102 public $fk_user_author;
119 public $ref_customer;
129 public $tracking_number;
134 public $tracking_url;
147 public $weight_units;
163 public $height_units;
180 public $livraison_id;
185 public $multicurrency_subprice;
215 public $date_delivery;
229 public $date_expedition;
235 public $date_shipping;
264 public $lines = array();
270 public $fk_multicurrency;
275 public $multicurrency_code;
279 public $multicurrency_tx;
283 public $multicurrency_total_ht;
287 public $multicurrency_total_tva;
291 public $multicurrency_total_ttc;
338 $this->ismultientitymanaged = 1;
339 $this->isextrafieldmanaged = 1;
342 $this->labelStatus = array();
343 $this->labelStatus[-1] =
'StatusSendingCanceled';
344 $this->labelStatus[0] =
'StatusSendingDraft';
345 $this->labelStatus[1] =
'StatusSendingValidated';
346 $this->labelStatus[2] =
'StatusSendingProcessed';
349 $this->labelStatusShort = array();
350 $this->labelStatusShort[-1] =
'StatusSendingCanceledShort';
351 $this->labelStatusShort[0] =
'StatusSendingDraftShort';
352 $this->labelStatusShort[1] =
'StatusSendingValidatedShort';
353 $this->labelStatusShort[2] =
'StatusSendingProcessedShort';
364 global $langs,
$conf;
365 $langs->load(
"sendings");
374 $dirmodels = array_merge(array(
'/'), (array)
$conf->modules_parts[
'models']);
376 foreach ($dirmodels as $reldir) {
380 $mybool = ((bool) @include_once $dir.$file) || $mybool;
388 $obj =
new $classname();
389 '@phan-var-force ModelNumRefExpedition $obj';
390 $numref = $obj->getNextValue($soc, $this);
395 dol_print_error($this->db, get_class($this).
"::getNextNumRef ".$obj->error);
399 print $langs->trans(
"Error").
" ".$langs->trans(
"Error_EXPEDITION_ADDON_NUMBER_NotDefined");
411 public function create($user, $notrigger = 0)
415 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
420 if (empty($this->fk_project)) {
421 $this->fk_project = 0;
423 if (empty($this->date_creation)) {
424 $this->date_creation = $now;
426 if (empty($this->date_shipping) && !empty($this->date_expedition)) {
427 $this->date_shipping = $this->date_expedition;
435 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"expedition (";
438 $sql .=
", ref_customer";
440 $sql .=
", date_creation";
441 $sql .=
", fk_user_author";
442 $sql .=
", date_expedition";
443 $sql .=
", date_delivery";
445 $sql .=
", fk_projet";
446 $sql .=
", fk_address";
447 $sql .=
", fk_shipping_method";
448 $sql .=
", tracking_number";
453 $sql .=
", weight_units";
454 $sql .=
", size_units";
455 $sql .=
", note_private";
456 $sql .=
", note_public";
457 $sql .=
", model_pdf";
458 $sql .=
", fk_incoterms, location_incoterms";
459 $sql .=
", signed_status";
460 $sql .=
") VALUES (";
462 $sql .=
", ".((int) $this->entity);
463 $sql .=
", ".($this->ref_customer ?
"'".$this->db->escape($this->ref_customer).
"'" :
"null");
464 $sql .=
", ".($this->ref_ext ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
465 $sql .=
", '".$this->db->idate($this->date_creation).
"'";
466 $sql .=
", ".((int) $user->id);
467 $sql .=
", ".($this->date_shipping > 0 ?
"'".$this->db->idate($this->date_shipping).
"'" :
"null");
468 $sql .=
", ".($this->date_delivery > 0 ?
"'".$this->db->idate($this->date_delivery).
"'" :
"null");
469 $sql .=
", ".($this->socid > 0 ? ((int) $this->socid) :
"null");
470 $sql .=
", ".($this->fk_project > 0 ? ((int) $this->fk_project) :
"null");
471 $sql .=
", ".($this->fk_delivery_address > 0 ? $this->fk_delivery_address :
"null");
472 $sql .=
", ".($this->shipping_method_id > 0 ? ((int) $this->shipping_method_id) :
"null");
473 $sql .=
", '".$this->db->escape($this->tracking_number).
"'";
474 $sql .=
", ".(is_numeric($this->weight) ? $this->weight :
'NULL');
475 $sql .=
", ".(is_numeric($this->sizeS) ? $this->sizeS :
'NULL');
476 $sql .=
", ".(is_numeric($this->sizeW) ? $this->sizeW :
'NULL');
477 $sql .=
", ".(is_numeric($this->sizeH) ? $this->sizeH :
'NULL');
478 $sql .=
", ".($this->weight_units !=
'' ? (int) $this->weight_units :
'NULL');
479 $sql .=
", ".($this->size_units !=
'' ? (int) $this->size_units :
'NULL');
480 $sql .=
", ".(!empty($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null");
481 $sql .=
", ".(!empty($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null");
482 $sql .=
", ".(!empty($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null");
483 $sql .=
", ".(int) $this->fk_incoterms;
484 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
485 $sql .=
", ".($this->signed_status);
488 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
489 $resql = $this->db->query($sql);
491 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
"expedition");
493 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
494 $sql .=
" SET ref = '(PROV".$this->id.
")'";
495 $sql .=
" WHERE rowid = ".((int) $this->
id);
497 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
498 if ($this->db->query($sql)) {
500 $num = count($this->lines);
501 $kits_list = array();
503 for ($i = 0; $i < $num; $i++) {
505 $objectsrc->fetch($this->lines[$i]->origin_line_id);
506 if ($this->lines[$i]->product_type ==
"9" && $objectsrc->special_code == SUBTOTALS_SPECIAL_CODE) {
507 if ($this->
create_line($this->lines[$i]->entrepot_id, $this->lines[$i]->origin_line_id, $this->lines[$i]->qty, $this->lines[$i]->rang, $this->lines[$i]->array_options) <= 0) {
514 $line = $this->lines[$i];
515 if ($line->fk_product > 0) {
516 if (!isset($kits_list[$line->fk_product])) {
517 if (!is_object($line->product)) {
518 $line_product =
new Product($this->db);
519 $result = $line_product->fetch($line->fk_product,
'',
'',
'', 1, 1, 1);
524 $line_product = $line->product;
528 $line_product->get_sousproduits_arbo();
529 $prods_arbo = $line_product->get_arbo_each_prod($line->qty);
530 if (count($prods_arbo) > 0) {
531 $kits_list[$line->fk_product] = array(
532 'arbo' => $prods_arbo,
533 'total_qty' => $line->qty,
537 $kits_list[$line->fk_product][
'total_qty'] += $line->qty;
543 $kits_id_cached = array();
544 $sub_kits_id_cached = array();
545 for ($i = 0; $i < $num; $i++) {
546 $line = $this->lines[$i];
549 if (!isset($kits_id_cached[$line->fk_product])) {
550 if (!isset($line->detail_batch) || (isset($kits_list[$line->fk_product]) && !
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE'))) {
551 $qty = isset($kits_list[$line->fk_product]) ? $kits_list[$line->fk_product][
'total_qty'] : $line->qty;
552 $warehouse_id = (isset($kits_list[$line->fk_product]) && !
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) ? 0 : $line->entrepot_id;
553 $line_id = $this->
create_line($warehouse_id, $line->origin_line_id, $qty, $line->rang, $line->array_options, 0, $line->fk_product);
557 if (isset($kits_list[$line->fk_product])) $kits_id_cached[$line->fk_product] = $line_id;
564 $line_id = $kits_id_cached[$line->fk_product];
568 if (isset($kits_list[$line->fk_product]) && !
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) {
569 $prods_arbo = $kits_list[$line->fk_product][
'arbo'];
570 $total_qty = $kits_list[$line->fk_product][
'total_qty'];
573 $parent_line_id = $line_id;
575 $product_child_id = 0;
576 foreach ($prods_arbo as $index => $product_child_arr) {
591 $product_child_level = (int) $product_child_arr[
'level'];
592 $product_child_incdec = !empty($product_child_arr[
'incdec']);
595 if ($product_child_level != $level_last) {
596 $parent_line_id = $line_id;
597 $parent_product_id = $product_child_id;
598 if (isset($kits_id_cached[$parent_product_id])) {
599 $parent_line_id = $kits_id_cached[$parent_product_id];
601 $kits_id_cached[$parent_product_id] = $parent_line_id;
607 $next_level = $product_child_level;
608 $next_index = $index + 1;
609 if (isset($prods_arbo[$next_index])) {
610 $next_level = (int) $prods_arbo[$next_index][
'level'];
612 if ($next_level > $product_child_level) {
617 $product_child_id = (int) $product_child_arr[
'id'];
618 $product_child_qty = (float) $product_child_arr[
'nb_total'];
619 $warehouse_id = $line->entrepot_id;
620 if ($is_kit || !$product_child_incdec) {
621 if (!$product_child_incdec) {
622 $product_child_qty = 0;
628 if (!isset($sub_kits_id_cached[$product_child_id]) || $warehouse_id > 0) {
629 $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);
637 if (empty($warehouse_id)) {
638 $sub_kits_id_cached[$product_child_id] = $line_id;
642 $level_last = $product_child_level;
648 if (!$error && $this->
id && $this->origin_id) {
655 if (!$error && $this->
id &&
getDolGlobalInt(
'SHIPPING_USE_ITS_OWN_CONTACTS') &&
getDolGlobalString(
'MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN') && !empty($this->origin_type) && !empty($this->origin_id)) {
656 $originforcontact = $this->origin_type;
657 $originidforcontact = $this->origin_id;
659 $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";
660 $sqlcontact .=
" WHERE element_id = ".((int) $originidforcontact).
" AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$this->db->escape($originforcontact).
"'";
662 $resqlcontact = $this->db->query($sqlcontact);
664 while ($objcontact = $this->db->fetch_object($resqlcontact)) {
665 $this->
add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source);
680 if (!$error && !$notrigger) {
682 $result = $this->
call_trigger(
'SHIPPING_CREATE', $user);
692 foreach ($this->errors as $errmsg) {
693 dol_syslog(get_class($this).
"::create ".$errmsg, LOG_ERR);
694 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
696 $this->db->rollback();
701 $this->db->rollback();
706 $this->error = $this->db->lasterror().
" - sql=$sql";
707 $this->db->rollback();
712 $this->error = $this->db->error().
" - sql=$sql";
713 $this->db->rollback();
731 public function create_line($entrepot_id, $origin_line_id, $qty, $rang = 0, $array_options = [], $parent_line_id = 0, $product_id = 0)
737 $expeditionline->fk_expedition = $this->id;
738 $expeditionline->entrepot_id = $entrepot_id;
739 $expeditionline->fk_elementdet = $origin_line_id;
740 $expeditionline->element_type = $this->origin;
741 $expeditionline->fk_parent = $parent_line_id;
742 $expeditionline->fk_product = $product_id;
743 $expeditionline->qty = $qty;
744 $expeditionline->rang = $rang;
745 $expeditionline->array_options = $array_options;
747 if (!($expeditionline->fk_product > 0)) {
749 $order_line->fetch($expeditionline->fk_elementdet);
750 $expeditionline->fk_product = $order_line->fk_product;
753 if (($lineId = $expeditionline->insert($user)) < 0) {
754 $this->errors[] = $expeditionline->error;
772 $stockLocationQty = array();
774 $tab = $line_ext->detail_batch;
776 foreach ($tab as $detbatch) {
777 if (!empty($detbatch->fk_warehouse)) {
778 if (empty($stockLocationQty[$detbatch->fk_warehouse])) {
779 $stockLocationQty[$detbatch->fk_warehouse] = 0;
781 $stockLocationQty[$detbatch->fk_warehouse] += $detbatch->qty;
785 foreach ($stockLocationQty as $stockLocation => $qty) {
786 $line_id = $this->
create_line($stockLocation, $line_ext->origin_line_id, $qty, $line_ext->rang, $array_options);
791 foreach ($tab as $detbatch) {
792 if ($detbatch->fk_warehouse == $stockLocation) {
793 if (!($detbatch->create($line_id) > 0)) {
794 $this->errors = $detbatch->errors;
818 public function fetch($id, $ref =
'', $ref_ext =
'', $notused =
'')
823 if (empty($id) && empty($ref) && empty($ref_ext)) {
827 $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";
828 $sql .=
", e.date_valid";
829 $sql .=
", e.weight, e.weight_units, e.size, e.size_units, e.width, e.height";
830 $sql .=
", e.date_expedition as date_expedition, e.model_pdf, e.fk_address, e.date_delivery";
831 $sql .=
", e.fk_shipping_method, e.tracking_number";
832 $sql .=
", e.note_private, e.note_public";
833 $sql .=
', e.fk_incoterms, e.location_incoterms';
834 $sql .=
', e.signed_status';
835 $sql .=
', i.libelle as label_incoterms';
836 $sql .=
', s.libelle as shipping_method';
837 $sql .=
", el.fk_source as origin_id, el.sourcetype as origin_type";
838 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expedition as e";
839 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"element_element as el ON el.fk_target = e.rowid AND el.targettype = '".$this->db->escape($this->element).
"'";
840 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON e.fk_incoterms = i.rowid';
841 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_shipment_mode as s ON e.fk_shipping_method = s.rowid';
842 $sql .=
" WHERE e.entity IN (".getEntity(
'expedition').
")";
844 $sql .=
" AND e.rowid = ".((int) $id);
847 $sql .=
" AND e.ref='".$this->db->escape($ref).
"'";
850 $sql .=
" AND e.ref_ext='".$this->db->escape($ref_ext).
"'";
853 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
854 $result = $this->db->query($sql);
856 if ($this->db->num_rows($result)) {
857 $obj = $this->db->fetch_object($result);
859 $this->
id = $obj->rowid;
860 $this->entity = $obj->entity;
861 $this->
ref = $obj->ref;
862 $this->socid = $obj->socid;
863 $this->ref_customer = $obj->ref_customer;
864 $this->ref_ext = $obj->ref_ext;
865 $this->
status = $obj->fk_statut;
866 $this->statut = $this->status;
867 $this->signed_status = $obj->signed_status;
868 $this->user_author_id = $obj->fk_user_author;
869 $this->fk_user_author = $obj->fk_user_author;
870 $this->date_creation = $this->db->jdate($obj->date_creation);
871 $this->date_valid = $this->db->jdate($obj->date_valid);
872 $this->date = $this->db->jdate($obj->date_expedition);
873 $this->date_expedition = $this->db->jdate($obj->date_expedition);
874 $this->date_shipping = $this->db->jdate($obj->date_expedition);
875 $this->date_delivery = $this->db->jdate($obj->date_delivery);
876 $this->fk_delivery_address = $obj->fk_address;
877 $this->model_pdf = $obj->model_pdf;
878 $this->shipping_method_id = $obj->fk_shipping_method;
879 $this->shipping_method = $obj->shipping_method;
880 $this->tracking_number = $obj->tracking_number;
881 $this->origin = ($obj->origin_type ? $obj->origin_type :
'commande');
882 $this->origin_type = ($obj->origin_type ? $obj->origin_type :
'commande');
883 $this->origin_id = $obj->origin_id;
884 $this->billed = $obj->billed;
885 $this->fk_project = $obj->fk_project;
886 $this->signed_status = $obj->signed_status;
887 $this->trueWeight = $obj->weight;
888 $this->weight_units = $obj->weight_units;
890 $this->trueWidth = $obj->width;
891 $this->width_units = $obj->size_units;
892 $this->trueHeight = $obj->height;
893 $this->height_units = $obj->size_units;
894 $this->trueDepth = $obj->size;
895 $this->depth_units = $obj->size_units;
897 $this->note_public = $obj->note_public;
898 $this->note_private = $obj->note_private;
901 $this->trueSize = $obj->size.
"x".$obj->width.
"x".$obj->height;
902 $this->size_units = $obj->size_units;
905 $this->fk_incoterms = $obj->fk_incoterms;
906 $this->location_incoterms = $obj->location_incoterms;
907 $this->label_incoterms = $obj->label_incoterms;
909 $this->db->free($result);
921 if (isModEnabled(
'multicurrency')) {
922 if (!empty($this->multicurrency_code)) {
923 $this->multicurrency_code = $this->thirdparty->multicurrency_code;
925 if (
getDolGlobalString(
'MULTICURRENCY_USE_ORIGIN_TX') && !empty($this->thirdparty->multicurrency_tx)) {
926 $this->multicurrency_tx = $this->thirdparty->multicurrency_tx;
940 dol_syslog(get_class($this).
'::Fetch no expedition found', LOG_ERR);
941 $this->error =
'Shipment with id '.$id.
' not found';
945 $this->error = $this->db->error();
957 public function valid($user, $notrigger = 0)
961 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
967 dol_syslog(get_class($this).
"::valid not in draft status", LOG_WARNING);
971 if (!((!
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'expedition',
'creer'))
972 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'expedition',
'shipping_advance',
'validate')))) {
973 $this->error =
'Permission denied';
974 dol_syslog(get_class($this).
"::valid ".$this->error, LOG_ERR);
984 $soc->fetch($this->socid);
987 $result = $soc->setAsCustomer();
990 if (!$error && (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref))) {
992 } elseif (!empty($this->
ref)) {
993 $numref = $this->ref;
995 $numref =
"EXP".$this->id;
1002 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition SET";
1003 $sql .=
" ref='".$this->db->escape($numref).
"'";
1004 $sql .=
", fk_statut = 1";
1005 $sql .=
", date_valid = '".$this->db->idate($now).
"'";
1006 $sql .=
", fk_user_valid = ".((int) $user->id);
1007 $sql .=
" WHERE rowid = ".((int) $this->
id);
1009 dol_syslog(get_class($this).
"::valid update expedition", LOG_DEBUG);
1010 $resql = $this->db->query($sql);
1012 $this->error = $this->db->lasterror();
1017 if (!$error && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT')) {
1025 $triggerKey =
'SHIPPING_';
1026 if ($this->origin ==
'commande') {
1027 $triggerKey.=
'ORDER_SHIPMENTONPROCESS';
1029 $triggerKey.= strtoupper($this->origin).
'_SHIPMENTONPROCESS';
1038 if (!$error && !$notrigger) {
1040 $result = $this->
call_trigger(
'SHIPPING_VALIDATE', $user);
1048 $this->oldref = $this->ref;
1051 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
1053 $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).
"'";
1054 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'expedition/sending/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
1055 $resql = $this->db->query($sql);
1058 $this->error = $this->db->lasterror();
1060 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'expedition/sending/".$this->db->escape($this->newref).
"'";
1061 $sql .=
" WHERE filepath = 'expedition/sending/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
1062 $resql = $this->db->query($sql);
1065 $this->error = $this->db->lasterror();
1071 $dirsource =
$conf->expedition->dir_output.
'/sending/'.$oldref;
1072 $dirdest =
$conf->expedition->dir_output.
'/sending/'.$newref;
1073 if (!$error && file_exists($dirsource)) {
1074 dol_syslog(get_class($this).
"::valid rename dir ".$dirsource.
" into ".$dirdest);
1076 if (@rename($dirsource, $dirdest)) {
1079 $listoffiles =
dol_dir_list(
$conf->expedition->dir_output.
'/sending/'.$newref,
'files', 1,
'^'.preg_quote($oldref,
'/'));
1080 foreach ($listoffiles as $fileentry) {
1081 $dirsource = $fileentry[
'name'];
1082 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
1083 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
1084 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
1085 @rename($dirsource, $dirdest);
1094 $this->
ref = $numref;
1100 $this->db->commit();
1103 $this->db->rollback();
1122 if ($this->
status == self::STATUS_VALIDATED || $this->
status == self::STATUS_CLOSED) {
1124 include_once DOL_DOCUMENT_ROOT.
'/delivery/class/delivery.class.php';
1125 $delivery =
new Delivery($this->db);
1126 $result = $delivery->create_from_sending($user, $this->
id);
1130 $this->error = $delivery->error;
1155 public function addline($entrepot_id, $id, $qty, $array_options = [], $fk_product = 0, $fk_parent = 0)
1157 global
$conf, $langs;
1159 $num = count($this->lines);
1162 $line->entrepot_id = $entrepot_id;
1163 $line->origin_line_id = $id;
1164 $line->fk_elementdet = $id;
1165 $line->element_type =
'order';
1166 $line->fk_parent = $fk_parent;
1167 $line->fk_product = $fk_product;
1171 $orderline->fetch($id);
1174 $line->rang = $orderline->rang;
1175 $line->product_type = $orderline->product_type;
1176 if (!($line->fk_product > 0)) {
1177 $line->fk_product = $orderline->fk_product;
1180 if (isModEnabled(
'stock') && !empty($orderline->fk_product)) {
1181 $product =
new Product($this->db);
1182 $product->fetch($orderline->fk_product);
1185 $langs->load(
"errors");
1186 $this->error = $langs->trans(
"ErrorWarehouseRequiredIntoShipmentLine");
1191 $productChildrenNb = 0;
1193 $productChildrenNb = $product->hasFatherOrChild(1);
1195 if ($productChildrenNb > 0) {
1196 $product_stock =
null;
1197 $product->loadStockForVirtualProduct(
'warehouseopen', $line->qty);
1198 if ($entrepot_id > 0) {
1199 if (isset($product->stock_warehouse[$entrepot_id])) {
1200 $product_stock = $product->stock_warehouse[$entrepot_id]->real;
1203 foreach ($product->stock_warehouse as $componentStockWarehouse) {
1204 if ($product_stock ===
null) {
1205 $product_stock = $componentStockWarehouse->real;
1207 $product_stock = min($product_stock, $componentStockWarehouse->real);
1211 if ($product_stock ===
null) {
1216 if ($entrepot_id > 0) {
1217 $product->load_stock(
'warehouseopen');
1218 $product_stock = $product->stock_warehouse[$entrepot_id]->real;
1220 $product_stock = $product->stock_reel;
1224 $product_type = $product->type;
1226 $isavirtualproduct = ($productChildrenNb > 0);
1229 if ($product->stockable_product == Product::ENABLED_STOCK && $product_stock < $qty) {
1230 $langs->load(
"errors");
1231 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnShipment', $product->ref);
1232 $this->errorhidden =
'ErrorStockIsNotEnoughToAddProductOnShipment';
1234 $this->db->rollback();
1244 if (isModEnabled(
'productbatch') && !empty($line->fk_product) && !empty($orderline->product_tobatch)) {
1245 $this->error =
'ADDLINE_WAS_CALLED_INSTEAD_OF_ADDLINEBATCH '.$orderline->id.
' '.$line->fk_product;
1250 if (!
getDolGlobalString(
'MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) {
1251 $line->array_options = $array_options;
1254 $this->lines[$num] = $line;
1268 public function addline_batch($dbatch, $array_options = [], $origin_line =
null)
1271 global
$conf, $langs;
1273 $num = count($this->lines);
1275 if ($dbatch[
'qty'] > 0 || ($dbatch[
'qty'] == 0 &&
getDolGlobalString(
'SHIPMENT_GETS_ALL_ORDER_PRODUCTS'))) {
1278 foreach ($dbatch[
'detail'] as $key => $value) {
1279 if ($value[
'q'] > 0 || ($value[
'q'] == 0 &&
getDolGlobalString(
'SHIPMENT_GETS_ALL_ORDER_PRODUCTS'))) {
1285 $ret = $linebatch->fetchFromStock($value[
'id_batch']);
1290 $linebatch->qty = $value[
'q'];
1291 if ($linebatch->qty == 0 &&
getDolGlobalString(
'SHIPMENT_GETS_ALL_ORDER_PRODUCTS')) {
1292 $linebatch->batch =
null;
1294 $tab[] = $linebatch;
1297 require_once DOL_DOCUMENT_ROOT.
'/product/class/productbatch.class.php';
1299 $prod_batch->fetch($value[
'id_batch']);
1301 if ($prod_batch->qty < $linebatch->qty) {
1302 $langs->load(
"errors");
1303 $this->errors[] = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnShipment', $prod_batch->fk_product);
1304 dol_syslog(get_class($this).
"::addline_batch error=Product ".$prod_batch->batch.
": ".$this->errorsToString(), LOG_ERR);
1305 $this->db->rollback();
1313 if (is_object($linebatch)) {
1314 $line->entrepot_id = $linebatch->fk_warehouse;
1316 $line->origin_line_id = $dbatch[
'ix_l'];
1317 $line->fk_elementdet = $dbatch[
'ix_l'];
1318 $line->qty = $dbatch[
'qty'];
1319 $line->detail_batch = $tab;
1320 if (!($line->rang > 0)) {
1321 $line->rang = $origin_line->rang;
1323 if (!($line->fk_product > 0)) {
1324 $line->fk_product = $origin_line->fk_product;
1328 if (!
getDolGlobalString(
'MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) {
1329 $line->array_options = $array_options;
1333 $this->lines[$num] = $line;
1346 public function update($user =
null, $notrigger = 0)
1353 if (isset($this->
ref)) {
1354 $this->
ref = trim($this->
ref);
1356 if (isset($this->entity)) {
1357 $this->entity = (int) $this->entity;
1359 if (isset($this->ref_customer)) {
1360 $this->ref_customer = trim($this->ref_customer);
1362 if (isset($this->socid)) {
1363 $this->socid = (int) $this->socid;
1365 if (isset($this->fk_user_author)) {
1366 $this->fk_user_author = (int) $this->fk_user_author;
1368 if (isset($this->fk_user_valid)) {
1370 $this->fk_user_valid = (int) $this->fk_user_valid;
1372 if (isset($this->fk_delivery_address)) {
1373 $this->fk_delivery_address = (int) $this->fk_delivery_address;
1375 if (isset($this->shipping_method_id)) {
1376 $this->shipping_method_id = (int) $this->shipping_method_id;
1378 if (isset($this->tracking_number)) {
1379 $this->tracking_number = trim($this->tracking_number);
1381 if (isset($this->statut)) {
1382 $this->statut = (int) $this->statut;
1384 if (isset($this->
status)) {
1387 if (isset($this->trueDepth)) {
1388 $this->trueDepth = trim($this->trueDepth);
1390 if (isset($this->trueWidth)) {
1391 $this->trueWidth = trim($this->trueWidth);
1393 if (isset($this->trueHeight)) {
1394 $this->trueHeight = trim($this->trueHeight);
1396 if (isset($this->size_units)) {
1397 $this->size_units = trim($this->size_units);
1399 if (isset($this->weight_units)) {
1400 $this->weight_units = (int) $this->weight_units;
1402 if (isset($this->trueWeight)) {
1403 $this->weight = trim((
string) $this->trueWeight);
1405 if (isset($this->note_private)) {
1406 $this->note_private = trim($this->note_private);
1408 if (isset($this->note_public)) {
1409 $this->note_public = trim($this->note_public);
1411 if (isset($this->model_pdf)) {
1412 $this->model_pdf = trim($this->model_pdf);
1414 if (!empty($this->date_expedition)) {
1415 $this->date_shipping = $this->date_expedition;
1422 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition SET";
1423 $sql .=
" ref = ".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
1424 $sql .=
" ref_ext = ".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
1425 $sql .=
" ref_customer = ".(isset($this->ref_customer) ?
"'".$this->db->escape($this->ref_customer).
"'" :
"null").
",";
1426 $sql .=
" fk_soc = ".(isset($this->socid) ? $this->socid :
"null").
",";
1427 $sql .=
" date_creation = ".(dol_strlen($this->date_creation) != 0 ?
"'".$this->db->idate($this->date_creation).
"'" :
'null').
",";
1428 $sql .=
" fk_user_author = ".(isset($this->fk_user_author) ? $this->fk_user_author :
"null").
",";
1429 $sql .=
" date_valid = ".(dol_strlen($this->date_valid) != 0 ?
"'".$this->db->idate($this->date_valid).
"'" :
'null').
",";
1430 $sql .=
" fk_user_valid = ".(isset($this->fk_user_valid) ? $this->fk_user_valid :
"null").
",";
1431 $sql .=
" date_expedition = ".(dol_strlen($this->date_shipping) != 0 ?
"'".$this->db->idate($this->date_shipping).
"'" :
'null').
",";
1432 $sql .=
" date_delivery = ".(dol_strlen($this->date_delivery) != 0 ?
"'".$this->db->idate($this->date_delivery).
"'" :
'null').
",";
1433 $sql .=
" fk_address = ".(isset($this->fk_delivery_address) ? $this->fk_delivery_address :
"null").
",";
1434 $sql .=
" fk_shipping_method = ".((isset($this->shipping_method_id) && $this->shipping_method_id > 0) ? $this->shipping_method_id :
"null").
",";
1435 $sql .=
" tracking_number = ".(isset($this->tracking_number) ?
"'".$this->db->escape($this->tracking_number).
"'" :
"null").
",";
1436 $sql .=
" fk_statut = ".(isset($this->
status) ? $this->
status :
"null").
",";
1437 $sql .=
" fk_projet = ".(isset($this->fk_project) ? $this->fk_project :
"null").
",";
1438 $sql .=
" height = ".(($this->trueHeight !=
'') ? $this->trueHeight :
"null").
",";
1439 $sql .=
" width = ".(($this->trueWidth !=
'') ? $this->trueWidth :
"null").
",";
1440 $sql .=
" size_units = ".(isset($this->size_units) ? $this->size_units :
"null").
",";
1441 $sql .=
" size = ".(($this->trueDepth !=
'') ? $this->trueDepth :
"null").
",";
1442 $sql .=
" weight_units = ".(isset($this->weight_units) ? $this->weight_units :
"null").
",";
1443 $sql .=
" weight = ".(($this->trueWeight !=
'') ? $this->trueWeight :
"null").
",";
1444 $sql .=
" note_private = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
1445 $sql .=
" note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
1446 $sql .=
" model_pdf = ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
1447 $sql .=
" entity = ".((int)
$conf->entity);
1448 $sql .=
" WHERE rowid = ".((int) $this->
id);
1452 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1453 $resql = $this->db->query($sql);
1456 $this->errors[] =
"Error ".$this->db->lasterror();
1467 if (!$error && !$notrigger) {
1469 $result = $this->
call_trigger(
'SHIPPING_MODIFY', $user);
1478 foreach ($this->errors as $errmsg) {
1479 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
1480 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1482 $this->db->rollback();
1485 $this->db->commit();
1498 public function cancel($notrigger = 0, $also_update_stock =
false)
1500 global
$conf, $langs, $user;
1502 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1511 if (isset($this->linkedObjectsIds[
'delivery']) && count($this->linkedObjectsIds[
'delivery']) > 0) {
1512 $this->error =
'ErrorThereIsSomeDeliveries';
1516 if (!$error && !$notrigger) {
1518 $result = $this->
call_trigger(
'SHIPPING_CANCEL', $user);
1526 $can_update_stock = isModEnabled(
'stock') &&
1528 (
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT_CLOSE') && $this->
status == self::STATUS_CLOSED && $also_update_stock));
1530 require_once DOL_DOCUMENT_ROOT.
"/product/stock/class/mouvementstock.class.php";
1532 $langs->load(
"agenda");
1536 $sql .=
" ed.fk_product";
1537 $sql .=
", ed.qty, ed.fk_entrepot, ed.rowid as expeditiondet_id";
1538 $sql .=
", SUM(".$this->db->ifsql(
"pa.rowid IS NOT NULL",
"1",
"0").
") as iskit";
1539 $sql .=
", ".$this->db->ifsql(
"pai.incdec IS NULL",
"1",
"pai.incdec").
" as incdec";
1540 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet as ed";
1541 $sql .=
" LEFT JOIN ".$this->db->prefix().
"product_association as pa ON pa.fk_product_pere = ed.fk_product";
1542 $sql .=
" LEFT JOIN ".$this->db->prefix().
"expeditiondet as edp ON edp.rowid = ed.fk_parent";
1543 $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";
1544 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
1545 $sql .=
" GROUP BY ed.fk_product, ed.qty, ed.fk_entrepot, ed.rowid, pai.incdec";
1546 $sql .= $this->db->order(
"ed.rowid",
"DESC");
1548 dol_syslog(get_class($this).
"::delete select details", LOG_DEBUG);
1549 $resql = $this->db->query($sql);
1551 $cpt = $this->db->num_rows($resql);
1555 for ($i = 0; $i < $cpt; $i++) {
1556 dol_syslog(get_class($this).
"::delete movement index ".$i);
1557 $obj = $this->db->fetch_object($resql);
1558 $line_id = (int) $obj->expeditiondet_id;
1560 if ($can_update_stock && (empty($obj->iskit) ||
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) && !empty($obj->incdec)) {
1563 $mouvS->origin =
'';
1566 if (isModEnabled(
'productbatch')) {
1567 $lotArray = $shipmentlinebatch->fetchAll($obj->expeditiondet_id);
1568 if (!is_array($lotArray)) {
1570 $this->errors[] =
"Error ".$this->db->lasterror();
1574 if (empty($lotArray)) {
1578 $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));
1581 $this->errors = array_merge($this->errors, $mouvS->errors);
1587 foreach ($lotArray as $lot) {
1588 $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));
1591 $this->errors = array_merge($this->errors, $mouvS->errors);
1604 $res = $shipment_line->fetch($line_id);
1606 $result = $shipment_line->delete($user);
1609 $this->errors[] =
"Error ".$shipment_line->errorsToString();
1613 $this->errors[] =
"Error ".$shipment_line->errorsToString();
1623 $this->errors[] =
"Error ".$this->db->lasterror();
1636 $sql =
"SELECT rowid FROM ".$this->db->prefix().
"expedition";
1637 $sql .=
" WHERE rowid = ".((int) $this->
id);
1639 if ($this->db->query($sql)) {
1640 if (!empty($this->origin) && $this->origin_id > 0) {
1643 '@phan-var-force Facture|Commande $origin_object';
1655 $this->db->commit();
1659 if (!empty(
$conf->expedition->dir_output)) {
1660 $dir =
$conf->expedition->dir_output.
'/sending/'.$ref;
1661 $file = $dir.
'/'.$ref.
'.pdf';
1662 if (file_exists($file)) {
1667 if (file_exists($dir)) {
1669 $this->error = $langs->trans(
"ErrorCanNotDeleteDir", $dir);
1677 $this->db->rollback();
1681 $this->error = $this->db->lasterror().
" - sql=$sql";
1682 $this->db->rollback();
1686 $this->db->rollback();
1690 $this->db->rollback();
1704 public function delete($user =
null, $notrigger = 0, $also_update_stock =
false)
1706 global
$conf, $langs;
1712 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1721 if (isset($this->linkedObjectsIds[
'delivery']) && count($this->linkedObjectsIds[
'delivery']) > 0) {
1722 $this->error =
'ErrorThereIsSomeDeliveries';
1726 if (!$error && !$notrigger) {
1728 $result = $this->
call_trigger(
'SHIPPING_DELETE', $user);
1736 $can_update_stock = isModEnabled(
'stock') &&
1738 (
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT_CLOSE') && $this->
status == self::STATUS_CLOSED && $also_update_stock));
1740 require_once DOL_DOCUMENT_ROOT.
"/product/stock/class/mouvementstock.class.php";
1742 $langs->load(
"agenda");
1749 $sql .=
" ed.fk_product";
1750 $sql .=
", ed.qty, ed.fk_entrepot, ed.rowid as expeditiondet_id";
1751 $sql .=
", SUM(".$this->db->ifsql(
"pa.rowid IS NOT NULL",
"1",
"0").
") as iskit";
1752 $sql .=
", ".$this->db->ifsql(
"pai.incdec IS NULL",
"1",
"pai.incdec").
" as incdec";
1753 $sql .=
" FROM ".$this->db->prefix().
"expeditiondet as ed";
1754 $sql .=
" LEFT JOIN ".$this->db->prefix().
"product_association as pa ON pa.fk_product_pere = ed.fk_product";
1755 $sql .=
" LEFT JOIN ".$this->db->prefix().
"expeditiondet as edp ON edp.rowid = ed.fk_parent";
1756 $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";
1757 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
1758 $sql .=
" GROUP BY ed.fk_product, ed.qty, ed.fk_entrepot, ed.rowid, pai.incdec";
1759 $sql .= $this->db->order(
"ed.rowid",
"DESC");
1761 dol_syslog(get_class($this).
"::delete select details", LOG_DEBUG);
1762 $resql = $this->db->query($sql);
1764 $cpt = $this->db->num_rows($resql);
1765 for ($i = 0; $i < $cpt; $i++) {
1766 dol_syslog(get_class($this).
"::delete movement index ".$i);
1767 $obj = $this->db->fetch_object($resql);
1768 $line_id = (int) $obj->expeditiondet_id;
1770 if ($can_update_stock && (empty($obj->iskit) ||
getDolGlobalInt(
'PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) && !empty($obj->incdec)) {
1773 $mouvS->origin =
'';
1775 $lotArray = $shipmentlinebatch->fetchAll($line_id);
1776 if (!is_array($lotArray)) {
1778 $this->errors[] =
"Error ".$this->db->lasterror();
1780 if (empty($lotArray)) {
1784 $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));
1787 $this->errors = array_merge($this->errors, $mouvS->errors);
1793 foreach ($lotArray as $lot) {
1794 $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));
1797 $this->errors = array_merge($this->errors, $mouvS->errors);
1810 $res = $shipment_line->fetch($line_id);
1812 $result = $shipment_line->delete($user);
1815 $this->errors[] =
"Error ".$shipment_line->errorsToString();
1819 $this->errors[] =
"Error ".$shipment_line->errorsToString();
1829 $this->errors[] =
"Error ".$this->db->lasterror();
1854 $sql =
"DELETE FROM ".$this->db->prefix().
"expedition";
1855 $sql .=
" WHERE rowid = ".((int) $this->
id);
1857 if ($this->db->query($sql)) {
1858 if (!empty($this->origin) && $this->origin_id > 0) {
1861 '@phan-var-force Facture|Commande $origin_object';
1873 $this->db->commit();
1881 if (!empty(
$conf->expedition->dir_output)) {
1882 $dir =
$conf->expedition->dir_output .
'/sending/' . $ref;
1883 $file = $dir .
'/' . $ref .
'.pdf';
1884 if (file_exists($file)) {
1889 if (file_exists($dir)) {
1891 $this->error = $langs->trans(
"ErrorCanNotDeleteDir", $dir);
1899 $this->db->rollback();
1903 $this->error = $this->db->lasterror().
" - sql=$sql";
1904 $this->db->rollback();
1908 $this->db->rollback();
1912 $this->db->rollback();
1928 $this->lines = array();
1933 $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";
1934 $sql .=
", cd.total_ht, cd.total_localtax1, cd.total_localtax2, cd.total_ttc, cd.total_tva";
1935 $sql .=
", cd.fk_remise_except, cd.fk_product_fournisseur_price as fk_fournprice";
1936 $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";
1937 $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";
1938 $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";
1939 $sql .=
", p.ref as product_ref, p.label as product_label, p.fk_product_type, p.barcode as product_barcode";
1940 $sql .=
", p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units";
1941 $sql .=
", p.surface, p.surface_units, p.volume, p.volume_units, p.tosell as product_tosell, p.tobuy as product_tobuy";
1942 $sql .=
", p.tobatch as product_tobatch, p.stockable_product";
1943 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expeditiondet as ed, ".MAIN_DB_PREFIX.
"commandedet as cd";
1944 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"product as p ON p.rowid = cd.fk_product";
1945 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
1946 $sql .=
" AND ed.fk_elementdet = cd.rowid";
1947 $sql .=
" ORDER BY cd.rang, ed.fk_elementdet";
1949 dol_syslog(get_class($this).
"::fetch_lines", LOG_DEBUG);
1950 $resql = $this->db->query($sql);
1952 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
1954 $num = $this->db->num_rows($resql);
1960 $this->total_ht = 0;
1961 $this->total_tva = 0;
1962 $this->total_ttc = 0;
1963 $this->total_localtax1 = 0;
1964 $this->total_localtax2 = 0;
1966 $this->multicurrency_total_ht = 0;
1967 $this->multicurrency_total_tva = 0;
1968 $this->multicurrency_total_ttc = 0;
1974 $obj = $this->db->fetch_object($resql);
1976 if ($originline > 0 && $originline == $obj->fk_elementdet) {
1978 $line->entrepot_id = 0;
1979 $line->qty_shipped += $obj->qty_shipped;
1982 $line->entrepot_id = $obj->fk_entrepot;
1983 $line->qty_shipped = $obj->qty_shipped;
1987 $detail_entrepot->entrepot_id = $obj->fk_entrepot;
1988 $detail_entrepot->qty_shipped = $obj->qty_shipped;
1989 $detail_entrepot->line_id = $obj->line_id;
1990 $line->details_entrepot[] = $detail_entrepot;
1992 $line->line_id = $obj->line_id;
1993 $line->rowid = $obj->line_id;
1994 $line->id = $obj->line_id;
1996 $line->fk_origin =
'orderline';
1998 $line->fk_element = $obj->fk_element;
1999 $line->origin_id = $obj->fk_element;
2000 $line->fk_elementdet = $obj->fk_elementdet;
2001 $line->origin_line_id = $obj->fk_elementdet;
2002 $line->element_type = $obj->element_type;
2004 $line->fk_expedition = $this->id;
2006 $line->stockable_product = $obj->stockable_product;
2007 $line->product_type = $obj->product_type;
2008 $line->fk_product = $obj->fk_product;
2009 $line->fk_product_type = $obj->fk_product_type;
2010 $line->ref = $obj->product_ref;
2011 $line->product_ref = $obj->product_ref;
2012 $line->product_label = $obj->product_label;
2013 $line->libelle = $obj->product_label;
2014 $line->product_barcode = $obj->product_barcode;
2015 $line->product_tosell = $obj->product_tosell;
2016 $line->product_tobuy = $obj->product_tobuy;
2017 $line->product_tobatch = $obj->product_tobatch;
2018 $line->fk_fournprice = $obj->fk_fournprice;
2019 $line->label = $obj->custom_label;
2020 $line->description = $obj->description;
2021 $line->qty_asked = $obj->qty_asked;
2022 $line->rang = $obj->rang;
2023 $line->weight = $obj->weight;
2024 $line->weight_units = $obj->weight_units;
2025 $line->length = $obj->length;
2026 $line->length_units = $obj->length_units;
2027 $line->width = $obj->width;
2028 $line->width_units = $obj->width_units;
2029 $line->height = $obj->height;
2030 $line->height_units = $obj->height_units;
2031 $line->surface = $obj->surface;
2032 $line->surface_units = $obj->surface_units;
2033 $line->volume = $obj->volume;
2034 $line->volume_units = $obj->volume_units;
2035 $line->stockable_product = $obj->stockable_product;
2036 $line->fk_unit = $obj->fk_unit;
2038 $line->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
2040 $line->pa_ht = $obj->pa_ht;
2043 $localtax_array = array(0 => $obj->localtax1_type, 1 => $obj->localtax1_tx, 2 => $obj->localtax2_type, 3 => $obj->localtax2_tx);
2044 $localtax1_tx =
get_localtax($obj->tva_tx, 1, $this->thirdparty);
2045 $localtax2_tx =
get_localtax($obj->tva_tx, 2, $this->thirdparty);
2048 $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);
2049 $line->desc = $obj->description;
2050 $line->qty = $line->qty_shipped;
2051 $line->total_ht = (float) $tabprice[0];
2052 $line->total_localtax1 = (float) $tabprice[9];
2053 $line->total_localtax2 = (float) $tabprice[10];
2054 $line->total_ttc = (float) $tabprice[2];
2055 $line->total_tva = (float) $tabprice[1];
2056 $line->vat_src_code = $obj->vat_src_code;
2057 $line->tva_tx = $obj->tva_tx;
2058 $line->localtax1_tx = $obj->localtax1_tx;
2059 $line->localtax2_tx = $obj->localtax2_tx;
2060 $line->info_bits = $obj->info_bits;
2061 $line->price = $obj->price;
2062 $line->subprice = $obj->subprice;
2063 $line->fk_remise_except = $obj->fk_remise_except;
2064 $line->remise_percent = $obj->remise_percent;
2066 $this->total_ht += $tabprice[0];
2067 $this->total_tva += $tabprice[1];
2068 $this->total_ttc += $tabprice[2];
2069 $this->total_localtax1 += $tabprice[9];
2070 $this->total_localtax2 += $tabprice[10];
2072 $line->date_start = $this->db->jdate($obj->date_start);
2073 $line->date_end = $this->db->jdate($obj->date_end);
2075 $line->special_code = $obj->special_code;
2078 $this->fk_multicurrency = $obj->fk_multicurrency;
2079 $this->multicurrency_code = $obj->multicurrency_code;
2080 $line->multicurrency_subprice = $obj->multicurrency_subprice;
2081 $line->multicurrency_total_ht = $obj->multicurrency_total_ht;
2082 $line->multicurrency_total_tva = $obj->multicurrency_total_tva;
2083 $line->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
2085 $this->multicurrency_total_ht += $obj->multicurrency_total_ht;
2086 $this->multicurrency_total_tva += $obj->multicurrency_total_tva;
2087 $this->multicurrency_total_ttc += $obj->multicurrency_total_ttc;
2089 if ($originline != $obj->fk_elementdet) {
2090 $line->detail_batch = array();
2094 if (isModEnabled(
'productbatch') && $obj->line_id > 0 && $obj->product_tobatch > 0) {
2095 $newdetailbatch = $shipmentlinebatch->fetchAll($obj->line_id, $obj->fk_product);
2097 if (is_array($newdetailbatch)) {
2098 if ($originline != $obj->fk_elementdet) {
2099 $line->detail_batch = $newdetailbatch;
2101 $line->detail_batch = array_merge($line->detail_batch, $newdetailbatch);
2108 $detail_children = array();
2109 $line_child_list = array();
2110 $res = $line->findAllChild($line->id, $line_child_list, 1);
2112 foreach ($line_child_list as $child_line) {
2113 foreach ($child_line as $child_obj) {
2114 $child_product_id = (int) $child_obj->fk_product;
2115 $child_warehouse_id = (int) $child_obj->fk_warehouse;
2117 if ($child_warehouse_id > 0) {
2119 if (!isset($detail_children[$child_product_id])) {
2120 $detail_children[$child_product_id] = array();
2122 if (!isset($detail_children[$child_product_id][$child_warehouse_id])) {
2123 $detail_children[$child_product_id][$child_warehouse_id] = 0;
2125 $detail_children[$child_product_id][$child_warehouse_id] += $child_obj->qty;
2130 $line->detail_children = $detail_children;
2133 $line->fetch_optionals();
2135 if ($originline != $obj->fk_elementdet) {
2136 $this->lines[$lineindex] = $line;
2139 $line->total_ht += $tabprice[0];
2140 $line->total_localtax1 += $tabprice[9];
2141 $line->total_localtax2 += $tabprice[10];
2142 $line->total_ttc += $tabprice[2];
2143 $line->total_tva += $tabprice[1];
2147 $originline = $obj->fk_elementdet;
2149 $this->db->free($resql);
2152 $this->error = $this->db->error();
2168 if ($this->
status == self::STATUS_DRAFT) {
2174 $line->fetch($lineid);
2176 if ($line->delete($user) > 0) {
2179 $this->db->commit();
2182 $this->db->rollback();
2186 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
2200 global
$conf, $langs;
2202 $langs->load(
'sendings');
2204 $nofetch = !empty($params[
'nofetch']);
2207 $datas[
'picto'] =
img_picto(
'', $this->picto).
' <u class="paddingrightonly">'.$langs->trans(
"Shipment").
'</u>';
2208 if (isset($this->
status)) {
2209 $datas[
'picto'] .=
' '.$this->getLibStatut(5);
2211 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
2212 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.($this->ref_customer ? $this->ref_customer : $this->ref_client);
2214 $langs->load(
'companies');
2215 if (empty($this->thirdparty)) {
2218 $datas[
'customer'] =
'<br><b>'.$langs->trans(
'Customer').
':</b> '.$this->thirdparty->getNomUrl(1,
'', 0, 1);
2235 public function getNomUrl($withpicto = 0, $option =
'', $max = 0, $short = 0, $notooltip = 0, $save_lastsearch_value = -1)
2237 global $langs, $hookmanager;
2242 'objecttype' => $this->element,
2243 'option' => $option,
2246 $classfortooltip =
'classfortooltip';
2249 $classfortooltip =
'classforajaxtooltip';
2250 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
2256 $url = DOL_URL_ROOT.
'/expedition/card.php?id='.$this->id;
2262 if ($option !==
'nolink') {
2264 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2265 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
2266 $add_save_lastsearch_values = 1;
2268 if ($add_save_lastsearch_values) {
2269 $url .=
'&save_lastsearch_values=1';
2274 if (empty($notooltip)) {
2276 $label = $langs->trans(
"Shipment");
2277 $linkclose .=
' alt="'.dolPrintHTMLForAttribute($label).
'"';
2279 $linkclose .= ($label ?
' title="'.dolPrintHTMLForAttribute($label).
'"' :
' title="tocomplete"');
2280 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
2283 $linkstart =
'<a href="'.$url.
'"';
2284 $linkstart .= $linkclose.
'>';
2287 $result .= $linkstart;
2289 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), ($notooltip ? (($withpicto != 2) ?
'class="paddingright"' :
'') :
'class="'.(($withpicto != 2) ?
'paddingright ' :
'').
'"'), 0, 0, $notooltip ? 0 : 1);
2291 if ($withpicto != 2) {
2292 $result .= $this->ref;
2294 $result .= $linkend;
2296 $hookmanager->initHooks(array($this->element .
'dao'));
2297 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result);
2298 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
2300 $result = $hookmanager->resPrint;
2302 $result .= $hookmanager->resPrint;
2331 $labelStatus = $langs->transnoentitiesnoconv($this->labelStatus[$status]);
2332 $labelStatusShort = $langs->transnoentitiesnoconv($this->labelStatusShort[$status]);
2334 $statusType =
'status'.$status;
2335 if ($status == self::STATUS_VALIDATED) {
2336 $statusType =
'status4';
2338 if ($status == self::STATUS_CLOSED) {
2339 $statusType =
'status6';
2341 if ($status == self::STATUS_CANCELED) {
2342 $statusType =
'status9';
2346 $status_label = $this->signed_status ? $labelStatus . $signed_label : $labelStatus;
2347 $status_label_short = $this->signed_status ? $labelStatusShort . $signed_label : $labelStatusShort;
2349 return dolGetStatus($status_label, $status_label_short,
'', $statusType, $mode);
2361 global $langs,
$conf;
2363 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
2365 $return =
'<div class="box-flex-item box-flex-grow-zero">';
2366 $return .=
'<div class="info-box info-box-sm">';
2367 $return .=
'<div class="info-box-icon bg-infobox-action">';
2369 $return .=
'</div>';
2370 $return .=
'<div class="info-box-content">';
2371 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl() : $this->ref).
'</span>';
2372 if ($selected >= 0) {
2373 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
2375 if (property_exists($this,
'thirdparty') && is_object($this->thirdparty)) {
2376 $return .=
'<br><div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).
'</div>';
2378 if (property_exists($this,
'total_ht')) {
2379 $return .=
'<div class="info-box-ref amount">'.price($this->total_ht, 0, $langs, 0, -1, -1,
$conf->currency).
' '.$langs->trans(
'HT').
'</div>';
2381 if (method_exists($this,
'getLibStatut')) {
2382 $return .=
'<div class="info-box-status">'.$this->getLibStatut(3).
'</div>';
2384 $return .=
'</div>';
2385 $return .=
'</div>';
2386 $return .=
'</div>';
2404 dol_syslog(get_class($this).
"::initAsSpecimen");
2407 $order->initAsSpecimen();
2411 $this->
ref =
'SPECIMEN';
2412 $this->specimen = 1;
2414 $this->livraison_id = 0;
2416 $this->date_creation = $now;
2417 $this->date_valid = $now;
2418 $this->date_delivery = $now + 24 * 3600;
2419 $this->date_expedition = $now + 24 * 3600;
2421 $this->entrepot_id = 0;
2422 $this->fk_delivery_address = 0;
2425 $this->commande_id = 0;
2426 $this->commande = $order;
2428 $this->origin_id = 1;
2429 $this->origin_type =
'commande';
2431 $this->note_private =
'Private note';
2432 $this->note_public =
'Public note';
2436 while ($xnbp < $nbp) {
2438 $line->product_desc = $langs->trans(
"Description").
" ".$xnbp;
2439 $line->product_label = $langs->trans(
"Description").
" ".$xnbp;
2441 $line->qty_asked = 5;
2442 $line->qty_shipped = 4;
2443 $line->fk_product = $this->commande->lines[$xnbp]->fk_product;
2445 $line->weight = 1.123456;
2446 $line->weight_units = 0;
2448 $line->volume = 2.34567;
2449 $line->volume_unit = 0;
2451 $this->lines[] = $line;
2482 if ($user->hasRight(
'expedition',
'creer')) {
2483 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
2484 $sql .=
" SET date_delivery = ".($delivery_date ?
"'".$this->db->idate($delivery_date).
"'" :
'null');
2485 $sql .=
" WHERE rowid = ".((int) $this->
id);
2487 dol_syslog(get_class($this).
"::setDeliveryDate", LOG_DEBUG);
2488 $resql = $this->db->query($sql);
2490 $this->date_delivery = $delivery_date;
2493 $this->error = $this->db->error();
2510 if ($user->hasRight(
'expedition',
'creer')) {
2511 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
2512 $sql .=
" SET date_expedition = ".($shipping_date ?
"'".$this->db->idate($shipping_date).
"'" :
'null');
2513 $sql .=
" WHERE rowid = ".((int) $this->
id);
2515 dol_syslog(get_class($this).
"::setShippingDate", LOG_DEBUG);
2516 $resql = $this->db->query($sql);
2518 $this->date_shipping = $shipping_date;
2521 $this->error = $this->db->error();
2539 $this->meths = array();
2541 $sql =
"SELECT em.rowid, em.code, em.libelle as label";
2542 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2543 $sql .=
" WHERE em.active = 1";
2544 $sql .=
" ORDER BY em.libelle ASC";
2546 $resql = $this->db->query($sql);
2548 while ($obj = $this->db->fetch_object($resql)) {
2549 $label = $langs->trans(
'SendingMethod'.$obj->code);
2550 $this->meths[$obj->rowid] = ($label !=
'SendingMethod'.$obj->code ? $label : $obj->label);
2567 $this->listmeths = array();
2570 $sql =
"SELECT em.rowid, em.code, em.libelle as label, em.description, em.tracking, em.active";
2571 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2573 $sql .=
" WHERE em.rowid=".((int) $id);
2576 $resql = $this->db->query($sql);
2578 while ($obj = $this->db->fetch_object($resql)) {
2579 $this->listmeths[$i][
'rowid'] = $obj->rowid;
2580 $this->listmeths[$i][
'code'] = $obj->code;
2581 $label = $langs->trans(
'SendingMethod'.$obj->code);
2582 $this->listmeths[$i][
'libelle'] = ($label !=
'SendingMethod'.$obj->code ? $label : $obj->label);
2583 $this->listmeths[$i][
'description'] = $obj->description;
2584 $this->listmeths[$i][
'tracking'] = $obj->tracking;
2585 $this->listmeths[$i][
'active'] = $obj->active;
2599 if (!empty($this->shipping_method_id)) {
2600 $sql =
"SELECT em.code, em.tracking";
2601 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2602 $sql .=
" WHERE em.rowid = ".((int) $this->shipping_method_id);
2604 $resql = $this->db->query($sql);
2606 if ($obj = $this->db->fetch_object($resql)) {
2607 $tracking = $obj->tracking;
2612 if (!empty($tracking) && !empty($value)) {
2613 $url = str_replace(
'{TRACKID}', $value, $tracking);
2614 $this->tracking_url = sprintf(
'<a target="_blank" rel="noopener noreferrer" href="%s">%s</a>', $url, ($value ? $value :
'url'));
2616 $this->tracking_url = $value;
2632 if ($this->
status == self::STATUS_CLOSED) {
2639 if (empty($this->date_shipping)) {
2640 $sql .=
", date_expedition = '".$this->db->escape($this->db->idate(
dol_now())).
"'";
2642 $sql .=
" WHERE rowid = ".((int) $this->
id).
" AND fk_statut > 0";
2644 $resql = $this->db->query($sql);
2647 if ($this->origin ==
'commande' && $this->origin_id > 0) {
2649 $order->fetch($this->origin_id);
2651 $order->loadExpeditions(self::STATUS_CLOSED);
2653 $shipments_match_order = 1;
2654 foreach ($order->lines as $line) {
2655 $lineid = $line->id;
2657 if (($line->product_type == 0 ||
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES')) && $order->expeditions[$lineid] != $qty) {
2658 $shipments_match_order = 0;
2659 $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';
2664 if ($shipments_match_order) {
2665 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');
2667 $order->cloture($user);
2675 if (!$error && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT_CLOSE')) {
2684 $result = $this->
call_trigger(
'SHIPPING_CLOSED', $user);
2695 $this->db->commit();
2701 $this->db->rollback();
2720 require_once DOL_DOCUMENT_ROOT .
'/product/stock/class/mouvementstock.class.php';
2722 $langs->load(
"agenda");
2726 $sql .=
" ed.rowid as edid, ed.fk_product, ed.qty, ed.fk_entrepot";
2727 $sql .=
", cd.rowid as cdid";
2728 $sql .=
", cd.subprice";
2729 $sql .=
", edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
2731 $sql .=
" FROM " . $this->db->prefix() .
"expeditiondet as ed";
2732 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"commandedet as cd ON cd.rowid = ed.fk_elementdet";
2733 $sql .=
" LEFT JOIN " . $this->db->prefix() .
"expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
2734 $sql .=
" INNER JOIN " . $this->db->prefix() .
"expedition as e ON ed.fk_expedition = e.rowid";
2735 $sql .=
" WHERE ed.fk_expedition = " . ((int) $this->
id);
2738 dol_syslog(get_class($this) .
"::valid select details", LOG_DEBUG);
2739 $resql = $this->db->query($sql);
2741 $cpt = $this->db->num_rows($resql);
2742 for ($i = 0; $i < $cpt; $i++) {
2743 $obj = $this->db->fetch_object($resql);
2744 if (empty($obj->edbrowid)) {
2747 $qty = $obj->edbqty;
2749 if ($qty <= 0 || ($qty < 0 && !
getDolGlobalInt(
'SHIPMENT_ALLOW_NEGATIVE_QTY'))) {
2752 dol_syslog(get_class($this) .
"::valid movement index " . $i .
" ed.rowid=" . $obj->edid .
" edb.rowid=" . $obj->edbrowid);
2755 $mouvS->origin = &$this;
2756 $mouvS->setOrigin($this->element, $this->
id, $obj->cdid, $obj->edid);
2758 if (empty($obj->edbrowid)) {
2762 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans($labelmovement, $obj->ref));
2764 $this->error = $mouvS->error;
2765 $this->errors = $mouvS->errors;
2773 $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);
2775 $this->error = $mouvS->error;
2776 $this->errors = $mouvS->errors;
2784 $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)";
2785 $resqldelete = $this->db->query($sqldelete);
2789 $this->error = $this->db->lasterror();
2790 $this->errors[] = $this->db->lasterror();
2813 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'expedition SET billed = 1';
2814 $sql .=
" WHERE rowid = ".((int) $this->
id).
' AND fk_statut > 0';
2816 $resql = $this->db->query($sql);
2821 $result = $this->
call_trigger(
'SHIPPING_BILLED', $user);
2828 $this->errors[] = $this->db->lasterror;
2831 if (empty($error)) {
2832 $this->db->commit();
2835 $this->db->rollback();
2850 if ($this->
status <= self::STATUS_DRAFT) {
2854 return $this->
setStatusCommon($user, self::STATUS_DRAFT, $notrigger,
'SHIPMENT_UNVALIDATE');
2864 global $langs, $user;
2869 if ($this->
status == self::STATUS_VALIDATED) {
2875 $oldbilled = $this->billed;
2877 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'expedition SET fk_statut = 1';
2878 $sql .=
" WHERE rowid = ".((int) $this->
id).
' AND fk_statut > 0';
2880 $resql = $this->db->query($sql);
2887 if (!$error && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_SHIPMENT_CLOSE')) {
2888 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
2890 $langs->load(
"agenda");
2894 $sql =
"SELECT cd.fk_product, cd.subprice,";
2895 $sql .=
" ed.rowid, ed.qty, ed.fk_entrepot,";
2896 $sql .=
" edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
2897 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commandedet as cd,";
2898 $sql .=
" ".MAIN_DB_PREFIX.
"expeditiondet as ed";
2899 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
2900 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
2901 $sql .=
" AND cd.rowid = ed.fk_elementdet";
2903 dol_syslog(get_class($this).
"::valid select details", LOG_DEBUG);
2904 $resql = $this->db->query($sql);
2906 $cpt = $this->db->num_rows($resql);
2907 for ($i = 0; $i < $cpt; $i++) {
2908 $obj = $this->db->fetch_object($resql);
2909 if (empty($obj->edbrowid)) {
2912 $qty = $obj->edbqty;
2917 dol_syslog(get_class($this).
"::reopen expedition movement index ".$i.
" ed.rowid=".$obj->rowid.
" edb.rowid=".$obj->edbrowid);
2921 $mouvS->origin = &$this;
2922 $mouvS->setOrigin($this->element, $this->
id);
2924 if (empty($obj->edbrowid)) {
2928 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans(
"ShipmentUnClassifyCloseddInDolibarr", $this->ref));
2930 $this->error = $mouvS->error;
2931 $this->errors = $mouvS->errors;
2939 $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);
2941 $this->error = $mouvS->error;
2942 $this->errors = $mouvS->errors;
2949 $this->error = $this->db->lasterror();
2956 $result = $this->
call_trigger(
'SHIPPING_REOPEN', $user);
2963 $this->errors[] = $this->db->lasterror();
2967 $this->db->commit();
2972 $this->billed = $oldbilled;
2973 $this->db->rollback();
2989 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
2991 $outputlangs->load(
"products");
2996 if (!empty($this->model_pdf)) {
2997 $modele = $this->model_pdf;
3003 $modelpath =
"core/modules/expedition/doc/";
3007 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
Class to manage customers orders.
const STATUS_SHIPMENTONPROCESS
Shipment on process.
const STATUS_VALIDATED
Validated status.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
deleteEcmFiles($mode=0)
Delete related files of object in database.
add_object_linked($origin=null, $origin_id=null, $f_user=null, $notrigger=0)
Add an object link into llx_element_element.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid=0, $f_user=null, $notrigger=0)
Delete all links between an object $this.
setErrorsFromObject($object)
setErrorsFromObject
setStatut($status, $elementId=null, $elementType='', $trigkey='', $fieldstatus='fk_statut')
Set status of an object.
deleteExtraFields()
Delete all extra fields values for the current object.
setStatusCommon($user, $status, $notrigger=0, $triggercode='')
Set to a status.
fetchObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $clause='OR', $alsosametype=1, $orderby='sourcetype', $loadalsoobjects=1)
Fetch array of objects linked to current object (object of enabled modules only).
errorsToString()
Method to output saved errors.
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
fetch_origin()
Read linked origin object.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
delete_linked_contact($source='', $code='')
Delete all links between an object $this and all its contacts in llx_element_contact.
call_trigger($triggerName, $user)
Call trigger based on this instance.
add_contact($fk_socpeople, $type_contact, $source='external', $notrigger=0)
Add a link between element $this->element and a contact.
Class to manage receptions.
Class to manage Dolibarr database access.
getNomUrl($withpicto=0, $option='', $max=0, $short=0, $notooltip=0, $save_lastsearch_value=-1)
Return clickable link of object (with eventually picto)
addline_batch($dbatch, $array_options=[], $origin_line=null)
Add a shipment line with batch record.
create_delivery($user)
Create a delivery receipt from a shipment.
setDraft($user, $notrigger=0)
Set draft status.
const STATUS_SHIPMENT_IN_PROGRESS
Expedition in progress -> package exit the warehouse and is now in the truck or into the hand of the ...
getUrlTrackingStatus($value='')
Forge an set tracking url.
setClosed()
Classify the shipping as closed (this records also the stock movement)
__construct($db)
Constructor.
create_line($entrepot_id, $origin_line_id, $qty, $rang=0, $array_options=[], $parent_line_id=0, $product_id=0)
Create a expedition line.
addline($entrepot_id, $id, $qty, $array_options=[], $fk_product=0, $fk_parent=0)
Add an expedition line.
create($user, $notrigger=0)
Create expedition en base.
LibStatut($status, $mode)
Return label of a status.
setBilled()
Classify the shipping as invoiced (used for example by trigger when WORKFLOW_SHIPPING_CLASSIFY_BILLED...
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
getTooltipContentArray($params)
getTooltipContentArray
setDeliveryDate($user, $delivery_date)
Set the planned delivery date.
getKanbanView($option='', $arraydata=null)
Return clickable link of object (with eventually picto)
setShippingDate($user, $shipping_date)
Set the shipping date.
const STATUS_DRAFT
Draft status.
const STATUS_CANCELED
Canceled status.
getLibStatut($mode=0)
Return status label.
set_date_livraison($user, $delivery_date)
Set delivery date.
initAsSpecimen()
Initialise an instance with random values.
getNextNumRef($soc)
Return next expedition ref.
const STATUS_CLOSED
Closed status -> parcel was received by customer / end of process prev status : validated or shipment...
const STATUS_VALIDATED
Validated status -> parcel is ready to be sent prev status : draft next status : closed or shipment_i...
create_line_batch($line_ext, $array_options=[])
Create the detail of the expedition line.
manageStockMvtOnEvt($user, $labelmovement='ShipmentClassifyClosedInDolibarr')
Manage Stock MVt onb Close or valid Shipment.
valid($user, $notrigger=0)
Validate object and update stock if option enabled.
update($user=null, $notrigger=0)
Update database.
cancel($notrigger=0, $also_update_stock=false)
Cancel shipment.
fetch_delivery_methods()
Fetch deliveries method and return an array.
fetch($id, $ref='', $ref_ext='', $notused='')
Get object and lines from database.
reOpen()
Classify the shipping as validated/opened.
deleteLine($user, $lineid)
Delete detail line.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
list_delivery_methods($id=0)
Fetch all deliveries method and return an array.
Class to manage lines of shipment.
CRUD class for batch number management within shipment.
Class to manage stock movements.
Class to manage order lines.
Class to manage products or services.
const TYPE_SERVICE
Service.
Manage record for batch number management.
Class to manage third parties objects (customers, suppliers, prospects...)
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
getLibSignedStatus(int $mode=0)
Returns the label for signed status.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0, $level=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
setEntity($currentobject)
Set entity id to use when to create an object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
get_localtax($vatrate, $local, $thirdparty_buyer=null, $thirdparty_seller=null, $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate,...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller=null, $localtaxes_array=[], $progress=100, $multicurrency_tx=1, $pu_devise=0, $multicurrency_code='')
Calculate totals (net, vat, ...) of a line.
$conf db user
Active Directory does not allow anonymous connections.