37 require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
38 require_once DOL_DOCUMENT_ROOT.
"/core/class/commonobjectline.class.php";
39 require_once DOL_DOCUMENT_ROOT.
'/core/class/commonincoterm.class.php';
40 if (!empty($conf->propal->enabled)) {
41 require_once DOL_DOCUMENT_ROOT.
'/comm/propal/class/propal.class.php';
43 if (!empty($conf->commande->enabled)) {
44 require_once DOL_DOCUMENT_ROOT.
'/commande/class/commande.class.php';
46 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expeditionlinebatch.class.php';
59 public $element =
"shipping";
64 public $fk_element =
"fk_expedition";
69 public $table_element =
"expedition";
74 public $table_element_line =
"expeditiondet";
80 public $ismultientitymanaged = 1;
85 public $picto =
'dolly';
117 public $tracking_number;
122 public $tracking_url;
131 public $weight_units;
135 public $height_units;
144 public $date_delivery;
162 public $date_shipping;
167 public $date_creation;
177 public $lines = array();
213 $this->statuts = array();
214 $this->statuts[-1] =
'StatusSendingCanceled';
215 $this->statuts[0] =
'StatusSendingDraft';
216 $this->statuts[1] =
'StatusSendingValidated';
217 $this->statuts[2] =
'StatusSendingProcessed';
220 $this->statutshorts = array();
221 $this->statutshorts[-1] =
'StatusSendingCanceledShort';
222 $this->statutshorts[0] =
'StatusSendingDraftShort';
223 $this->statutshorts[1] =
'StatusSendingValidatedShort';
224 $this->statutshorts[2] =
'StatusSendingProcessedShort';
235 global $langs, $conf;
236 $langs->load(
"sendings");
238 if (!empty($conf->global->EXPEDITION_ADDON_NUMBER)) {
241 $file = $conf->global->EXPEDITION_ADDON_NUMBER.
".php";
242 $classname = $conf->global->EXPEDITION_ADDON_NUMBER;
245 $dirmodels = array_merge(array(
'/'), (array) $conf->modules_parts[
'models']);
247 foreach ($dirmodels as $reldir) {
251 $mybool |= @include_once $dir.$file;
259 $obj =
new $classname();
261 $numref = $obj->getNextValue($soc, $this);
270 print $langs->trans(
"Error").
" ".$langs->trans(
"Error_EXPEDITION_ADDON_NUMBER_NotDefined");
282 public function create($user, $notrigger = 0)
284 global $conf, $hookmanager;
288 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
292 $this->brouillon = 1;
294 if (empty($this->fk_project)) {
295 $this->fk_project = 0;
303 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"expedition (";
306 $sql .=
", ref_customer";
309 $sql .=
", date_creation";
310 $sql .=
", fk_user_author";
311 $sql .=
", date_expedition";
312 $sql .=
", date_delivery";
314 $sql .=
", fk_projet";
315 $sql .=
", fk_address";
316 $sql .=
", fk_shipping_method";
317 $sql .=
", tracking_number";
322 $sql .=
", weight_units";
323 $sql .=
", size_units";
324 $sql .=
", note_private";
325 $sql .=
", note_public";
326 $sql .=
", model_pdf";
327 $sql .=
", fk_incoterms, location_incoterms";
328 $sql .=
") VALUES (";
330 $sql .=
", ".((int) $conf->entity);
331 $sql .=
", ".($this->ref_customer ?
"'".$this->db->escape($this->ref_customer).
"'" :
"null");
332 $sql .=
", ".($this->ref_int ?
"'".$this->db->escape($this->ref_int).
"'" :
"null");
333 $sql .=
", ".($this->ref_ext ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
334 $sql .=
", '".$this->db->idate($now).
"'";
335 $sql .=
", ".((int) $user->id);
336 $sql .=
", ".($this->date_expedition > 0 ?
"'".$this->db->idate($this->date_expedition).
"'" :
"null");
337 $sql .=
", ".($this->date_delivery > 0 ?
"'".$this->db->idate($this->date_delivery).
"'" :
"null");
338 $sql .=
", ".($this->socid > 0 ? ((int) $this->socid) :
"null");
339 $sql .=
", ".($this->fk_project > 0 ? ((int) $this->fk_project) :
"null");
340 $sql .=
", ".($this->fk_delivery_address > 0 ? $this->fk_delivery_address :
"null");
341 $sql .=
", ".($this->shipping_method_id > 0 ? ((int) $this->shipping_method_id) :
"null");
342 $sql .=
", '".$this->db->escape($this->tracking_number).
"'";
343 $sql .=
", ".(is_numeric($this->weight) ? $this->weight :
'NULL');
344 $sql .=
", ".(is_numeric($this->sizeS) ? $this->sizeS :
'NULL');
345 $sql .=
", ".(is_numeric($this->sizeW) ? $this->sizeW :
'NULL');
346 $sql .=
", ".(is_numeric($this->sizeH) ? $this->sizeH :
'NULL');
347 $sql .=
", ".($this->weight_units !=
'' ? (int) $this->weight_units :
'NULL');
348 $sql .=
", ".($this->size_units !=
'' ? (int) $this->size_units :
'NULL');
349 $sql .=
", ".(!empty($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null");
350 $sql .=
", ".(!empty($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null");
351 $sql .=
", ".(!empty($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null");
352 $sql .=
", ".(int) $this->fk_incoterms;
353 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
356 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
359 $this->
id = $this->
db->last_insert_id(MAIN_DB_PREFIX.
"expedition");
361 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
362 $sql .=
" SET ref = '(PROV".$this->id.
")'";
363 $sql .=
" WHERE rowid = ".((int) $this->
id);
365 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
366 if ($this->
db->query($sql)) {
368 $num = count($this->lines);
369 for ($i = 0; $i < $num; $i++) {
370 if (empty($this->lines[$i]->product_type) || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
371 if (!isset($this->lines[$i]->detail_batch)) {
372 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) {
376 if ($this->
create_line_batch($this->lines[$i], $this->lines[$i]->array_options) <= 0) {
383 if (!$error && $this->
id && $this->origin_id) {
398 if (!$error && !$notrigger) {
400 $result = $this->
call_trigger(
'SHIPPING_CREATE', $user);
410 foreach ($this->errors as $errmsg) {
411 dol_syslog(get_class($this).
"::create ".$errmsg, LOG_ERR);
412 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
414 $this->
db->rollback();
419 $this->
db->rollback();
424 $this->error = $this->
db->lasterror().
" - sql=$sql";
425 $this->
db->rollback();
430 $this->error = $this->
db->error().
" - sql=$sql";
431 $this->
db->rollback();
447 public function create_line($entrepot_id, $origin_line_id, $qty, $rang = 0, $array_options =
null)
453 $expeditionline->fk_expedition = $this->id;
454 $expeditionline->entrepot_id = $entrepot_id;
455 $expeditionline->fk_origin_line = $origin_line_id;
456 $expeditionline->qty = $qty;
457 $expeditionline->rang = $rang;
458 $expeditionline->array_options = $array_options;
460 if (($lineId = $expeditionline->insert($user)) < 0) {
461 $this->errors[] = $expeditionline->error;
479 $stockLocationQty = array();
481 $tab = $line_ext->detail_batch;
483 foreach ($tab as $detbatch) {
484 if ($detbatch->entrepot_id) {
485 $stockLocationQty[$detbatch->entrepot_id] += $detbatch->qty;
489 foreach ($stockLocationQty as $stockLocation => $qty) {
490 $line_id = $this->
create_line($stockLocation, $line_ext->origin_line_id, $qty, $line_ext->rang, $array_options);
495 foreach ($tab as $detbatch) {
496 if ($detbatch->entrepot_id == $stockLocation) {
497 if (!($detbatch->create($line_id) > 0)) {
521 public function fetch($id, $ref =
'', $ref_ext =
'', $notused =
'')
526 if (empty($id) && empty($ref) && empty($ref_ext)) {
530 $sql =
"SELECT e.rowid, e.entity, e.ref, e.fk_soc as socid, e.date_creation, e.ref_customer, e.ref_ext, e.ref_int, e.fk_user_author, e.fk_statut, e.fk_projet as fk_project, e.billed";
531 $sql .=
", e.date_valid";
532 $sql .=
", e.weight, e.weight_units, e.size, e.size_units, e.width, e.height";
533 $sql .=
", e.date_expedition as date_expedition, e.model_pdf, e.fk_address, e.date_delivery";
534 $sql .=
", e.fk_shipping_method, e.tracking_number";
535 $sql .=
", e.note_private, e.note_public";
536 $sql .=
', e.fk_incoterms, e.location_incoterms';
537 $sql .=
', i.libelle as label_incoterms';
538 $sql .=
', s.libelle as shipping_method';
539 $sql .=
", el.fk_source as origin_id, el.sourcetype as origin";
540 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expedition as e";
541 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"element_element as el ON el.fk_target = e.rowid AND el.targettype = '".$this->
db->escape($this->element).
"'";
542 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON e.fk_incoterms = i.rowid';
543 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_shipment_mode as s ON e.fk_shipping_method = s.rowid';
544 $sql .=
" WHERE e.entity IN (".getEntity(
'expedition').
")";
546 $sql .=
" AND e.rowid = ".((int) $id);
549 $sql .=
" AND e.ref='".$this->db->escape($ref).
"'";
552 $sql .=
" AND e.ref_ext='".$this->db->escape($ref_ext).
"'";
555 $sql .=
" AND e.ref_int='".$this->db->escape($notused).
"'";
558 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
559 $result = $this->
db->query($sql);
561 if ($this->
db->num_rows($result)) {
562 $obj = $this->
db->fetch_object($result);
564 $this->
id = $obj->rowid;
565 $this->entity = $obj->entity;
566 $this->
ref = $obj->ref;
567 $this->socid = $obj->socid;
568 $this->ref_customer = $obj->ref_customer;
569 $this->ref_ext = $obj->ref_ext;
570 $this->ref_int = $obj->ref_int;
571 $this->statut = $obj->fk_statut;
572 $this->user_author_id = $obj->fk_user_author;
573 $this->date_creation = $this->
db->jdate($obj->date_creation);
574 $this->date_valid = $this->
db->jdate($obj->date_valid);
575 $this->date = $this->
db->jdate($obj->date_expedition);
576 $this->date_expedition = $this->
db->jdate($obj->date_expedition);
577 $this->date_shipping = $this->
db->jdate($obj->date_expedition);
578 $this->date_delivery = $this->
db->jdate($obj->date_delivery);
579 $this->fk_delivery_address = $obj->fk_address;
580 $this->model_pdf = $obj->model_pdf;
581 $this->modelpdf = $obj->model_pdf;
582 $this->shipping_method_id = $obj->fk_shipping_method;
583 $this->shipping_method = $obj->shipping_method;
584 $this->tracking_number = $obj->tracking_number;
585 $this->origin = ($obj->origin ? $obj->origin :
'commande');
586 $this->origin_id = $obj->origin_id;
587 $this->billed = $obj->billed;
588 $this->fk_project = $obj->fk_project;
590 $this->trueWeight = $obj->weight;
591 $this->weight_units = $obj->weight_units;
593 $this->trueWidth = $obj->width;
594 $this->width_units = $obj->size_units;
595 $this->trueHeight = $obj->height;
596 $this->height_units = $obj->size_units;
597 $this->trueDepth = $obj->size;
598 $this->depth_units = $obj->size_units;
600 $this->note_public = $obj->note_public;
601 $this->note_private = $obj->note_private;
604 $this->trueSize = $obj->size.
"x".$obj->width.
"x".$obj->height;
605 $this->size_units = $obj->size_units;
608 $this->fk_incoterms = $obj->fk_incoterms;
609 $this->location_incoterms = $obj->location_incoterms;
610 $this->label_incoterms = $obj->label_incoterms;
612 $this->
db->free($result);
614 if ($this->statut == self::STATUS_DRAFT) {
615 $this->brouillon = 1;
628 if (!empty($conf->multicurrency->enabled)) {
629 if (!empty($this->multicurrency_code)) {
630 $this->multicurrency_code = $this->thirdparty->multicurrency_code;
632 if (!empty($conf->global->MULTICURRENCY_USE_ORIGIN_TX) && !empty($this->thirdparty->multicurrency_tx)) {
633 $this->multicurrency_tx = $this->thirdparty->multicurrency_tx;
647 dol_syslog(get_class($this).
'::Fetch no expedition found', LOG_ERR);
648 $this->error =
'Delivery with id '.$id.
' not found';
652 $this->error = $this->
db->error();
664 public function valid($user, $notrigger = 0)
666 global $conf, $langs;
668 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
674 dol_syslog(get_class($this).
"::valid not in draft status", LOG_WARNING);
678 if (!((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->expedition->creer))
679 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->expedition->shipping_advance->validate)))) {
680 $this->error =
'Permission denied';
681 dol_syslog(get_class($this).
"::valid ".$this->error, LOG_ERR);
691 $soc->fetch($this->socid);
694 $result = $soc->set_as_client();
697 if (!$error && (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref))) {
700 $numref =
"EXP".$this->id;
707 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition SET";
708 $sql .=
" ref='".$this->db->escape($numref).
"'";
709 $sql .=
", fk_statut = 1";
710 $sql .=
", date_valid = '".$this->db->idate($now).
"'";
711 $sql .=
", fk_user_valid = ".$user->id;
712 $sql .=
" WHERE rowid = ".((int) $this->
id);
714 dol_syslog(get_class($this).
"::valid update expedition", LOG_DEBUG);
717 $this->error = $this->
db->lasterror();
722 if (!$error && !empty($conf->stock->enabled) && !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)) {
723 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
725 $langs->load(
"agenda");
728 $sql =
"SELECT cd.fk_product, cd.subprice,";
729 $sql .=
" ed.rowid, ed.qty, ed.fk_entrepot,";
730 $sql .=
" edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
731 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commandedet as cd,";
732 $sql .=
" ".MAIN_DB_PREFIX.
"expeditiondet as ed";
733 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
734 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
735 $sql .=
" AND cd.rowid = ed.fk_origin_line";
737 dol_syslog(get_class($this).
"::valid select details", LOG_DEBUG);
741 for ($i = 0; $i < $cpt; $i++) {
742 $obj = $this->
db->fetch_object(
$resql);
743 if (empty($obj->edbrowid)) {
751 dol_syslog(get_class($this).
"::valid movement index ".$i.
" ed.rowid=".$obj->rowid.
" edb.rowid=".$obj->edbrowid);
756 $mouvS->setOrigin($this->element, $this->
id);
758 if (empty($obj->edbrowid)) {
762 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans(
"ShipmentValidatedInDolibarr", $numref),
'',
'',
'',
'', 0,
'', 1);
766 $this->error = $mouvS->error;
767 $this->errors = array_merge($this->errors, $mouvS->errors);
775 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans(
"ShipmentValidatedInDolibarr", $numref),
'', $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, $obj->fk_origin_stock,
'', 1);
778 $this->error = $mouvS->error;
779 $this->errors = array_merge($this->errors, $mouvS->errors);
787 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"product_stock WHERE reel = 0 AND rowid NOT IN (SELECT fk_product_stock FROM ".MAIN_DB_PREFIX.
"product_batch as pb)";
791 $this->
db->rollback();
792 $this->error = $this->
db->error();
803 if (!$error && !$notrigger) {
805 $result = $this->
call_trigger(
'SHIPPING_VALIDATE', $user);
813 $this->oldref = $this->ref;
816 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
818 $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).
"'";
819 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'expedition/sending/".$this->
db->escape($this->
ref).
"' and entity = ".((int) $conf->entity);
822 $error++; $this->error = $this->
db->lasterror();
828 $dirsource = $conf->expedition->dir_output.
'/sending/'.$oldref;
829 $dirdest = $conf->expedition->dir_output.
'/sending/'.$newref;
830 if (!$error && file_exists($dirsource)) {
831 dol_syslog(get_class($this).
"::valid rename dir ".$dirsource.
" into ".$dirdest);
833 if (@rename($dirsource, $dirdest)) {
836 $listoffiles =
dol_dir_list($conf->expedition->dir_output.
'/sending/'.$newref,
'files', 1,
'^'.preg_quote($oldref,
'/'));
837 foreach ($listoffiles as $fileentry) {
838 $dirsource = $fileentry[
'name'];
839 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
840 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
841 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
842 @rename($dirsource, $dirdest);
851 $this->
ref = $numref;
859 $this->
db->rollback();
877 if ($conf->delivery_note->enabled) {
878 if ($this->statut == self::STATUS_VALIDATED || $this->statut == self::STATUS_CLOSED) {
880 include_once DOL_DOCUMENT_ROOT.
'/delivery/class/delivery.class.php';
882 $result = $delivery->create_from_sending($user, $this->
id);
886 $this->error = $delivery->error;
909 public function addline($entrepot_id, $id, $qty, $array_options = 0)
911 global $conf, $langs;
913 $num = count($this->lines);
916 $line->entrepot_id = $entrepot_id;
917 $line->origin_line_id = $id;
918 $line->fk_origin_line = $id;
922 $orderline->fetch($id);
925 $line->rang = $orderline->rang;
926 $line->product_type = $orderline->product_type;
928 if (!empty($conf->stock->enabled) && !empty($orderline->fk_product)) {
929 $fk_product = $orderline->fk_product;
931 if (!($entrepot_id > 0) && empty($conf->global->STOCK_WAREHOUSE_NOT_REQUIRED_FOR_SHIPMENTS)) {
932 $langs->load(
"errors");
933 $this->error = $langs->trans(
"ErrorWarehouseRequiredIntoShipmentLine");
937 if (!empty($conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT)) {
939 $product->fetch($fk_product);
942 if ($entrepot_id > 0) {
943 $product->load_stock(
'warehouseopen');
944 $product_stock = $product->stock_warehouse[$entrepot_id]->real;
946 $product_stock = $product->stock_reel;
949 $product_type = $product->type;
950 if ($product_type == 0 || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
951 $isavirtualproduct = ($product->hasFatherOrChild(1) > 0);
953 if (!$isavirtualproduct || empty($conf->global->PRODUIT_SOUSPRODUITS) || ($isavirtualproduct && empty($conf->global->STOCK_EXCLUDE_VIRTUAL_PRODUCTS))) {
954 if ($product_stock < $qty) {
955 $langs->load(
"errors");
956 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnShipment', $product->ref);
957 $this->errorhidden =
'ErrorStockIsNotEnoughToAddProductOnShipment';
959 $this->
db->rollback();
968 if (!empty($conf->productbatch->enabled) && !empty($orderline->fk_product) && !empty($orderline->product_tobatch)) {
969 $this->error =
'ADDLINE_WAS_CALLED_INSTEAD_OF_ADDLINEBATCH';
974 if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options) > 0) {
975 $line->array_options = $array_options;
978 $this->lines[$num] = $line;
994 global $conf, $langs;
996 $num = count($this->lines);
997 if ($dbatch[
'qty'] > 0) {
1000 foreach ($dbatch[
'detail'] as $key => $value) {
1001 if ($value[
'q'] > 0) {
1007 $ret = $linebatch->fetchFromStock($value[
'id_batch']);
1009 $this->error = $linebatch->error;
1012 $linebatch->qty = $value[
'q'];
1013 $tab[] = $linebatch;
1015 if ($conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT) {
1016 require_once DOL_DOCUMENT_ROOT.
'/product/class/productbatch.class.php';
1018 $prod_batch->fetch($value[
'id_batch']);
1020 if ($prod_batch->qty < $linebatch->qty) {
1021 $langs->load(
"errors");
1022 $this->errors[] = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnShipment', $prod_batch->fk_product);
1023 dol_syslog(get_class($this).
"::addline_batch error=Product ".$prod_batch->batch.
": ".$this->errorsToString(), LOG_ERR);
1024 $this->
db->rollback();
1032 $line->entrepot_id = $linebatch->entrepot_id;
1033 $line->origin_line_id = $dbatch[
'ix_l'];
1034 $line->fk_origin_line = $dbatch[
'ix_l'];
1035 $line->qty = $dbatch[
'qty'];
1036 $line->detail_batch = $tab;
1039 if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options) > 0) {
1040 $line->array_options = $array_options;
1044 $this->lines[$num] = $line;
1056 public function update($user =
null, $notrigger = 0)
1063 if (isset($this->
ref)) {
1064 $this->
ref = trim($this->
ref);
1066 if (isset($this->entity)) {
1067 $this->entity = (int) $this->entity;
1069 if (isset($this->ref_customer)) {
1070 $this->ref_customer = trim($this->ref_customer);
1072 if (isset($this->socid)) {
1073 $this->socid = (int) $this->socid;
1075 if (isset($this->fk_user_author)) {
1076 $this->fk_user_author = (int) $this->fk_user_author;
1078 if (isset($this->fk_user_valid)) {
1079 $this->fk_user_valid = (int) $this->fk_user_valid;
1081 if (isset($this->fk_delivery_address)) {
1082 $this->fk_delivery_address = (int) $this->fk_delivery_address;
1084 if (isset($this->shipping_method_id)) {
1085 $this->shipping_method_id = (int) $this->shipping_method_id;
1087 if (isset($this->tracking_number)) {
1088 $this->tracking_number = trim($this->tracking_number);
1090 if (isset($this->statut)) {
1091 $this->statut = (int) $this->statut;
1093 if (isset($this->trueDepth)) {
1094 $this->trueDepth = trim($this->trueDepth);
1096 if (isset($this->trueWidth)) {
1097 $this->trueWidth = trim($this->trueWidth);
1099 if (isset($this->trueHeight)) {
1100 $this->trueHeight = trim($this->trueHeight);
1102 if (isset($this->size_units)) {
1103 $this->size_units = trim($this->size_units);
1105 if (isset($this->weight_units)) {
1106 $this->weight_units = trim($this->weight_units);
1108 if (isset($this->trueWeight)) {
1109 $this->weight = trim($this->trueWeight);
1111 if (isset($this->note_private)) {
1112 $this->note_private = trim($this->note_private);
1114 if (isset($this->note_public)) {
1115 $this->note_public = trim($this->note_public);
1117 if (isset($this->model_pdf)) {
1118 $this->model_pdf = trim($this->model_pdf);
1127 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition SET";
1129 $sql .=
" ref=".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
1130 $sql .=
" ref_ext=".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
1131 $sql .=
" ref_customer=".(isset($this->ref_customer) ?
"'".$this->db->escape($this->ref_customer).
"'" :
"null").
",";
1132 $sql .=
" fk_soc=".(isset($this->socid) ? $this->socid :
"null").
",";
1133 $sql .=
" date_creation=".(dol_strlen($this->date_creation) != 0 ?
"'".$this->db->idate($this->date_creation).
"'" :
'null').
",";
1134 $sql .=
" fk_user_author=".(isset($this->fk_user_author) ? $this->fk_user_author :
"null").
",";
1135 $sql .=
" date_valid=".(dol_strlen($this->date_valid) != 0 ?
"'".$this->db->idate($this->date_valid).
"'" :
'null').
",";
1136 $sql .=
" fk_user_valid=".(isset($this->fk_user_valid) ? $this->fk_user_valid :
"null").
",";
1137 $sql .=
" date_expedition=".(dol_strlen($this->date_expedition) != 0 ?
"'".$this->db->idate($this->date_expedition).
"'" :
'null').
",";
1138 $sql .=
" date_delivery=".(dol_strlen($this->date_delivery) != 0 ?
"'".$this->db->idate($this->date_delivery).
"'" :
'null').
",";
1139 $sql .=
" fk_address=".(isset($this->fk_delivery_address) ? $this->fk_delivery_address :
"null").
",";
1140 $sql .=
" fk_shipping_method=".((isset($this->shipping_method_id) && $this->shipping_method_id > 0) ? $this->shipping_method_id :
"null").
",";
1141 $sql .=
" tracking_number=".(isset($this->tracking_number) ?
"'".$this->db->escape($this->tracking_number).
"'" :
"null").
",";
1142 $sql .=
" fk_statut=".(isset($this->statut) ? $this->statut :
"null").
",";
1143 $sql .=
" fk_projet=".(isset($this->fk_project) ? $this->fk_project :
"null").
",";
1144 $sql .=
" height=".(($this->trueHeight !=
'') ? $this->trueHeight :
"null").
",";
1145 $sql .=
" width=".(($this->trueWidth !=
'') ? $this->trueWidth :
"null").
",";
1146 $sql .=
" size_units=".(isset($this->size_units) ? $this->size_units :
"null").
",";
1147 $sql .=
" size=".(($this->trueDepth !=
'') ? $this->trueDepth :
"null").
",";
1148 $sql .=
" weight_units=".(isset($this->weight_units) ? $this->weight_units :
"null").
",";
1149 $sql .=
" weight=".(($this->trueWeight !=
'') ? $this->trueWeight :
"null").
",";
1150 $sql .=
" note_private=".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
1151 $sql .=
" note_public=".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
1152 $sql .=
" model_pdf=".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
1153 $sql .=
" entity=".$conf->entity;
1155 $sql .=
" WHERE rowid=".((int) $this->
id);
1159 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1162 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
1165 if (!$error && !$notrigger) {
1167 $result = $this->
call_trigger(
'SHIPPING_MODIFY', $user);
1176 foreach ($this->errors as $errmsg) {
1177 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
1178 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1180 $this->
db->rollback();
1183 $this->
db->commit();
1196 public function cancel($notrigger = 0, $also_update_stock =
false)
1198 global $conf, $langs, $user;
1200 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1209 if (count($this->linkedObjectsIds) > 0) {
1210 $this->error =
'ErrorThereIsSomeDeliveries';
1214 if (!$error && !$notrigger) {
1216 $result = $this->
call_trigger(
'SHIPPING_CANCEL', $user);
1224 if (!$error && $conf->stock->enabled &&
1225 (($conf->global->STOCK_CALCULATE_ON_SHIPMENT && $this->statut > self::STATUS_DRAFT) ||
1226 ($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE && $this->statut == self::STATUS_CLOSED && $also_update_stock))) {
1227 require_once DOL_DOCUMENT_ROOT.
"/product/stock/class/mouvementstock.class.php";
1229 $langs->load(
"agenda");
1232 $sql =
"SELECT cd.fk_product, cd.subprice, ed.qty, ed.fk_entrepot, ed.rowid as expeditiondet_id";
1233 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commandedet as cd,";
1234 $sql .=
" ".MAIN_DB_PREFIX.
"expeditiondet as ed";
1235 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
1236 $sql .=
" AND cd.rowid = ed.fk_origin_line";
1238 dol_syslog(get_class($this).
"::delete select details", LOG_DEBUG);
1241 $cpt = $this->
db->num_rows(
$resql);
1245 for ($i = 0; $i < $cpt; $i++) {
1246 dol_syslog(get_class($this).
"::delete movement index ".$i);
1247 $obj = $this->
db->fetch_object(
$resql);
1251 $mouvS->origin =
null;
1255 $lotArray = $shipmentlinebatch->fetchAll($obj->expeditiondet_id);
1256 if (!is_array($lotArray)) {
1258 $this->errors[] =
"Error ".$this->db->lasterror();
1262 if (empty($lotArray)) {
1266 $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $obj->qty, 0, $langs->trans(
"ShipmentCanceledInDolibarr", $this->ref));
1269 $this->errors = array_merge($this->errors, $mouvS->errors);
1275 foreach ($lotArray as $lot) {
1276 $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $lot->qty, 0, $langs->trans(
"ShipmentCanceledInDolibarr", $this->ref), $lot->eatby, $lot->sellby, $lot->batch);
1279 $this->errors = array_merge($this->errors, $mouvS->errors);
1289 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
1294 if (!$error && $conf->productbatch->enabled) {
1296 if ($shipmentlinebatch->deleteFromShipment($this->id) < 0) {
1297 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
1303 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"expeditiondet";
1304 $sql .=
" WHERE fk_expedition = ".((int) $this->
id);
1306 if ($this->
db->query($sql)) {
1315 $sql =
"SELECT rowid FROM ".MAIN_DB_PREFIX.
"expedition";
1316 $sql .=
" WHERE rowid = ".((int) $this->
id);
1318 if ($this->
db->query($sql)) {
1319 if (!empty($this->origin) && $this->origin_id > 0) {
1321 $origin = $this->origin;
1324 $this->$origin->loadExpeditions();
1326 if (count($this->$origin->expeditions) <= 0) {
1333 $this->
db->commit();
1337 if (!empty($conf->expedition->dir_output)) {
1338 $dir = $conf->expedition->dir_output.
'/sending/'.$ref;
1339 $file = $dir.
'/'.$ref.
'.pdf';
1340 if (file_exists($file)) {
1345 if (file_exists($dir)) {
1347 $this->error = $langs->trans(
"ErrorCanNotDeleteDir", $dir);
1355 $this->
db->rollback();
1359 $this->error = $this->
db->lasterror().
" - sql=$sql";
1360 $this->
db->rollback();
1364 $this->error = $this->
db->lasterror().
" - sql=$sql";
1365 $this->
db->rollback();
1369 $this->error = $this->
db->lasterror().
" - sql=$sql";
1370 $this->
db->rollback();
1374 $this->
db->rollback();
1387 public function delete($notrigger = 0, $also_update_stock =
false)
1389 global $conf, $langs, $user;
1391 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1400 if (count($this->linkedObjectsIds) > 0) {
1401 $this->error =
'ErrorThereIsSomeDeliveries';
1405 if (!$error && !$notrigger) {
1407 $result = $this->
call_trigger(
'SHIPPING_DELETE', $user);
1415 if (!$error && $conf->stock->enabled &&
1416 (($conf->global->STOCK_CALCULATE_ON_SHIPMENT && $this->statut > self::STATUS_DRAFT) ||
1417 ($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE && $this->statut == self::STATUS_CLOSED && $also_update_stock))) {
1418 require_once DOL_DOCUMENT_ROOT.
"/product/stock/class/mouvementstock.class.php";
1420 $langs->load(
"agenda");
1426 $sql =
"SELECT cd.fk_product, cd.subprice, ed.qty, ed.fk_entrepot, ed.rowid as expeditiondet_id";
1427 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commandedet as cd,";
1428 $sql .=
" ".MAIN_DB_PREFIX.
"expeditiondet as ed";
1429 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
1430 $sql .=
" AND cd.rowid = ed.fk_origin_line";
1432 dol_syslog(get_class($this).
"::delete select details", LOG_DEBUG);
1435 $cpt = $this->
db->num_rows(
$resql);
1436 for ($i = 0; $i < $cpt; $i++) {
1437 dol_syslog(get_class($this).
"::delete movement index ".$i);
1438 $obj = $this->
db->fetch_object(
$resql);
1442 $mouvS->origin =
null;
1444 $lotArray = $shipmentlinebatch->fetchAll($obj->expeditiondet_id);
1445 if (!is_array($lotArray)) {
1446 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
1448 if (empty($lotArray)) {
1452 $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $obj->qty, 0, $langs->trans(
"ShipmentDeletedInDolibarr", $this->ref));
1455 $this->errors = array_merge($this->errors, $mouvS->errors);
1461 foreach ($lotArray as $lot) {
1462 $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $lot->qty, 0, $langs->trans(
"ShipmentDeletedInDolibarr", $this->ref), $lot->eatby, $lot->sellby, $lot->batch);
1465 $this->errors = array_merge($this->errors, $mouvS->errors);
1475 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
1482 if ($shipmentlinebatch->deleteFromShipment($this->id) < 0) {
1483 $error++; $this->errors[] =
"Error ".$this->db->lasterror();
1488 $main = MAIN_DB_PREFIX.
'expeditiondet';
1489 $ef = $main.
"_extrafields";
1490 $sqlef =
"DELETE FROM $ef WHERE fk_object IN (SELECT rowid FROM $main WHERE fk_expedition = ".((int) $this->
id).
")";
1492 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"expeditiondet";
1493 $sql .=
" WHERE fk_expedition = ".((int) $this->
id);
1495 if ($this->
db->query($sqlef) && $this->
db->query($sql)) {
1509 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"expedition";
1510 $sql .=
" WHERE rowid = ".((int) $this->
id);
1512 if ($this->
db->query($sql)) {
1513 if (!empty($this->origin) && $this->origin_id > 0) {
1515 $origin = $this->origin;
1518 $this->$origin->loadExpeditions();
1520 if (count($this->$origin->expeditions) <= 0) {
1527 $this->
db->commit();
1534 if (!empty($conf->expedition->dir_output)) {
1535 $dir = $conf->expedition->dir_output.
'/sending/'.$ref;
1536 $file = $dir.
'/'.$ref.
'.pdf';
1537 if (file_exists($file)) {
1542 if (file_exists($dir)) {
1544 $this->error = $langs->trans(
"ErrorCanNotDeleteDir", $dir);
1552 $this->
db->rollback();
1556 $this->error = $this->
db->lasterror().
" - sql=$sql";
1557 $this->
db->rollback();
1561 $this->error = $this->
db->lasterror().
" - sql=$sql";
1562 $this->
db->rollback();
1566 $this->error = $this->
db->lasterror().
" - sql=$sql";
1567 $this->
db->rollback();
1571 $this->
db->rollback();
1585 global $conf, $mysoc;
1587 $this->lines = array();
1592 $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";
1593 $sql .=
", cd.total_ht, cd.total_localtax1, cd.total_localtax2, cd.total_ttc, cd.total_tva";
1594 $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";
1595 $sql .=
", cd.fk_multicurrency, cd.multicurrency_code, cd.multicurrency_subprice, cd.multicurrency_total_ht, cd.multicurrency_total_tva, cd.multicurrency_total_ttc, cd.rang";
1596 $sql .=
", ed.rowid as line_id, ed.qty as qty_shipped, ed.fk_origin_line, ed.fk_entrepot";
1597 $sql .=
", p.ref as product_ref, p.label as product_label, p.fk_product_type";
1598 $sql .=
", p.weight, p.weight_units, p.length, p.length_units, p.surface, p.surface_units, p.volume, p.volume_units, p.tosell as product_tosell, p.tobuy as product_tobuy, p.tobatch as product_tobatch";
1599 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expeditiondet as ed, ".MAIN_DB_PREFIX.
"commandedet as cd";
1600 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"product as p ON p.rowid = cd.fk_product";
1601 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
1602 $sql .=
" AND ed.fk_origin_line = cd.rowid";
1603 $sql .=
" ORDER BY cd.rang, ed.fk_origin_line";
1605 dol_syslog(get_class($this).
"::fetch_lines", LOG_DEBUG);
1608 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
1610 $num = $this->
db->num_rows(
$resql);
1615 $this->total_ht = 0;
1616 $this->total_tva = 0;
1617 $this->total_ttc = 0;
1618 $this->total_localtax1 = 0;
1619 $this->total_localtax2 = 0;
1624 $obj = $this->
db->fetch_object(
$resql);
1626 if ($originline > 0 && $originline == $obj->fk_origin_line) {
1627 $line->entrepot_id = 0;
1628 $line->qty_shipped += $obj->qty_shipped;
1631 $line->entrepot_id = $obj->fk_entrepot;
1632 $line->qty_shipped = $obj->qty_shipped;
1635 $detail_entrepot =
new stdClass();
1636 $detail_entrepot->entrepot_id = $obj->fk_entrepot;
1637 $detail_entrepot->qty_shipped = $obj->qty_shipped;
1638 $detail_entrepot->line_id = $obj->line_id;
1639 $line->details_entrepot[] = $detail_entrepot;
1641 $line->line_id = $obj->line_id;
1642 $line->rowid = $obj->line_id;
1643 $line->id = $obj->line_id;
1645 $line->fk_origin =
'orderline';
1646 $line->fk_origin_line = $obj->fk_origin_line;
1647 $line->origin_line_id = $obj->fk_origin_line;
1649 $line->fk_expedition = $this->id;
1651 $line->product_type = $obj->product_type;
1652 $line->fk_product = $obj->fk_product;
1653 $line->fk_product_type = $obj->fk_product_type;
1654 $line->ref = $obj->product_ref;
1655 $line->product_ref = $obj->product_ref;
1656 $line->product_label = $obj->product_label;
1657 $line->libelle = $obj->product_label;
1658 $line->product_tosell = $obj->product_tosell;
1659 $line->product_tobuy = $obj->product_tobuy;
1660 $line->product_tobatch = $obj->product_tobatch;
1661 $line->label = $obj->custom_label;
1662 $line->description = $obj->description;
1663 $line->qty_asked = $obj->qty_asked;
1664 $line->rang = $obj->rang;
1665 $line->weight = $obj->weight;
1666 $line->weight_units = $obj->weight_units;
1667 $line->length = $obj->length;
1668 $line->length_units = $obj->length_units;
1669 $line->surface = $obj->surface;
1670 $line->surface_units = $obj->surface_units;
1671 $line->volume = $obj->volume;
1672 $line->volume_units = $obj->volume_units;
1673 $line->fk_unit = $obj->fk_unit;
1675 $line->pa_ht = $obj->pa_ht;
1678 $localtax_array = array(0=>$obj->localtax1_type, 1=>$obj->localtax1_tx, 2=>$obj->localtax2_type, 3=>$obj->localtax2_tx);
1679 $localtax1_tx =
get_localtax($obj->tva_tx, 1, $this->thirdparty);
1680 $localtax2_tx =
get_localtax($obj->tva_tx, 2, $this->thirdparty);
1683 $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);
1684 $line->desc = $obj->description;
1685 $line->qty = $line->qty_shipped;
1686 $line->total_ht = $tabprice[0];
1687 $line->total_localtax1 = $tabprice[9];
1688 $line->total_localtax2 = $tabprice[10];
1689 $line->total_ttc = $tabprice[2];
1690 $line->total_tva = $tabprice[1];
1691 $line->vat_src_code = $obj->vat_src_code;
1692 $line->tva_tx = $obj->tva_tx;
1693 $line->localtax1_tx = $obj->localtax1_tx;
1694 $line->localtax2_tx = $obj->localtax2_tx;
1695 $line->info_bits = $obj->info_bits;
1696 $line->price = $obj->price;
1697 $line->subprice = $obj->subprice;
1698 $line->remise_percent = $obj->remise_percent;
1700 $this->total_ht += $tabprice[0];
1701 $this->total_tva += $tabprice[1];
1702 $this->total_ttc += $tabprice[2];
1703 $this->total_localtax1 += $tabprice[9];
1704 $this->total_localtax2 += $tabprice[10];
1707 $this->fk_multicurrency = $obj->fk_multicurrency;
1708 $this->multicurrency_code = $obj->multicurrency_code;
1709 $this->multicurrency_subprice = $obj->multicurrency_subprice;
1710 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
1711 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
1712 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
1714 if ($originline != $obj->fk_origin_line) {
1715 $line->detail_batch = array();
1719 if (!empty($conf->productbatch->enabled) && $obj->line_id > 0 && $obj->product_tobatch > 0) {
1720 $newdetailbatch = $shipmentlinebatch->fetchAll($obj->line_id, $obj->fk_product);
1722 if (is_array($newdetailbatch)) {
1723 if ($originline != $obj->fk_origin_line) {
1724 $line->detail_batch = $newdetailbatch;
1726 $line->detail_batch = array_merge($line->detail_batch, $newdetailbatch);
1731 $line->fetch_optionals();
1733 if ($originline != $obj->fk_origin_line) {
1734 $this->lines[$lineindex] = $line;
1737 $line->total_ht += $tabprice[0];
1738 $line->total_localtax1 += $tabprice[9];
1739 $line->total_localtax2 += $tabprice[10];
1740 $line->total_ttc += $tabprice[2];
1741 $line->total_tva += $tabprice[1];
1745 $originline = $obj->fk_origin_line;
1750 $this->error = $this->
db->error();
1766 if ($this->statut == self::STATUS_DRAFT) {
1772 $line->fetch($lineid);
1774 if ($line->delete($user) > 0) {
1777 $this->
db->commit();
1780 $this->
db->rollback();
1784 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
1801 public function getNomUrl($withpicto = 0, $option =
'', $max = 0, $short = 0, $notooltip = 0, $save_lastsearch_value = -1)
1803 global $langs, $conf, $hookmanager;
1806 $label =
'<u>'.$langs->trans(
"Shipment").
'</u>';
1807 $label .=
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
1808 $label .=
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.($this->ref_customer ? $this->ref_customer : $this->ref_client);
1810 $url = DOL_URL_ROOT.
'/expedition/card.php?id='.$this->id;
1816 if ($option !==
'nolink') {
1818 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1819 if ($save_lastsearch_value == -1 && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
1820 $add_save_lastsearch_values = 1;
1822 if ($add_save_lastsearch_values) {
1823 $url .=
'&save_lastsearch_values=1';
1828 if (empty($notooltip)) {
1829 if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
1830 $label = $langs->trans(
"Shipment");
1831 $linkclose .=
' alt="'.dol_escape_htmltag($label, 1).
'"';
1833 $linkclose .=
' title="'.dol_escape_htmltag($label, 1).
'"';
1834 $linkclose .=
' class="classfortooltip"';
1837 $linkstart =
'<a href="'.$url.
'"';
1838 $linkstart .= $linkclose.
'>';
1841 $result .= $linkstart;
1843 $result .=
img_object(($notooltip ?
'' : $label), $this->picto, ($notooltip ? (($withpicto != 2) ?
'class="paddingright"' :
'') :
'class="'.(($withpicto != 2) ?
'paddingright ' :
'').
'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
1845 if ($withpicto != 2) {
1846 $result .= $this->ref;
1848 $result .= $linkend;
1850 $hookmanager->initHooks(array($this->element .
'dao'));
1851 $parameters = array(
'id'=>$this->
id,
'getnomurl' => &$result);
1852 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
1854 $result = $hookmanager->resPrint;
1856 $result .= $hookmanager->resPrint;
1869 return $this->
LibStatut($this->statut, $mode);
1885 $labelStatus = $langs->transnoentitiesnoconv($this->statuts[$status]);
1886 $labelStatusShort = $langs->transnoentitiesnoconv($this->statutshorts[$status]);
1888 $statusType =
'status'.$status;
1889 if ($status == self::STATUS_VALIDATED) {
1890 $statusType =
'status4';
1892 if ($status == self::STATUS_CLOSED) {
1893 $statusType =
'status6';
1895 if ($status == self::STATUS_CANCELED) {
1896 $statusType =
'status9';
1899 return dolGetStatus($labelStatus, $labelStatusShort,
'', $statusType, $mode);
1915 dol_syslog(get_class($this).
"::initAsSpecimen");
1920 $sql =
"SELECT rowid";
1921 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
1922 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
1925 $num_prods = $this->
db->num_rows(
$resql);
1927 while ($i < $num_prods) {
1929 $row = $this->
db->fetch_row(
$resql);
1930 $prodids[$i] = $row[0];
1935 $order->initAsSpecimen();
1939 $this->
ref =
'SPECIMEN';
1940 $this->specimen = 1;
1942 $this->livraison_id = 0;
1944 $this->date_creation = $now;
1945 $this->date_valid = $now;
1946 $this->date_delivery = $now;
1947 $this->date_expedition = $now + 24 * 3600;
1949 $this->entrepot_id = 0;
1950 $this->fk_delivery_address = 0;
1953 $this->commande_id = 0;
1954 $this->commande = $order;
1956 $this->origin_id = 1;
1957 $this->origin =
'commande';
1959 $this->note_private =
'Private note';
1960 $this->note_public =
'Public note';
1964 while ($xnbp < $nbp) {
1966 $line->desc = $langs->trans(
"Description").
" ".$xnbp;
1967 $line->libelle = $langs->trans(
"Description").
" ".$xnbp;
1968 $line->label = $langs->trans(
"Description").
" ".$xnbp;
1970 $line->qty_asked = 5;
1971 $line->qty_shipped = 4;
1972 $line->fk_product = $this->commande->lines[$xnbp]->fk_product;
1974 $this->lines[] = $line;
2003 if ($user->rights->expedition->creer) {
2004 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"expedition";
2005 $sql .=
" SET date_delivery = ".($delivery_date ?
"'".$this->db->idate($delivery_date).
"'" :
'null');
2006 $sql .=
" WHERE rowid = ".((int) $this->
id);
2008 dol_syslog(get_class($this).
"::setDeliveryDate", LOG_DEBUG);
2011 $this->date_delivery = $delivery_date;
2014 $this->error = $this->
db->error();
2032 $this->meths = array();
2034 $sql =
"SELECT em.rowid, em.code, em.libelle as label";
2035 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2036 $sql .=
" WHERE em.active = 1";
2037 $sql .=
" ORDER BY em.libelle ASC";
2041 while ($obj = $this->
db->fetch_object(
$resql)) {
2042 $label = $langs->trans(
'SendingMethod'.$obj->code);
2043 $this->meths[$obj->rowid] = ($label !=
'SendingMethod'.$obj->code ? $label : $obj->label);
2060 $this->listmeths = array();
2063 $sql =
"SELECT em.rowid, em.code, em.libelle as label, em.description, em.tracking, em.active";
2064 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2066 $sql .=
" WHERE em.rowid=".((int) $id);
2071 while ($obj = $this->
db->fetch_object(
$resql)) {
2072 $this->listmeths[$i][
'rowid'] = $obj->rowid;
2073 $this->listmeths[$i][
'code'] = $obj->code;
2074 $label = $langs->trans(
'SendingMethod'.$obj->code);
2075 $this->listmeths[$i][
'libelle'] = ($label !=
'SendingMethod'.$obj->code ? $label : $obj->label);
2076 $this->listmeths[$i][
'description'] = $obj->description;
2077 $this->listmeths[$i][
'tracking'] = $obj->tracking;
2078 $this->listmeths[$i][
'active'] = $obj->active;
2092 if (!empty($this->shipping_method_id)) {
2093 $sql =
"SELECT em.code, em.tracking";
2094 $sql .=
" FROM ".MAIN_DB_PREFIX.
"c_shipment_mode as em";
2095 $sql .=
" WHERE em.rowid = ".((int) $this->shipping_method_id);
2099 if ($obj = $this->
db->fetch_object(
$resql)) {
2100 $tracking = $obj->tracking;
2105 if (!empty($tracking) && !empty($value)) {
2106 $url = str_replace(
'{TRACKID}', $value, $tracking);
2107 $this->tracking_url = sprintf(
'<a target="_blank" rel="noopener noreferrer" href="%s">'.($value ? $value :
'url').
'</a>', $url, $url);
2109 $this->tracking_url = $value;
2120 global $conf, $langs, $user;
2125 if ($this->statut == self::STATUS_CLOSED) {
2132 $sql .=
" WHERE rowid = ".((int) $this->
id).
" AND fk_statut > 0";
2137 if ($this->origin ==
'commande' && $this->origin_id > 0) {
2139 $order->fetch($this->origin_id);
2141 $order->loadExpeditions(self::STATUS_CLOSED);
2143 $shipments_match_order = 1;
2144 foreach ($order->lines as $line) {
2145 $lineid = $line->id;
2147 if (($line->product_type == 0 || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) && $order->expeditions[$lineid] != $qty) {
2148 $shipments_match_order = 0;
2149 $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';
2154 if ($shipments_match_order) {
2155 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');
2157 $order->cloture($user);
2165 if (!$error && !empty($conf->stock->enabled) && !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) {
2166 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
2168 $langs->load(
"agenda");
2172 $sql =
"SELECT cd.fk_product, cd.subprice,";
2173 $sql .=
" ed.rowid, ed.qty, ed.fk_entrepot,";
2175 $sql .=
" edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
2176 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commandedet as cd,";
2177 $sql .=
" ".MAIN_DB_PREFIX.
"expeditiondet as ed";
2178 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
2179 $sql .=
" INNER JOIN ".MAIN_DB_PREFIX.
"expedition as e ON ed.fk_expedition = e.rowid";
2180 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
2181 $sql .=
" AND cd.rowid = ed.fk_origin_line";
2183 dol_syslog(get_class($this).
"::valid select details", LOG_DEBUG);
2186 $cpt = $this->
db->num_rows(
$resql);
2187 for ($i = 0; $i < $cpt; $i++) {
2188 $obj = $this->
db->fetch_object(
$resql);
2189 if (empty($obj->edbrowid)) {
2192 $qty = $obj->edbqty;
2197 dol_syslog(get_class($this).
"::valid movement index ".$i.
" ed.rowid=".$obj->rowid.
" edb.rowid=".$obj->edbrowid);
2200 $mouvS->origin = &$this;
2201 $mouvS->setOrigin($this->element, $this->
id);
2203 if (empty($obj->edbrowid)) {
2207 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans(
"ShipmentClassifyClosedInDolibarr", $obj->ref));
2209 $this->error = $mouvS->error;
2210 $this->errors = $mouvS->errors;
2218 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans(
"ShipmentClassifyClosedInDolibarr", $obj->ref),
'', $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, $obj->fk_origin_stock);
2220 $this->error = $mouvS->error;
2221 $this->errors = $mouvS->errors;
2228 $this->error = $this->
db->lasterror();
2235 $result = $this->
call_trigger(
'SHIPPING_CLOSED', $user);
2246 $this->
db->commit();
2252 $this->
db->rollback();
2268 dol_syslog(get_class($this).
"::set_billed is deprecated, use setBilled instead", LOG_NOTICE);
2284 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'expedition SET fk_statut=2, billed=1';
2285 $sql .=
" WHERE rowid = ".((int) $this->
id).
' AND fk_statut > 0';
2293 $result = $this->
call_trigger(
'SHIPPING_BILLED', $user);
2299 $this->errors[] = $this->
db->lasterror;
2302 if (empty($error)) {
2303 $this->
db->commit();
2308 $this->
db->rollback();
2320 global $conf, $langs, $user;
2325 if ($this->statut == self::STATUS_VALIDATED) {
2331 $oldbilled = $this->billed;
2333 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'expedition SET fk_statut=1';
2334 $sql .=
" WHERE rowid = ".((int) $this->
id).
' AND fk_statut > 0';
2342 if (!$error && !empty($conf->stock->enabled) && !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) {
2343 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
2345 $langs->load(
"agenda");
2349 $sql =
"SELECT cd.fk_product, cd.subprice,";
2350 $sql .=
" ed.rowid, ed.qty, ed.fk_entrepot,";
2351 $sql .=
" edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
2352 $sql .=
" FROM ".MAIN_DB_PREFIX.
"commandedet as cd,";
2353 $sql .=
" ".MAIN_DB_PREFIX.
"expeditiondet as ed";
2354 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
2355 $sql .=
" WHERE ed.fk_expedition = ".((int) $this->
id);
2356 $sql .=
" AND cd.rowid = ed.fk_origin_line";
2358 dol_syslog(get_class($this).
"::valid select details", LOG_DEBUG);
2361 $cpt = $this->
db->num_rows(
$resql);
2362 for ($i = 0; $i < $cpt; $i++) {
2363 $obj = $this->
db->fetch_object(
$resql);
2364 if (empty($obj->edbrowid)) {
2367 $qty = $obj->edbqty;
2372 dol_syslog(get_class($this).
"::reopen expedition movement index ".$i.
" ed.rowid=".$obj->rowid.
" edb.rowid=".$obj->edbrowid);
2376 $mouvS->origin = &$this;
2377 $mouvS->setOrigin($this->element, $this->
id);
2379 if (empty($obj->edbrowid)) {
2383 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans(
"ShipmentUnClassifyCloseddInDolibarr", $numref));
2385 $this->error = $mouvS->error;
2386 $this->errors = $mouvS->errors;
2394 $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans(
"ShipmentUnClassifyCloseddInDolibarr", $numref),
'', $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, $obj->fk_origin_stock);
2396 $this->error = $mouvS->error;
2397 $this->errors = $mouvS->errors;
2404 $this->error = $this->
db->lasterror();
2411 $result = $this->
call_trigger(
'SHIPPING_REOPEN', $user);
2418 $this->errors[] = $this->
db->lasterror();
2422 $this->
db->commit();
2426 $this->billed = $oldbilled;
2427 $this->
db->rollback();
2443 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
2447 $outputlangs->load(
"products");
2452 if (!empty($this->model_pdf)) {
2453 $modele = $this->model_pdf;
2454 } elseif (!empty($this->modelpdf)) {
2455 $modele = $this->modelpdf;
2456 } elseif (!empty($conf->global->EXPEDITION_ADDON_PDF)) {
2457 $modele = $conf->global->EXPEDITION_ADDON_PDF;
2461 $modelpath =
"core/modules/expedition/doc/";
2465 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
2495 public $element =
'expeditiondet';
2500 public $table_element =
'expeditiondet';
2511 public $fk_origin_line;
2516 public $fk_expedition;
2531 public $qty_shipped;
2537 public $detail_batch;
2542 public $entrepot_id;
2559 public $product_ref;
2570 public $product_label;
2582 public $product_desc;
2588 public $product_type = 0;
2599 public $weight_units;
2605 public $length_units;
2611 public $surface_units;
2617 public $volume_units;
2620 public $remise_percent;
2641 public $total_localtax1;
2646 public $total_localtax2;
2667 $sql =
'SELECT ed.rowid, ed.fk_expedition, ed.fk_entrepot, ed.fk_origin_line, ed.qty, ed.rang';
2668 $sql .=
' FROM '.MAIN_DB_PREFIX.$this->table_element.
' as ed';
2669 $sql .=
' WHERE ed.rowid = '.((int) $rowid);
2670 $result = $this->
db->query($sql);
2672 $objp = $this->
db->fetch_object($result);
2673 $this->
id = $objp->rowid;
2674 $this->fk_expedition = $objp->fk_expedition;
2675 $this->entrepot_id = $objp->fk_entrepot;
2676 $this->fk_origin_line = $objp->fk_origin_line;
2677 $this->qty = $objp->qty;
2678 $this->rang = $objp->rang;
2680 $this->
db->free($result);
2684 $this->errors[] = $this->
db->lasterror();
2685 $this->error = $this->
db->lasterror();
2697 public function insert($user, $notrigger = 0)
2699 global $langs, $conf;
2704 if (empty($this->fk_expedition) || empty($this->fk_origin_line) || !is_numeric($this->qty)) {
2705 $this->error =
'ErrorMandatoryParametersNotProvided';
2711 if (empty($this->rang)) {
2716 $ranktouse = $this->rang;
2717 if ($ranktouse == -1) {
2718 $rangmax = $this->
line_max($this->fk_expedition);
2719 $ranktouse = $rangmax + 1;
2722 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"expeditiondet (";
2723 $sql .=
"fk_expedition";
2724 $sql .=
", fk_entrepot";
2725 $sql .=
", fk_origin_line";
2728 $sql .=
") VALUES (";
2729 $sql .= $this->fk_expedition;
2730 $sql .=
", ".(empty($this->entrepot_id) ?
'NULL' : $this->entrepot_id);
2731 $sql .=
", ".((int) $this->fk_origin_line);
2732 $sql .=
", ".price2num($this->qty,
'MS');
2733 $sql .=
", ".((int) $ranktouse);
2736 dol_syslog(get_class($this).
"::insert", LOG_DEBUG);
2739 $this->
id = $this->
db->last_insert_id(MAIN_DB_PREFIX.
"expeditiondet");
2748 if (!$error && !$notrigger) {
2750 $result = $this->
call_trigger(
'LINESHIPPING_INSERT', $user);
2758 foreach ($this->errors as $errmsg) {
2759 dol_syslog(get_class($this).
"::delete ".$errmsg, LOG_ERR);
2760 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2768 $this->
db->rollback();
2771 $this->
db->commit();
2783 public function delete($user =
null, $notrigger = 0)
2793 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"expeditiondet_batch";
2794 $sql .=
" WHERE fk_expeditiondet = ".((int) $this->
id);
2796 if (!$this->
db->query($sql)) {
2797 $this->errors[] = $this->
db->lasterror().
" - sql=$sql";
2802 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"expeditiondet";
2803 $sql .=
" WHERE rowid = ".((int) $this->
id);
2805 if (!$error && $this->
db->query($sql)) {
2810 $this->errors[] = $this->error;
2814 if (!$error && !$notrigger) {
2816 $result = $this->
call_trigger(
'LINESHIPPING_DELETE', $user);
2818 $this->errors[] = $this->error;
2824 $this->errors[] = $this->
db->lasterror().
" - sql=$sql";
2829 $this->
db->commit();
2832 foreach ($this->errors as $errmsg) {
2833 dol_syslog(get_class($this).
"::delete ".$errmsg, LOG_ERR);
2834 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2836 $this->
db->rollback();
2848 public function update($user =
null, $notrigger = 0)
2854 dol_syslog(get_class($this).
"::update id=$this->id, entrepot_id=$this->entrepot_id, product_id=$this->fk_product, qty=$this->qty");
2859 if (empty($this->qty)) {
2866 $expedition_batch_id =
null;
2867 if (is_array($this->detail_batch)) {
2868 if (count($this->detail_batch) > 1) {
2869 dol_syslog(get_class($this).
'::update only possible for one batch', LOG_ERR);
2870 $this->errors[] =
'ErrorBadParameters';
2873 $batch = $this->detail_batch[0]->batch;
2874 $batch_id = $this->detail_batch[0]->fk_origin_stock;
2875 $expedition_batch_id = $this->detail_batch[0]->id;
2876 if ($this->entrepot_id != $this->detail_batch[0]->entrepot_id) {
2877 dol_syslog(get_class($this).
'::update only possible for batch of same warehouse', LOG_ERR);
2878 $this->errors[] =
'ErrorBadParameters';
2881 $qty =
price2num($this->detail_batch[0]->qty);
2883 } elseif (!empty($this->detail_batch)) {
2884 $batch = $this->detail_batch->batch;
2885 $batch_id = $this->detail_batch->fk_origin_stock;
2886 $expedition_batch_id = $this->detail_batch->id;
2887 if ($this->entrepot_id != $this->detail_batch->entrepot_id) {
2888 dol_syslog(get_class($this).
'::update only possible for batch of same warehouse', LOG_ERR);
2889 $this->errors[] =
'ErrorBadParameters';
2892 $qty =
price2num($this->detail_batch->qty);
2896 if (!isset($this->
id) || !isset($this->entrepot_id)) {
2897 dol_syslog(get_class($this).
'::update missing line id and/or warehouse id', LOG_ERR);
2898 $this->errors[] =
'ErrorMandatoryParametersNotProvided';
2905 if (!empty($batch) && $conf->productbatch->enabled) {
2906 dol_syslog(get_class($this).
"::update expedition batch id=$expedition_batch_id, batch_id=$batch_id, batch=$batch");
2908 if (empty($batch_id) || empty($this->fk_product)) {
2909 dol_syslog(get_class($this).
'::update missing fk_origin_stock (batch_id) and/or fk_product', LOG_ERR);
2910 $this->errors[] =
'ErrorMandatoryParametersNotProvided';
2917 if (!$error && ($lotArray = $shipmentlinebatch->fetchAll($this->id)) < 0) {
2918 $this->errors[] = $this->
db->lasterror().
" - ExpeditionLineBatch::fetchAll";
2922 foreach ($lotArray as $lot) {
2923 if ($expedition_batch_id != $lot->id) {
2924 $remainingQty += $lot->qty;
2927 $qty += $remainingQty;
2932 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/productlot.class.php';
2934 if ($lot->fetch(0, $this->fk_product, $batch) < 0) {
2935 $this->errors[] = $lot->errors;
2938 if (!$error && !empty($expedition_batch_id)) {
2940 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"expeditiondet_batch";
2941 $sql .=
" WHERE fk_expeditiondet = ".((int) $this->
id);
2942 $sql .=
" AND rowid = ".((int) $expedition_batch_id);
2944 if (!$this->
db->query($sql)) {
2945 $this->errors[] = $this->
db->lasterror().
" - sql=$sql";
2949 if (!$error && $this->detail_batch->qty > 0) {
2951 if (isset($lot->id)) {
2953 $shipmentLot->batch = $lot->batch;
2954 $shipmentLot->eatby = $lot->eatby;
2955 $shipmentLot->sellby = $lot->sellby;
2956 $shipmentLot->entrepot_id = $this->detail_batch->entrepot_id;
2957 $shipmentLot->qty = $this->detail_batch->qty;
2958 $shipmentLot->fk_origin_stock = $batch_id;
2959 if ($shipmentLot->create($this->id) < 0) {
2960 $this->errors[] = $shipmentLot->errors;
2969 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element.
" SET";
2970 $sql .=
" fk_entrepot = ".($this->entrepot_id > 0 ? $this->entrepot_id :
'null');
2971 $sql .=
" , qty = ".((float)
price2num($qty,
'MS'));
2972 $sql .=
" WHERE rowid = ".((int) $this->
id);
2974 if (!$this->
db->query($sql)) {
2975 $this->errors[] = $this->
db->lasterror().
" - sql=$sql";
2984 $this->errors[] = $this->error;
2990 if (!$error && !$notrigger) {
2992 $result = $this->
call_trigger(
'LINESHIPPING_MODIFY', $user);
2994 $this->errors[] = $this->error;
3000 $this->
db->commit();
3003 foreach ($this->errors as $errmsg) {
3004 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
3005 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3007 $this->
db->rollback();