Passed
Push — master ( 3cffbe...0f9140 )
by Alxarafe
23:50
created
dolibarr/htdocs/expedition/class/expeditionbatch.class.php 1 patch
Indentation   +197 added lines, -197 removed lines patch added patch discarded remove patch
@@ -28,21 +28,21 @@  discard block
 block discarded – undo
28 28
  */
29 29
 class ExpeditionLineBatch extends CommonObject
30 30
 {
31
-	/**
32
-	 * @var string ID to identify managed object
33
-	 */
34
-	public $element='expeditionlignebatch';
35
-
36
-	private static $_table_element='expeditiondet_batch';		//!< Name of table without prefix where object is stored
37
-
38
-	var $sellby;
39
-	var $eatby;
40
-	var $batch;
41
-	var $qty;
42
-	var $dluo_qty; // deprecated, use qty
43
-	var $entrepot_id;
44
-	var $fk_origin_stock;
45
-	var $fk_expeditiondet;
31
+    /**
32
+     * @var string ID to identify managed object
33
+     */
34
+    public $element='expeditionlignebatch';
35
+
36
+    private static $_table_element='expeditiondet_batch';		//!< Name of table without prefix where object is stored
37
+
38
+    var $sellby;
39
+    var $eatby;
40
+    var $batch;
41
+    var $qty;
42
+    var $dluo_qty; // deprecated, use qty
43
+    var $entrepot_id;
44
+    var $fk_origin_stock;
45
+    var $fk_expeditiondet;
46 46
 
47 47
     /**
48 48
      *  Constructor
@@ -54,187 +54,187 @@  discard block
 block discarded – undo
54 54
         $this->db = $db;
55 55
     }
56 56
 
57
-	/**
58
-	 * Fill object based on a product-warehouse-batch's record
59
-	 *
60
-	 * @param	int		$id_stockdluo	Rowid in product_batch table
61
-	 * @return	int      		   	 -1 if KO, 1 if OK
62
-	 */
63
-	function fetchFromStock($id_stockdluo)
64
-	{
65
-		$sql = "SELECT";
66
-		$sql.= " pb.batch,";
67
-		$sql.= " pl.sellby,";
68
-		$sql.= " pl.eatby,";
69
-		$sql.= " ps.fk_entrepot";
70
-
71
-		$sql.= " FROM ".MAIN_DB_PREFIX."product_batch as pb";
72
-		$sql.= " JOIN ".MAIN_DB_PREFIX."product_stock as ps on pb.fk_product_stock=ps.rowid";
73
-		$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX."product_lot as pl on pl.batch = pb.batch AND pl.fk_product = ps.fk_product";
74
-		$sql.= " WHERE pb.rowid = ".(int) $id_stockdluo;
75
-
76
-		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
77
-		$resql=$this->db->query($sql);
78
-		if ($resql)
79
-		{
80
-			if ($this->db->num_rows($resql))
81
-			{
82
-				$obj = $this->db->fetch_object($resql);
83
-
84
-				$this->sellby = $this->db->jdate($obj->sellby);
85
-				$this->eatby = $this->db->jdate($obj->eatby);
86
-				$this->batch = $obj->batch;
87
-				$this->entrepot_id= $obj->fk_entrepot;
88
-				$this->fk_origin_stock=(int) $id_stockdluo;
89
-			}
90
-			$this->db->free($resql);
91
-
92
-			return 1;
93
-		}
94
-		else
95
-		{
96
-			$this->error="Error ".$this->db->lasterror();
97
-			return -1;
98
-		}
99
-	}
100
-
101
-	/**
102
-	 * Create an expeditiondet_batch DB record link to an expedtiondet record
103
-	 *
104
-	 * @param	int		$id_line_expdet		rowid of expedtiondet record
105
-	 * @return	int							<0 if KO, Id of record (>0) if OK
106
-	 */
107
-	function create($id_line_expdet)
108
-	{
109
-		$error = 0;
110
-
111
-		$id_line_expdet = (int) $id_line_expdet;
112
-
113
-		$sql = "INSERT INTO ".MAIN_DB_PREFIX.self::$_table_element." (";
114
-		$sql.= "fk_expeditiondet";
115
-		$sql.= ", sellby";
116
-		$sql.= ", eatby";
117
-		$sql.= ", batch";
118
-		$sql.= ", qty";
119
-		$sql.= ", fk_origin_stock";
120
-		$sql.= ") VALUES (";
121
-		$sql.= $id_line_expdet.",";
122
-		$sql.= " ".(! isset($this->sellby) || dol_strlen($this->sellby)==0?'NULL':("'".$this->db->idate($this->sellby))."'").",";
123
-		$sql.= " ".(! isset($this->eatby) || dol_strlen($this->eatby)==0?'NULL':("'".$this->db->idate($this->eatby))."'").",";
124
-		$sql.= " ".(! isset($this->batch)?'NULL':("'".$this->db->escape($this->batch)."'")).",";
125
-		$sql.= " ".(! isset($this->qty)?((! isset($this->dluo_qty))?'NULL':$this->dluo_qty):$this->qty).","; // dluo_qty deprecated, use qty
126
-		$sql.= " ".(! isset($this->fk_origin_stock)?'NULL':$this->fk_origin_stock);
127
-		$sql.= ")";
128
-
129
-		dol_syslog(__METHOD__, LOG_DEBUG);
130
-		$resql=$this->db->query($sql);
131
-		if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
132
-
133
-		if (! $error)
134
-		{
57
+    /**
58
+     * Fill object based on a product-warehouse-batch's record
59
+     *
60
+     * @param	int		$id_stockdluo	Rowid in product_batch table
61
+     * @return	int      		   	 -1 if KO, 1 if OK
62
+     */
63
+    function fetchFromStock($id_stockdluo)
64
+    {
65
+        $sql = "SELECT";
66
+        $sql.= " pb.batch,";
67
+        $sql.= " pl.sellby,";
68
+        $sql.= " pl.eatby,";
69
+        $sql.= " ps.fk_entrepot";
70
+
71
+        $sql.= " FROM ".MAIN_DB_PREFIX."product_batch as pb";
72
+        $sql.= " JOIN ".MAIN_DB_PREFIX."product_stock as ps on pb.fk_product_stock=ps.rowid";
73
+        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX."product_lot as pl on pl.batch = pb.batch AND pl.fk_product = ps.fk_product";
74
+        $sql.= " WHERE pb.rowid = ".(int) $id_stockdluo;
75
+
76
+        dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
77
+        $resql=$this->db->query($sql);
78
+        if ($resql)
79
+        {
80
+            if ($this->db->num_rows($resql))
81
+            {
82
+                $obj = $this->db->fetch_object($resql);
83
+
84
+                $this->sellby = $this->db->jdate($obj->sellby);
85
+                $this->eatby = $this->db->jdate($obj->eatby);
86
+                $this->batch = $obj->batch;
87
+                $this->entrepot_id= $obj->fk_entrepot;
88
+                $this->fk_origin_stock=(int) $id_stockdluo;
89
+            }
90
+            $this->db->free($resql);
91
+
92
+            return 1;
93
+        }
94
+        else
95
+        {
96
+            $this->error="Error ".$this->db->lasterror();
97
+            return -1;
98
+        }
99
+    }
100
+
101
+    /**
102
+     * Create an expeditiondet_batch DB record link to an expedtiondet record
103
+     *
104
+     * @param	int		$id_line_expdet		rowid of expedtiondet record
105
+     * @return	int							<0 if KO, Id of record (>0) if OK
106
+     */
107
+    function create($id_line_expdet)
108
+    {
109
+        $error = 0;
110
+
111
+        $id_line_expdet = (int) $id_line_expdet;
112
+
113
+        $sql = "INSERT INTO ".MAIN_DB_PREFIX.self::$_table_element." (";
114
+        $sql.= "fk_expeditiondet";
115
+        $sql.= ", sellby";
116
+        $sql.= ", eatby";
117
+        $sql.= ", batch";
118
+        $sql.= ", qty";
119
+        $sql.= ", fk_origin_stock";
120
+        $sql.= ") VALUES (";
121
+        $sql.= $id_line_expdet.",";
122
+        $sql.= " ".(! isset($this->sellby) || dol_strlen($this->sellby)==0?'NULL':("'".$this->db->idate($this->sellby))."'").",";
123
+        $sql.= " ".(! isset($this->eatby) || dol_strlen($this->eatby)==0?'NULL':("'".$this->db->idate($this->eatby))."'").",";
124
+        $sql.= " ".(! isset($this->batch)?'NULL':("'".$this->db->escape($this->batch)."'")).",";
125
+        $sql.= " ".(! isset($this->qty)?((! isset($this->dluo_qty))?'NULL':$this->dluo_qty):$this->qty).","; // dluo_qty deprecated, use qty
126
+        $sql.= " ".(! isset($this->fk_origin_stock)?'NULL':$this->fk_origin_stock);
127
+        $sql.= ")";
128
+
129
+        dol_syslog(__METHOD__, LOG_DEBUG);
130
+        $resql=$this->db->query($sql);
131
+        if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
132
+
133
+        if (! $error)
134
+        {
135 135
             $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.self::$_table_element);
136
-			$this->fk_expeditiondet=$id_line_expdet;
137
-			return $this->id;
138
-		}
139
-		else
140
-		{
141
-			foreach($this->errors as $errmsg)
142
-			{
143
-	            dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
144
-	            $this->error.=($this->error?', '.$errmsg:$errmsg);
145
-			}
146
-			$this->db->rollback();
147
-			return -1*$error;
148
-		}
149
-	}
150
-
151
-	/**
152
-	 * Delete batch record attach to a shipment
153
-	 *
154
-	 * @param	DoliDB	$db				Database object
155
-	 * @param	int		$id_expedition	rowid of shipment
156
-	 * @return 	int						-1 if KO, 1 if OK
157
-	 */
158
-	static function deletefromexp($db,$id_expedition)
159
-	{
160
-		$id_expedition = (int) $id_expedition;
161
-
162
-		$sql="DELETE FROM ".MAIN_DB_PREFIX.self::$_table_element;
163
-		$sql.=" WHERE fk_expeditiondet in (SELECT rowid FROM ".MAIN_DB_PREFIX."expeditiondet WHERE fk_expedition=".$id_expedition.")";
164
-
165
-		dol_syslog(__METHOD__, LOG_DEBUG);
166
-		if ($db->query($sql))
167
-		{
168
-			return 1;
169
-		}
170
-		else
171
-		{
172
-			return -1;
173
-		}
174
-	}
175
-
176
-	/**
177
-	 * Retrieve all batch number detailed information of a shipment line
178
-	 *
179
-	 * @param	DoliDB		$db					Database object
180
-	 * @param	int			$id_line_expdet		id of shipment line
181
-	 * @param	int			$fk_product			If provided, load also detailed information of lot
182
-	 * @return	int|array						-1 if KO, array of ExpeditionLineBatch if OK
183
-	 */
184
-	static function fetchAll($db, $id_line_expdet, $fk_product=0)
185
-	{
186
-		$sql="SELECT";
187
-		$sql.= " eb.rowid,";
188
-		$sql.= " eb.fk_expeditiondet,";
189
-		$sql.= " eb.sellby as oldsellby,";				// deprecated
190
-		$sql.= " eb.eatby as oldeatby,";				// deprecated
191
-		$sql.= " eb.batch,";
192
-		$sql.= " eb.qty,";
193
-		$sql.= " eb.fk_origin_stock";
194
-		if ($fk_product > 0)
195
-		{
196
-			$sql.= ", pl.sellby";
197
-			$sql.= ", pl.eatby";
198
-		}
199
-		$sql.= " FROM ".MAIN_DB_PREFIX.self::$_table_element." as eb";
200
-		if ($fk_product > 0)
201
-		{
202
-			$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_lot as pl ON pl.batch = eb.batch AND pl.fk_product = ".$fk_product;
203
-		}
204
-		$sql.= " WHERE fk_expeditiondet=".(int) $id_line_expdet;
205
-
206
-		dol_syslog(__METHOD__ ."", LOG_DEBUG);
207
-		$resql=$db->query($sql);
208
-		if ($resql)
209
-		{
210
-			$num=$db->num_rows($resql);
211
-			$i=0;
212
-			$ret = array();
213
-			while ($i<$num)
214
-			{
215
-				$tmp=new self($db);
216
-
217
-				$obj = $db->fetch_object($resql);
218
-
219
-				$tmp->sellby = $db->jdate($obj->sellby ? $obj->sellby : $obj->oldsellby);
220
-				$tmp->eatby = $db->jdate($obj->eatby ? $obj->eatby : $obj->oldeatby);
221
-				$tmp->batch = $obj->batch;
222
-				$tmp->id = $obj->rowid;
223
-				$tmp->fk_origin_stock = $obj->fk_origin_stock;
224
-				$tmp->fk_expeditiondet = $obj->fk_expeditiondet;
225
-				$tmp->dluo_qty = $obj->qty; // dluo_qty deprecated, use qty
226
-				$tmp->qty = $obj->qty;
227
-
228
-				$ret[]=$tmp;
229
-				$i++;
230
-			}
231
-			$db->free($resql);
232
-			return $ret;
233
-		}
234
-		else
235
-		{
236
-			dol_print_error($db);
237
-			return -1;
238
-		}
239
-	}
136
+            $this->fk_expeditiondet=$id_line_expdet;
137
+            return $this->id;
138
+        }
139
+        else
140
+        {
141
+            foreach($this->errors as $errmsg)
142
+            {
143
+                dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
144
+                $this->error.=($this->error?', '.$errmsg:$errmsg);
145
+            }
146
+            $this->db->rollback();
147
+            return -1*$error;
148
+        }
149
+    }
150
+
151
+    /**
152
+     * Delete batch record attach to a shipment
153
+     *
154
+     * @param	DoliDB	$db				Database object
155
+     * @param	int		$id_expedition	rowid of shipment
156
+     * @return 	int						-1 if KO, 1 if OK
157
+     */
158
+    static function deletefromexp($db,$id_expedition)
159
+    {
160
+        $id_expedition = (int) $id_expedition;
161
+
162
+        $sql="DELETE FROM ".MAIN_DB_PREFIX.self::$_table_element;
163
+        $sql.=" WHERE fk_expeditiondet in (SELECT rowid FROM ".MAIN_DB_PREFIX."expeditiondet WHERE fk_expedition=".$id_expedition.")";
164
+
165
+        dol_syslog(__METHOD__, LOG_DEBUG);
166
+        if ($db->query($sql))
167
+        {
168
+            return 1;
169
+        }
170
+        else
171
+        {
172
+            return -1;
173
+        }
174
+    }
175
+
176
+    /**
177
+     * Retrieve all batch number detailed information of a shipment line
178
+     *
179
+     * @param	DoliDB		$db					Database object
180
+     * @param	int			$id_line_expdet		id of shipment line
181
+     * @param	int			$fk_product			If provided, load also detailed information of lot
182
+     * @return	int|array						-1 if KO, array of ExpeditionLineBatch if OK
183
+     */
184
+    static function fetchAll($db, $id_line_expdet, $fk_product=0)
185
+    {
186
+        $sql="SELECT";
187
+        $sql.= " eb.rowid,";
188
+        $sql.= " eb.fk_expeditiondet,";
189
+        $sql.= " eb.sellby as oldsellby,";				// deprecated
190
+        $sql.= " eb.eatby as oldeatby,";				// deprecated
191
+        $sql.= " eb.batch,";
192
+        $sql.= " eb.qty,";
193
+        $sql.= " eb.fk_origin_stock";
194
+        if ($fk_product > 0)
195
+        {
196
+            $sql.= ", pl.sellby";
197
+            $sql.= ", pl.eatby";
198
+        }
199
+        $sql.= " FROM ".MAIN_DB_PREFIX.self::$_table_element." as eb";
200
+        if ($fk_product > 0)
201
+        {
202
+            $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_lot as pl ON pl.batch = eb.batch AND pl.fk_product = ".$fk_product;
203
+        }
204
+        $sql.= " WHERE fk_expeditiondet=".(int) $id_line_expdet;
205
+
206
+        dol_syslog(__METHOD__ ."", LOG_DEBUG);
207
+        $resql=$db->query($sql);
208
+        if ($resql)
209
+        {
210
+            $num=$db->num_rows($resql);
211
+            $i=0;
212
+            $ret = array();
213
+            while ($i<$num)
214
+            {
215
+                $tmp=new self($db);
216
+
217
+                $obj = $db->fetch_object($resql);
218
+
219
+                $tmp->sellby = $db->jdate($obj->sellby ? $obj->sellby : $obj->oldsellby);
220
+                $tmp->eatby = $db->jdate($obj->eatby ? $obj->eatby : $obj->oldeatby);
221
+                $tmp->batch = $obj->batch;
222
+                $tmp->id = $obj->rowid;
223
+                $tmp->fk_origin_stock = $obj->fk_origin_stock;
224
+                $tmp->fk_expeditiondet = $obj->fk_expeditiondet;
225
+                $tmp->dluo_qty = $obj->qty; // dluo_qty deprecated, use qty
226
+                $tmp->qty = $obj->qty;
227
+
228
+                $ret[]=$tmp;
229
+                $i++;
230
+            }
231
+            $db->free($resql);
232
+            return $ret;
233
+        }
234
+        else
235
+        {
236
+            dol_print_error($db);
237
+            return -1;
238
+        }
239
+    }
240 240
 }
Please login to merge, or discard this patch.
dolibarr/htdocs/expedition/class/expedition.class.php 1 patch
Indentation   +2658 added lines, -2658 removed lines patch added patch discarded remove patch
@@ -45,2305 +45,2305 @@  discard block
 block discarded – undo
45 45
  */
46 46
 class Expedition extends CommonObject
47 47
 {
48
-	/**
49
-	 * @var string ID to identify managed object
50
-	 */
51
-	public $element="shipping";
52
-
53
-	/**
54
-	 * @var int Field with ID of parent key if this field has a parent
55
-	 */
56
-	public $fk_element="fk_expedition";
57
-
58
-	/**
59
-	 * @var string Name of table without prefix where object is stored
60
-	 */
61
-	public $table_element="expedition";
62
-
63
-	/**
64
-	 * @var int    Name of subtable line
65
-	 */
66
-	public $table_element_line="expeditiondet";
67
-
68
-	/**
69
-	 * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
70
-	 * @var int
71
-	 */
72
-	public $ismultientitymanaged = 1;
73
-
74
-	/**
75
-	 * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
76
-	 */
77
-	public $picto = 'sending';
78
-
79
-	public $socid;
80
-
81
-	/**
82
-	 * @var string Customer ref
83
-	 */
84
-	public $ref_customer;
85
-
86
-	/**
87
-	 * @var string internal ref
88
-	 */
89
-	public $ref_int;
90
-
91
-	public $brouillon;
92
-
93
-	/**
94
-	 * @var int warehouse id
95
-	 */
96
-	public $entrepot_id;
97
-	public $lines=array();
98
-
99
-	/**
100
-	 * @var string Tracking number
101
-	 */
102
-	public $tracking_number;
103
-
104
-	/**
105
-	 * @var string Tracking url
106
-	 */
107
-	public $tracking_url;
108
-	public $billed;
109
-
110
-	/**
111
-	 * @var string name of pdf model
112
-	 */
113
-	public $model_pdf;
114
-
115
-	public $trueWeight;
116
-	public $weight_units;
117
-	public $trueWidth;
118
-	public $width_units;
119
-	public $trueHeight;
120
-	public $height_units;
121
-	public $trueDepth;
122
-	public $depth_units;
123
-	// A denormalized value
124
-	public $trueSize;
125
-
126
-	public $date_delivery;		// Date delivery planed
127
-
128
-	/**
129
-	 * @deprecated
130
-	 * @see date_shipping
131
-	 */
132
-	public $date;
133
-
134
-	/**
135
-	 * @deprecated
136
-	 * @see date_shipping
137
-	 */
138
-	public $date_expedition;
139
-
140
-	/**
141
-	 * Effective delivery date
142
-	 * @var int
143
-	 */
144
-	public $date_shipping;
145
-
146
-	public $date_creation;
147
-	public $date_valid;
148
-
149
-	public $meths;
150
-	public $listmeths;			// List of carriers
151
-
152
-    /**
153
-	 * Draft status
154
-	 */
155
-	const STATUS_DRAFT = 0;
156
-
157
-	/**
158
-	 * Validated status
159
-	 */
160
-	const STATUS_VALIDATED = 1;
161
-
162
-	/**
163
-	 * Closed status
164
-	 */
165
-	const STATUS_CLOSED = 2;
166
-
167
-
168
-
169
-	/**
170
-	 *	Constructor
171
-	 *
172
-	 *  @param		DoliDB		$db      Database handler
173
-	 */
174
-	function __construct($db)
175
-	{
176
-		global $conf;
177
-
178
-		$this->db = $db;
179
-		$this->lines = array();
180
-		$this->products = array();
181
-
182
-		// List of long language codes for status
183
-		$this->statuts = array();
184
-		$this->statuts[-1] = 'StatusSendingCanceled';
185
-		$this->statuts[0]  = 'StatusSendingDraft';
186
-		$this->statuts[1]  = 'StatusSendingValidated';
187
-		$this->statuts[2]  = 'StatusSendingProcessed';
188
-
189
-		// List of short language codes for status
190
-		$this->statutshorts = array();
191
-		$this->statutshorts[-1] = 'StatusSendingCanceledShort';
192
-		$this->statutshorts[0]  = 'StatusSendingDraftShort';
193
-		$this->statutshorts[1]  = 'StatusSendingValidatedShort';
194
-		$this->statutshorts[2]  = 'StatusSendingProcessedShort';
195
-
196
-		/* Status "billed" or not is managed by another field than status
197
-		if (! empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))
198
-		{
199
-			$this->statuts[2]  = 'StatusSendingBilled';
200
-			$this->statutshorts[2]  = 'StatusSendingBilledShort';
201
-		}*/
202
-	}
203
-
204
-	/**
205
-	 *	Return next contract ref
206
-	 *
207
-	 *	@param	Societe		$soc	Thirdparty object
208
-	 *	@return string				Free reference for contract
209
-	 */
210
-	function getNextNumRef($soc)
211
-	{
212
-		global $langs, $conf;
213
-		$langs->load("sendings");
214
-
215
-		if (!empty($conf->global->EXPEDITION_ADDON_NUMBER))
216
-		{
217
-			$mybool = false;
218
-
219
-			$file = $conf->global->EXPEDITION_ADDON_NUMBER.".php";
220
-			$classname = $conf->global->EXPEDITION_ADDON_NUMBER;
221
-
222
-			// Include file with class
223
-			$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
224
-
225
-			foreach ($dirmodels as $reldir) {
226
-
227
-				$dir = dol_buildpath($reldir."core/modules/expedition/");
228
-
229
-				// Load file with numbering class (if found)
230
-				$mybool|=@include_once $dir.$file;
231
-			}
232
-
233
-			if (! $mybool)
234
-			{
235
-				dol_print_error('',"Failed to include file ".$file);
236
-				return '';
237
-			}
238
-
239
-			$obj = new $classname();
240
-			$numref = "";
241
-			$numref = $obj->getNextValue($soc,$this);
242
-
243
-			if ( $numref != "")
244
-			{
245
-				return $numref;
246
-			}
247
-			else
248
-			{
249
-				dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
250
-				return "";
251
-			}
252
-		}
253
-		else
254
-		{
255
-			print $langs->trans("Error")." ".$langs->trans("Error_EXPEDITION_ADDON_NUMBER_NotDefined");
256
-			return "";
257
-		}
258
-	}
259
-
260
-	/**
261
-	 *  Create expedition en base
262
-	 *
263
-	 *  @param	User	$user       Objet du user qui cree
264
-	 * 	@param		int		$notrigger	1=Does not execute triggers, 0= execute triggers
265
-	 *  @return int 				<0 si erreur, id expedition creee si ok
266
-	 */
267
-	function create($user, $notrigger=0)
268
-	{
269
-		global $conf, $hookmanager;
270
-
271
-		$now=dol_now();
272
-
273
-		require_once DOL_DOCUMENT_ROOT .'/product/stock/class/mouvementstock.class.php';
274
-		$error = 0;
275
-
276
-		// Clean parameters
277
-		$this->brouillon = 1;
278
-		$this->tracking_number = dol_sanitizeFileName($this->tracking_number);
279
-		if (empty($this->fk_project)) $this->fk_project = 0;
280
-
281
-		$this->user = $user;
282
-
283
-
284
-		$this->db->begin();
285
-
286
-		$sql = "INSERT INTO ".MAIN_DB_PREFIX."expedition (";
287
-		$sql.= "ref";
288
-		$sql.= ", entity";
289
-		$sql.= ", ref_customer";
290
-		$sql.= ", ref_int";
291
-		$sql.= ", date_creation";
292
-		$sql.= ", fk_user_author";
293
-		$sql.= ", date_expedition";
294
-		$sql.= ", date_delivery";
295
-		$sql.= ", fk_soc";
296
-		$sql.= ", fk_projet";
297
-		$sql.= ", fk_address";
298
-		$sql.= ", fk_shipping_method";
299
-		$sql.= ", tracking_number";
300
-		$sql.= ", weight";
301
-		$sql.= ", size";
302
-		$sql.= ", width";
303
-		$sql.= ", height";
304
-		$sql.= ", weight_units";
305
-		$sql.= ", size_units";
306
-		$sql.= ", note_private";
307
-		$sql.= ", note_public";
308
-		$sql.= ", model_pdf";
309
-		$sql.= ", fk_incoterms, location_incoterms";
310
-		$sql.= ") VALUES (";
311
-		$sql.= "'(PROV)'";
312
-		$sql.= ", ".$conf->entity;
313
-		$sql.= ", ".($this->ref_customer?"'".$this->db->escape($this->ref_customer)."'":"null");
314
-		$sql.= ", ".($this->ref_int?"'".$this->db->escape($this->ref_int)."'":"null");
315
-		$sql.= ", '".$this->db->idate($now)."'";
316
-		$sql.= ", ".$user->id;
317
-		$sql.= ", ".($this->date_expedition>0?"'".$this->db->idate($this->date_expedition)."'":"null");
318
-		$sql.= ", ".($this->date_delivery>0?"'".$this->db->idate($this->date_delivery)."'":"null");
319
-		$sql.= ", ".$this->socid;
320
-		$sql.= ", ".$this->fk_project;
321
-		$sql.= ", ".($this->fk_delivery_address>0?$this->fk_delivery_address:"null");
322
-		$sql.= ", ".($this->shipping_method_id>0?$this->shipping_method_id:"null");
323
-		$sql.= ", '".$this->db->escape($this->tracking_number)."'";
324
-		$sql.= ", ".$this->weight;
325
-		$sql.= ", ".$this->sizeS;	// TODO Should use this->trueDepth
326
-		$sql.= ", ".$this->sizeW;	// TODO Should use this->trueWidth
327
-		$sql.= ", ".$this->sizeH;	// TODO Should use this->trueHeight
328
-		$sql.= ", ".$this->weight_units;
329
-		$sql.= ", ".$this->size_units;
330
-		$sql.= ", ".(!empty($this->note_private)?"'".$this->db->escape($this->note_private)."'":"null");
331
-		$sql.= ", ".(!empty($this->note_public)?"'".$this->db->escape($this->note_public)."'":"null");
332
-		$sql.= ", ".(!empty($this->model_pdf)?"'".$this->db->escape($this->model_pdf)."'":"null");
333
-		$sql.= ", ".(int) $this->fk_incoterms;
334
-		$sql.= ", '".$this->db->escape($this->location_incoterms)."'";
335
-		$sql.= ")";
336
-
337
-		dol_syslog(get_class($this)."::create", LOG_DEBUG);
338
-		$resql=$this->db->query($sql);
339
-		if ($resql)
340
-		{
341
-			$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."expedition");
342
-
343
-			$sql = "UPDATE ".MAIN_DB_PREFIX."expedition";
344
-			$sql.= " SET ref = '(PROV".$this->id.")'";
345
-			$sql.= " WHERE rowid = ".$this->id;
346
-
347
-			dol_syslog(get_class($this)."::create", LOG_DEBUG);
348
-			if ($this->db->query($sql))
349
-			{
350
-				// Insertion des lignes
351
-				$num=count($this->lines);
352
-				for ($i = 0; $i < $num; $i++)
353
-				{
354
-					if (! isset($this->lines[$i]->detail_batch))
355
-					{	// no batch management
356
-						if (! $this->create_line($this->lines[$i]->entrepot_id, $this->lines[$i]->origin_line_id, $this->lines[$i]->qty, $this->lines[$i]->array_options) > 0)
357
-						{
358
-							$error++;
359
-						}
360
-					}
361
-					else
362
-					{	// with batch management
363
-						if (! $this->create_line_batch($this->lines[$i],$this->lines[$i]->array_options) > 0)
364
-						{
365
-							$error++;
366
-						}
367
-					}
368
-				}
369
-
370
-				if (! $error && $this->id && $this->origin_id)
371
-				{
372
-					$ret = $this->add_object_linked();
373
-					if (!$ret)
374
-					{
375
-						$error++;
376
-					}
377
-				}
378
-
379
-				// Actions on extra fields
380
-				if (! $error && empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))
381
-				{
382
-					$result=$this->insertExtraFields();
383
-					if ($result < 0)
384
-					{
385
-						$error++;
386
-					}
387
-				}
388
-
389
-				if (! $error && ! $notrigger)
390
-				{
391
-					// Call trigger
392
-					$result=$this->call_trigger('SHIPPING_CREATE',$user);
393
-					if ($result < 0) { $error++; }
394
-					// End call triggers
395
-
396
-					if (! $error)
397
-					{
398
-						$this->db->commit();
399
-						return $this->id;
400
-					}
401
-					else
402
-					{
403
-						foreach($this->errors as $errmsg)
404
-						{
405
-							dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
406
-							$this->error.=($this->error?', '.$errmsg:$errmsg);
407
-						}
408
-						$this->db->rollback();
409
-						return -1*$error;
410
-					}
411
-				}
412
-				else
413
-				{
414
-					$error++;
415
-					$this->error=$this->db->lasterror()." - sql=$sql";
416
-					$this->db->rollback();
417
-					return -3;
418
-				}
419
-			}
420
-			else
421
-			{
422
-				$error++;
423
-				$this->error=$this->db->lasterror()." - sql=$sql";
424
-				$this->db->rollback();
425
-				return -2;
426
-			}
427
-		}
428
-		else
429
-		{
430
-			$error++;
431
-			$this->error=$this->db->error()." - sql=$sql";
432
-			$this->db->rollback();
433
-			return -1;
434
-		}
435
-	}
48
+    /**
49
+     * @var string ID to identify managed object
50
+     */
51
+    public $element="shipping";
436 52
 
437
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
438
-	/**
439
-	 * Create a expedition line
440
-	 *
441
-	 * @param 	int		$entrepot_id		Id of warehouse
442
-	 * @param 	int		$origin_line_id		Id of source line
443
-	 * @param 	int		$qty				Quantity
444
-	 * @param	array	$array_options		extrafields array
445
-	 * @return	int							<0 if KO, line_id if OK
446
-	 */
447
-	function create_line($entrepot_id, $origin_line_id, $qty,$array_options=0)
448
-	{
449
-        //phpcs:enable
450
-		$expeditionline = new ExpeditionLigne($this->db);
451
-		$expeditionline->fk_expedition = $this->id;
452
-		$expeditionline->entrepot_id = $entrepot_id;
453
-		$expeditionline->fk_origin_line = $origin_line_id;
454
-		$expeditionline->qty = $qty;
455
-		$expeditionline->array_options = $array_options;
456
-
457
-		if (($lineId = $expeditionline->insert()) < 0)
458
-		{
459
-			$this->errors[]=$expeditionline->error;
460
-		}
461
-		return $lineId;
462
-	}
53
+    /**
54
+     * @var int Field with ID of parent key if this field has a parent
55
+     */
56
+    public $fk_element="fk_expedition";
463 57
 
58
+    /**
59
+     * @var string Name of table without prefix where object is stored
60
+     */
61
+    public $table_element="expedition";
464 62
 
465
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
466
-	/**
467
-	 * Create the detail (eat-by date) of the expedition line
468
-	 *
469
-	 * @param 	object		$line_ext		full line informations
470
-	 * @param	array		$array_options		extrafields array
471
-	 * @return	int							<0 if KO, >0 if OK
472
-	 */
473
-	function create_line_batch($line_ext,$array_options=0)
474
-	{
475
-        // phpcs:enable
476
-		$error = 0;
477
-		$stockLocationQty = array(); // associated array with batch qty in stock location
63
+    /**
64
+     * @var int    Name of subtable line
65
+     */
66
+    public $table_element_line="expeditiondet";
478 67
 
479
-		$tab=$line_ext->detail_batch;
480
-		// create stockLocation Qty array
481
-		foreach ($tab as $detbatch)
482
-		{
483
-			if ($detbatch->entrepot_id)
484
-			{
485
-				$stockLocationQty[$detbatch->entrepot_id] += $detbatch->qty;
486
-			}
487
-		}
488
-		// create shipment lines
489
-		foreach ($stockLocationQty as $stockLocation => $qty)
490
-		{
491
-			if (($line_id = $this->create_line($stockLocation,$line_ext->origin_line_id,$qty,$array_options)) < 0)
492
-			{
493
-				$error++;
494
-			}
495
-			else
496
-			{
497
-				// create shipment batch lines for stockLocation
498
-				foreach ($tab as $detbatch)
499
-				{
500
-					if ($detbatch->entrepot_id == $stockLocation){
501
-						if (! ($detbatch->create($line_id) >0))		// Create an expeditionlinebatch
502
-						{
503
-							$error++;
504
-						}
505
-					}
506
-				}
507
-			}
508
-		}
509
-
510
-		if (! $error) return 1;
511
-		else return -1;
512
-	}
513
-
514
-	/**
515
-	 *	Get object and lines from database
516
-	 *
517
-	 *	@param	int		$id       	Id of object to load
518
-	 * 	@param	string	$ref		Ref of object
519
-	 * 	@param	string	$ref_ext	External reference of object
520
-	 * 	@param	string	$ref_int	Internal reference of other object
521
-	 *	@return int			        >0 if OK, 0 if not found, <0 if KO
522
-	 */
523
-	function fetch($id, $ref='', $ref_ext='', $ref_int='')
524
-	{
525
-		global $conf;
526
-
527
-		// Check parameters
528
-		if (empty($id) && empty($ref) && empty($ref_ext) && empty($ref_int)) return -1;
529
-
530
-		$sql = "SELECT e.rowid, 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, e.billed";
531
-		$sql.= ", e.weight, e.weight_units, e.size, e.size_units, e.width, e.height";
532
-		$sql.= ", e.date_expedition as date_expedition, e.model_pdf, e.fk_address, e.date_delivery";
533
-		$sql.= ", e.fk_shipping_method, e.tracking_number";
534
-		$sql.= ", e.note_private, e.note_public";
535
-		$sql.= ', e.fk_incoterms, e.location_incoterms';
536
-		$sql.= ', i.libelle as libelle_incoterms';
537
-		$sql.= ', s.libelle as shipping_method';
538
-		$sql.= ", el.fk_source as origin_id, el.sourcetype as origin";
539
-		$sql.= " FROM ".MAIN_DB_PREFIX."expedition as e";
540
-		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."element_element as el ON el.fk_target = e.rowid AND el.targettype = '".$this->db->escape($this->element)."'";
541
-		$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_incoterms as i ON e.fk_incoterms = i.rowid';
542
-		$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_shipment_mode as s ON e.fk_shipping_method = s.rowid';
543
-		$sql.= " WHERE e.entity IN (".getEntity('expedition').")";
544
-		if ($id)   	  $sql.= " AND e.rowid=".$id;
545
-		if ($ref)     $sql.= " AND e.ref='".$this->db->escape($ref)."'";
546
-		if ($ref_ext) $sql.= " AND e.ref_ext='".$this->db->escape($ref_ext)."'";
547
-		if ($ref_int) $sql.= " AND e.ref_int='".$this->db->escape($ref_int)."'";
548
-
549
-		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
550
-		$result = $this->db->query($sql);
551
-		if ($result)
552
-		{
553
-			if ($this->db->num_rows($result))
554
-			{
555
-				$obj = $this->db->fetch_object($result);
556
-
557
-				$this->id                   = $obj->rowid;
558
-				$this->ref                  = $obj->ref;
559
-				$this->socid                = $obj->socid;
560
-				$this->ref_customer	    = $obj->ref_customer;
561
-				$this->ref_ext		    = $obj->ref_ext;
562
-				$this->ref_int		    = $obj->ref_int;
563
-				$this->statut               = $obj->fk_statut;
564
-				$this->user_author_id       = $obj->fk_user_author;
565
-				$this->date_creation        = $this->db->jdate($obj->date_creation);
566
-				$this->date                 = $this->db->jdate($obj->date_expedition);	// TODO deprecated
567
-				$this->date_expedition      = $this->db->jdate($obj->date_expedition);	// TODO deprecated
568
-				$this->date_shipping        = $this->db->jdate($obj->date_expedition);	// Date real
569
-				$this->date_delivery        = $this->db->jdate($obj->date_delivery);	// Date planed
570
-				$this->fk_delivery_address  = $obj->fk_address;
571
-				$this->modelpdf             = $obj->model_pdf;
572
-				$this->shipping_method_id   = $obj->fk_shipping_method;
573
-				$this->shipping_method	    = $obj->shipping_method;
574
-				$this->tracking_number      = $obj->tracking_number;
575
-				$this->origin               = ($obj->origin?$obj->origin:'commande'); // For compatibility
576
-				$this->origin_id            = $obj->origin_id;
577
-				$this->billed               = $obj->billed;
578
-				$this->fk_project	    = $obj->fk_projet;
579
-
580
-				$this->trueWeight           = $obj->weight;
581
-				$this->weight_units         = $obj->weight_units;
582
-
583
-				$this->trueWidth            = $obj->width;
584
-				$this->width_units          = $obj->size_units;
585
-				$this->trueHeight           = $obj->height;
586
-				$this->height_units         = $obj->size_units;
587
-				$this->trueDepth            = $obj->size;
588
-				$this->depth_units          = $obj->size_units;
589
-
590
-				$this->note_public          = $obj->note_public;
591
-				$this->note_private         = $obj->note_private;
592
-
593
-				// A denormalized value
594
-				$this->trueSize             = $obj->size."x".$obj->width."x".$obj->height;
595
-				$this->size_units           = $obj->size_units;
596
-
597
-				//Incoterms
598
-				$this->fk_incoterms         = $obj->fk_incoterms;
599
-				$this->location_incoterms   = $obj->location_incoterms;
600
-				$this->libelle_incoterms    = $obj->libelle_incoterms;
601
-
602
-				$this->db->free($result);
603
-
604
-				if ($this->statut == 0) $this->brouillon = 1;
605
-
606
-				// Tracking url
607
-				$this->getUrlTrackingStatus($obj->tracking_number);
608
-
609
-				/*
610
-				 * Thirparty
611
-				 */
612
-				$result=$this->fetch_thirdparty();
68
+    /**
69
+     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
70
+     * @var int
71
+     */
72
+    public $ismultientitymanaged = 1;
613 73
 
614
-				// Retreive extrafields
615
-				$this->fetch_optionals();
74
+    /**
75
+     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
76
+     */
77
+    public $picto = 'sending';
616 78
 
617
-				/*
618
-				 * Lines
619
-				 */
620
-				$result=$this->fetch_lines();
621
-				if ($result < 0)
622
-				{
623
-					return -3;
624
-				}
625
-
626
-				return 1;
627
-			}
628
-			else
629
-			{
630
-				dol_syslog(get_class($this).'::Fetch no expedition found', LOG_ERR);
631
-				$this->error='Delivery with id '.$id.' not found';
632
-				return 0;
633
-			}
634
-		}
635
-		else
636
-		{
637
-			$this->error=$this->db->error();
638
-			return -1;
639
-		}
640
-	}
641
-
642
-	/**
643
-	 *  Validate object and update stock if option enabled
644
-	 *
645
-	 *  @param      User		$user       Object user that validate
646
-	 *  @param		int			$notrigger	1=Does not execute triggers, 0= execute triggers
647
-	 *  @return     int						<0 if OK, >0 if KO
648
-	 */
649
-	function valid($user, $notrigger=0)
650
-	{
651
-		global $conf, $langs;
652
-
653
-		require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
654
-
655
-		dol_syslog(get_class($this)."::valid");
656
-
657
-		// Protection
658
-		if ($this->statut)
659
-		{
660
-			dol_syslog(get_class($this)."::valid no draft status", LOG_WARNING);
661
-			return 0;
662
-		}
79
+    public $socid;
663 80
 
664
-		if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->creer))
665
-	   	|| (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->shipping_advance->validate))))
666
-		{
667
-			$this->error='Permission denied';
668
-			dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
669
-			return -1;
670
-		}
81
+    /**
82
+     * @var string Customer ref
83
+     */
84
+    public $ref_customer;
671 85
 
672
-		$this->db->begin();
86
+    /**
87
+     * @var string internal ref
88
+     */
89
+    public $ref_int;
673 90
 
674
-		$error = 0;
91
+    public $brouillon;
675 92
 
676
-		// Define new ref
677
-		$soc = new Societe($this->db);
678
-		$soc->fetch($this->socid);
93
+    /**
94
+     * @var int warehouse id
95
+     */
96
+    public $entrepot_id;
97
+    public $lines=array();
679 98
 
680
-		// Class of company linked to order
681
-		$result=$soc->set_as_client();
99
+    /**
100
+     * @var string Tracking number
101
+     */
102
+    public $tracking_number;
682 103
 
683
-		// Define new ref
684
-		if (! $error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life
685
-		{
686
-			$numref = $this->getNextNumRef($soc);
687
-		}
688
-		else
689
-		{
690
-			$numref = "EXP".$this->id;
691
-		}
692
-		$this->newref = $numref;
693
-
694
-		$now=dol_now();
695
-
696
-		// Validate
697
-		$sql = "UPDATE ".MAIN_DB_PREFIX."expedition SET";
698
-		$sql.= " ref='".$numref."'";
699
-		$sql.= ", fk_statut = 1";
700
-		$sql.= ", date_valid = '".$this->db->idate($now)."'";
701
-		$sql.= ", fk_user_valid = ".$user->id;
702
-		$sql.= " WHERE rowid = ".$this->id;
703
-
704
-		dol_syslog(get_class($this)."::valid update expedition", LOG_DEBUG);
705
-		$resql=$this->db->query($sql);
706
-		if (! $resql)
707
-		{
708
-			$this->error=$this->db->lasterror();
709
-			$error++;
710
-		}
104
+    /**
105
+     * @var string Tracking url
106
+     */
107
+    public $tracking_url;
108
+    public $billed;
711 109
 
712
-		// If stock increment is done on sending (recommanded choice)
713
-		if (! $error && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT))
714
-		{
715
-			require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
716
-
717
-			$langs->load("agenda");
718
-
719
-			// Loop on each product line to add a stock movement
720
-			$sql = "SELECT cd.fk_product, cd.subprice,";
721
-			$sql.= " ed.rowid, ed.qty, ed.fk_entrepot,";
722
-			$sql.= " edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
723
-			$sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd,";
724
-			$sql.= " ".MAIN_DB_PREFIX."expeditiondet as ed";
725
-			$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
726
-			$sql.= " WHERE ed.fk_expedition = ".$this->id;
727
-			$sql.= " AND cd.rowid = ed.fk_origin_line";
728
-
729
-			dol_syslog(get_class($this)."::valid select details", LOG_DEBUG);
730
-			$resql=$this->db->query($sql);
731
-			if ($resql)
732
-			{
733
-				$cpt = $this->db->num_rows($resql);
734
-				for ($i = 0; $i < $cpt; $i++)
735
-				{
736
-					$obj = $this->db->fetch_object($resql);
737
-					if (empty($obj->edbrowid))
738
-					{
739
-						$qty = $obj->qty;
740
-					}
741
-					else
742
-					{
743
-						$qty = $obj->edbqty;
744
-					}
745
-					if ($qty <= 0) continue;
746
-					dol_syslog(get_class($this)."::valid movement index ".$i." ed.rowid=".$obj->rowid." edb.rowid=".$obj->edbrowid);
747
-
748
-					//var_dump($this->lines[$i]);
749
-					$mouvS = new MouvementStock($this->db);
750
-					$mouvS->origin = &$this;
751
-
752
-					if (empty($obj->edbrowid))
753
-					{
754
-						// line without batch detail
755
-
756
-						// We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record.
757
-						$result=$mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans("ShipmentValidatedInDolibarr",$numref));
758
-						if ($result < 0) {
759
-							$error++;
760
-							$this->errors[]=$mouvS->error;
761
-							$this->errors = array_merge($this->errors, $mouvS->errors);
762
-							break;
763
-						}
764
-					}
765
-					else
766
-					{
767
-						// line with batch detail
768
-
769
-						// We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record.
770
-						// Note: ->fk_origin_stock = id into table llx_product_batch (may be rename into llx_product_stock_batch in another version)
771
-						$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);
772
-						if ($result < 0) {
773
-							$error++;
774
-							$this->errors[]=$mouvS->error;
775
-							$this->errors = array_merge($this->errors, $mouvS->errors);
776
-							break;
777
-						}
778
-					}
779
-				}
780
-			}
781
-			else
782
-			{
783
-				$this->db->rollback();
784
-				$this->error=$this->db->error();
785
-				return -2;
786
-			}
787
-		}
788
-
789
-		// Change status of order to "shipment in process"
790
-		$ret = $this->setStatut(Commande::STATUS_SHIPMENTONPROCESS, $this->origin_id, $this->origin);
791
-
792
-		if (! $ret)
793
-		{
794
-			$error++;
795
-		}
110
+    /**
111
+     * @var string name of pdf model
112
+     */
113
+    public $model_pdf;
796 114
 
797
-		if (! $error && ! $notrigger)
798
-		{
799
-			// Call trigger
800
-			$result=$this->call_trigger('SHIPPING_VALIDATE',$user);
801
-			if ($result < 0) { $error++; }
802
-			// End call triggers
803
-		}
115
+    public $trueWeight;
116
+    public $weight_units;
117
+    public $trueWidth;
118
+    public $width_units;
119
+    public $trueHeight;
120
+    public $height_units;
121
+    public $trueDepth;
122
+    public $depth_units;
123
+    // A denormalized value
124
+    public $trueSize;
804 125
 
805
-		if (! $error)
806
-		{
807
-			$this->oldref = $this->ref;
808
-
809
-			// Rename directory if dir was a temporary ref
810
-			if (preg_match('/^[\(]?PROV/i', $this->ref))
811
-			{
812
-				// On renomme repertoire ($this->ref = ancienne ref, $numfa = nouvelle ref)
813
-				// in order not to lose the attached files
814
-				$oldref = dol_sanitizeFileName($this->ref);
815
-				$newref = dol_sanitizeFileName($numref);
816
-				$dirsource = $conf->expedition->dir_output.'/sending/'.$oldref;
817
-				$dirdest = $conf->expedition->dir_output.'/sending/'.$newref;
818
-				if (file_exists($dirsource))
819
-				{
820
-					dol_syslog(get_class($this)."::valid rename dir ".$dirsource." into ".$dirdest);
821
-
822
-					if (@rename($dirsource, $dirdest))
823
-					{
824
-						dol_syslog("Rename ok");
825
-						// Rename docs starting with $oldref with $newref
826
-						$listoffiles=dol_dir_list($conf->expedition->dir_output.'/sending/'.$newref, 'files', 1, '^'.preg_quote($oldref,'/'));
827
-						foreach($listoffiles as $fileentry)
828
-						{
829
-							$dirsource=$fileentry['name'];
830
-							$dirdest=preg_replace('/^'.preg_quote($oldref,'/').'/',$newref, $dirsource);
831
-							$dirsource=$fileentry['path'].'/'.$dirsource;
832
-							$dirdest=$fileentry['path'].'/'.$dirdest;
833
-							@rename($dirsource, $dirdest);
834
-						}
835
-					}
836
-				}
837
-			}
838
-		}
839
-
840
-		// Set new ref and current status
841
-		if (! $error)
842
-		{
843
-			$this->ref = $numref;
844
-			$this->statut = 1;
845
-		}
126
+    public $date_delivery;		// Date delivery planed
846 127
 
847
-		if (! $error)
848
-		{
849
-			$this->db->commit();
850
-			return 1;
851
-		}
852
-		else
853
-		{
854
-			foreach($this->errors as $errmsg)
855
-			{
856
-				dol_syslog(get_class($this)."::valid ".$errmsg, LOG_ERR);
857
-				$this->error.=($this->error?', '.$errmsg:$errmsg);
858
-			}
859
-			$this->db->rollback();
860
-			return -1*$error;
861
-		}
862
-	}
128
+    /**
129
+     * @deprecated
130
+     * @see date_shipping
131
+     */
132
+    public $date;
863 133
 
134
+    /**
135
+     * @deprecated
136
+     * @see date_shipping
137
+     */
138
+    public $date_expedition;
864 139
 
865
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
866
-	/**
867
-	 *	Create a delivery receipt from a shipment
868
-	 *
869
-	 *	@param	User	$user       User
870
-	 *  @return int  				<0 if KO, >=0 if OK
871
-	 */
872
-	function create_delivery($user)
873
-	{
874
-        // phpcs:enable
875
-		global $conf;
140
+    /**
141
+     * Effective delivery date
142
+     * @var int
143
+     */
144
+    public $date_shipping;
876 145
 
877
-		if ($conf->livraison_bon->enabled)
878
-		{
879
-			if ($this->statut == 1 || $this->statut == 2)
880
-			{
881
-				// Expedition validee
882
-				include_once DOL_DOCUMENT_ROOT.'/livraison/class/livraison.class.php';
883
-				$delivery = new Livraison($this->db);
884
-				$result=$delivery->create_from_sending($user, $this->id);
885
-				if ($result > 0)
886
-				{
887
-					return $result;
888
-				}
889
-				else
890
-				{
891
-					$this->error=$delivery->error;
892
-					return $result;
893
-				}
894
-			}
895
-			else return 0;
896
-		}
897
-		else return 0;
898
-	}
899
-
900
-	/**
901
-	 * Add an expedition line.
902
-	 * If STOCK_WAREHOUSE_NOT_REQUIRED_FOR_SHIPMENTS is set, you can add a shipment line, with no stock source defined
903
-	 * If STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT is not set, you can add a shipment line, even if not enough into stock
904
-	 *
905
-	 * @param 	int		$entrepot_id		Id of warehouse
906
-	 * @param 	int		$id					Id of source line (order line)
907
-	 * @param 	int		$qty				Quantity
908
-	 * @param	array	$array_options		extrafields array
909
-	 * @return	int							<0 if KO, >0 if OK
910
-	 */
911
-	function addline($entrepot_id, $id, $qty,$array_options=0)
912
-	{
913
-		global $conf, $langs;
914
-
915
-		$num = count($this->lines);
916
-		$line = new ExpeditionLigne($this->db);
917
-
918
-		$line->entrepot_id = $entrepot_id;
919
-		$line->origin_line_id = $id;
920
-		$line->qty = $qty;
921
-
922
-		$orderline = new OrderLine($this->db);
923
-		$orderline->fetch($id);
924
-
925
-		if (! empty($conf->stock->enabled) && ! empty($orderline->fk_product))
926
-		{
927
-			$fk_product = $orderline->fk_product;
928
-
929
-			if (! ($entrepot_id > 0) && empty($conf->global->STOCK_WAREHOUSE_NOT_REQUIRED_FOR_SHIPMENTS))
930
-			{
931
-				$langs->load("errors");
932
-				$this->error=$langs->trans("ErrorWarehouseRequiredIntoShipmentLine");
933
-				return -1;
934
-			}
935
-
936
-			if ($conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT)
937
-			{
938
-				// Check must be done for stock of product into warehouse if $entrepot_id defined
939
-				$product=new Product($this->db);
940
-				$result=$product->fetch($fk_product);
941
-
942
-				if ($entrepot_id > 0) {
943
-					$product->load_stock('warehouseopen');
944
-					$product_stock = $product->stock_warehouse[$entrepot_id]->real;
945
-				}
946
-				else
947
-					$product_stock = $product->stock_reel;
948
-
949
-				$product_type=$product->type;
950
-				if ($product_type == 0 && $product_stock < $qty)
951
-				{
952
-					$langs->load("errors");
953
-					$this->error=$langs->trans('ErrorStockIsNotEnoughToAddProductOnShipment', $product->ref);
954
-					$this->db->rollback();
955
-					return -3;
956
-				}
957
-			}
958
-		}
959
-
960
-		// If product need a batch number, we should not have called this function but addline_batch instead.
961
-		if (! empty($conf->productbatch->enabled) && ! empty($orderline->fk_product) && ! empty($orderline->product_tobatch))
962
-		{
963
-			$this->error='ADDLINE_WAS_CALLED_INSTEAD_OF_ADDLINEBATCH';
964
-			return -4;
965
-		}
146
+    public $date_creation;
147
+    public $date_valid;
966 148
 
967
-		// extrafields
968
-		if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options)>0) // For avoid conflicts if trigger used
969
-			$line->array_options = $array_options;
149
+    public $meths;
150
+    public $listmeths;			// List of carriers
970 151
 
971
-		$this->lines[$num] = $line;
972
-	}
152
+    /**
153
+     * Draft status
154
+     */
155
+    const STATUS_DRAFT = 0;
973 156
 
974
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
975
-	/**
976
-	 * Add a shipment line with batch record
977
-	 *
978
-	 * @param 	array		$dbatch		Array of value (key 'detail' -> Array, key 'qty' total quantity for line, key ix_l : original line index)
979
-	 * @param	array		$array_options		extrafields array
980
-	 * @return	int						<0 if KO, >0 if OK
981
-	 */
982
-	function addline_batch($dbatch,$array_options=0)
983
-	{
984
-        // phpcs:enable
985
-		global $conf,$langs;
157
+    /**
158
+     * Validated status
159
+     */
160
+    const STATUS_VALIDATED = 1;
986 161
 
987
-		$num = count($this->lines);
988
-		if ($dbatch['qty']>0)
989
-		{
990
-			$line = new ExpeditionLigne($this->db);
991
-			$tab=array();
992
-			foreach ($dbatch['detail'] as $key=>$value)
993
-			{
994
-				if ($value['q']>0)
995
-				{
996
-					// $value['q']=qty to move
997
-					// $value['id_batch']=id into llx_product_batch of record to move
998
-					//var_dump($value);
999
-
1000
-					$linebatch = new ExpeditionLineBatch($this->db);
1001
-					$ret=$linebatch->fetchFromStock($value['id_batch']);	// load serial, sellby, eatby
1002
-					if ($ret<0)
1003
-					{
1004
-						$this->error=$linebatch->error;
1005
-						return -1;
1006
-					}
1007
-					$linebatch->qty=$value['q'];
1008
-					$tab[]=$linebatch;
1009
-
1010
-					if ($conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT)
1011
-					{
1012
-						require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
1013
-						$prod_batch = new Productbatch($this->db);
1014
-						$prod_batch->fetch($value['id_batch']);
1015
-
1016
-						if ($prod_batch->qty < $linebatch->qty)
1017
-						{
1018
-							$langs->load("errors");
1019
-							$this->errors[]=$langs->trans('ErrorStockIsNotEnoughToAddProductOnShipment', $prod_batch->fk_product);
1020
-							dol_syslog(get_class($this)."::addline_batch error=Product ".$prod_batch->batch.": ".$this->errorsToString(), LOG_ERR);
1021
-							$this->db->rollback();
1022
-							return -1;
1023
-						}
1024
-					}
1025
-
1026
-					//var_dump($linebatch);
1027
-				}
1028
-			}
1029
-			$line->entrepot_id = $linebatch->entrepot_id;
1030
-			$line->origin_line_id = $dbatch['ix_l'];
1031
-			$line->qty = $dbatch['qty'];
1032
-			$line->detail_batch=$tab;
1033
-
1034
-			// extrafields
1035
-			if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options)>0) // For avoid conflicts if trigger used
1036
-				$line->array_options = $array_options;
1037
-
1038
-			//var_dump($line);
1039
-			$this->lines[$num] = $line;
1040
-			return 1;
1041
-		}
1042
-	}
1043
-
1044
-	/**
1045
-	 *  Update database
1046
-	 *
1047
-	 *  @param	User	$user        	User that modify
1048
-	 *  @param  int		$notrigger	    0=launch triggers after, 1=disable triggers
1049
-	 *  @return int 			       	<0 if KO, >0 if OK
1050
-	 */
1051
-	function update($user=null, $notrigger=0)
1052
-	{
1053
-		global $conf;
1054
-		$error=0;
1055
-
1056
-		// Clean parameters
1057
-
1058
-		if (isset($this->ref)) $this->ref=trim($this->ref);
1059
-		if (isset($this->entity)) $this->entity=trim($this->entity);
1060
-		if (isset($this->ref_customer)) $this->ref_customer=trim($this->ref_customer);
1061
-		if (isset($this->socid)) $this->socid=trim($this->socid);
1062
-		if (isset($this->fk_user_author)) $this->fk_user_author=trim($this->fk_user_author);
1063
-		if (isset($this->fk_user_valid)) $this->fk_user_valid=trim($this->fk_user_valid);
1064
-		if (isset($this->fk_delivery_address)) $this->fk_delivery_address=trim($this->fk_delivery_address);
1065
-		if (isset($this->shipping_method_id)) $this->shipping_method_id=trim($this->shipping_method_id);
1066
-		if (isset($this->tracking_number)) $this->tracking_number=trim($this->tracking_number);
1067
-		if (isset($this->statut)) $this->statut=(int) $this->statut;
1068
-		if (isset($this->trueDepth)) $this->trueDepth=trim($this->trueDepth);
1069
-		if (isset($this->trueWidth)) $this->trueWidth=trim($this->trueWidth);
1070
-		if (isset($this->trueHeight)) $this->trueHeight=trim($this->trueHeight);
1071
-		if (isset($this->size_units)) $this->size_units=trim($this->size_units);
1072
-		if (isset($this->weight_units)) $this->weight_units=trim($this->weight_units);
1073
-		if (isset($this->trueWeight)) $this->weight=trim($this->trueWeight);
1074
-		if (isset($this->note_private)) $this->note=trim($this->note_private);
1075
-		if (isset($this->note_public)) $this->note=trim($this->note_public);
1076
-		if (isset($this->modelpdf)) $this->modelpdf=trim($this->modelpdf);
1077
-
1078
-
1079
-
1080
-		// Check parameters
1081
-		// Put here code to add control on parameters values
1082
-
1083
-		// Update request
1084
-		$sql = "UPDATE ".MAIN_DB_PREFIX."expedition SET";
1085
-
1086
-		$sql.= " tms=".(dol_strlen($this->tms)!=0 ? "'".$this->db->idate($this->tms)."'" : 'null').",";
1087
-		$sql.= " ref=".(isset($this->ref)?"'".$this->db->escape($this->ref)."'":"null").",";
1088
-		$sql.= " ref_customer=".(isset($this->ref_customer)?"'".$this->db->escape($this->ref_customer)."'":"null").",";
1089
-		$sql.= " fk_soc=".(isset($this->socid)?$this->socid:"null").",";
1090
-		$sql.= " date_creation=".(dol_strlen($this->date_creation)!=0 ? "'".$this->db->idate($this->date_creation)."'" : 'null').",";
1091
-		$sql.= " fk_user_author=".(isset($this->fk_user_author)?$this->fk_user_author:"null").",";
1092
-		$sql.= " date_valid=".(dol_strlen($this->date_valid)!=0 ? "'".$this->db->idate($this->date_valid)."'" : 'null').",";
1093
-		$sql.= " fk_user_valid=".(isset($this->fk_user_valid)?$this->fk_user_valid:"null").",";
1094
-		$sql.= " date_expedition=".(dol_strlen($this->date_expedition)!=0 ? "'".$this->db->idate($this->date_expedition)."'" : 'null').",";
1095
-		$sql.= " date_delivery=".(dol_strlen($this->date_delivery)!=0 ? "'".$this->db->idate($this->date_delivery)."'" : 'null').",";
1096
-		$sql.= " fk_address=".(isset($this->fk_delivery_address)?$this->fk_delivery_address:"null").",";
1097
-		$sql.= " fk_shipping_method=".((isset($this->shipping_method_id) && $this->shipping_method_id > 0)?$this->shipping_method_id:"null").",";
1098
-		$sql.= " tracking_number=".(isset($this->tracking_number)?"'".$this->db->escape($this->tracking_number)."'":"null").",";
1099
-		$sql.= " fk_statut=".(isset($this->statut)?$this->statut:"null").",";
1100
-		$sql.= " fk_projet=".(isset($this->fk_project)?$this->fk_project:"null").",";
1101
-		$sql.= " height=".(($this->trueHeight != '')?$this->trueHeight:"null").",";
1102
-		$sql.= " width=".(($this->trueWidth != '')?$this->trueWidth:"null").",";
1103
-		$sql.= " size_units=".(isset($this->size_units)?$this->size_units:"null").",";
1104
-		$sql.= " size=".(($this->trueDepth != '')?$this->trueDepth:"null").",";
1105
-		$sql.= " weight_units=".(isset($this->weight_units)?$this->weight_units:"null").",";
1106
-		$sql.= " weight=".(($this->trueWeight != '')?$this->trueWeight:"null").",";
1107
-		$sql.= " note_private=".(isset($this->note_private)?"'".$this->db->escape($this->note_private)."'":"null").",";
1108
-		$sql.= " note_public=".(isset($this->note_public)?"'".$this->db->escape($this->note_public)."'":"null").",";
1109
-		$sql.= " model_pdf=".(isset($this->modelpdf)?"'".$this->db->escape($this->modelpdf)."'":"null").",";
1110
-		$sql.= " entity=".$conf->entity;
1111
-
1112
-		$sql.= " WHERE rowid=".$this->id;
1113
-
1114
-		$this->db->begin();
1115
-
1116
-		dol_syslog(get_class($this)."::update", LOG_DEBUG);
1117
-		$resql = $this->db->query($sql);
1118
-		if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
1119
-
1120
-		if (! $error)
1121
-		{
1122
-			if (! $notrigger)
1123
-			{
1124
-				// Call trigger
1125
-				$result=$this->call_trigger('SHIPPING_MODIFY',$user);
1126
-				if ($result < 0) { $error++; }
1127
-				// End call triggers
1128
-			}
1129
-		}
1130
-
1131
-		// Commit or rollback
1132
-		if ($error)
1133
-		{
1134
-			foreach($this->errors as $errmsg)
1135
-			{
1136
-				dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
1137
-				$this->error.=($this->error?', '.$errmsg:$errmsg);
1138
-			}
1139
-			$this->db->rollback();
1140
-			return -1*$error;
1141
-		}
1142
-		else
1143
-		{
1144
-			$this->db->commit();
1145
-			return 1;
1146
-		}
1147
-	}
1148
-
1149
-	/**
1150
-	 * 	Delete shipment.
1151
-	 * 	Warning, do not delete a shipment if a delivery is linked to (with table llx_element_element)
1152
-	 *
1153
-	 * 	@return	int		>0 if OK, 0 if deletion done but failed to delete files, <0 if KO
1154
-	 */
1155
-	function delete()
1156
-	{
1157
-		global $conf, $langs, $user;
1158
-
1159
-		require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1160
-		require_once DOL_DOCUMENT_ROOT.'/expedition/class/expeditionbatch.class.php';
1161
-
1162
-		$error=0;
1163
-		$this->error='';
1164
-
1165
-		$this->db->begin();
1166
-
1167
-		// Add a protection to refuse deleting if shipment has at least one delivery
1168
-		$this->fetchObjectLinked($this->id, 'shipping', 0, 'delivery');	// Get deliveries linked to this shipment
1169
-		if (count($this->linkedObjectsIds) > 0)
1170
-		{
1171
-			$this->error='ErrorThereIsSomeDeliveries';
1172
-			$error++;
1173
-		}
162
+    /**
163
+     * Closed status
164
+     */
165
+    const STATUS_CLOSED = 2;
1174 166
 
1175
-		if (! $error)
1176
-		{
1177
-			if (! $notrigger)
1178
-			{
1179
-				// Call trigger
1180
-				$result=$this->call_trigger('SHIPPING_DELETE',$user);
1181
-				if ($result < 0) { $error++; }
1182
-				// End call triggers
1183
-			}
1184
-		}
1185
-
1186
-		// Stock control
1187
-		if (! $error && $conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_SHIPMENT && $this->statut > 0)
1188
-		{
1189
-			require_once DOL_DOCUMENT_ROOT."/product/stock/class/mouvementstock.class.php";
1190
-
1191
-			$langs->load("agenda");
1192
-
1193
-			// Loop on each product line to add a stock movement
1194
-			$sql = "SELECT cd.fk_product, cd.subprice, ed.qty, ed.fk_entrepot, ed.rowid as expeditiondet_id";
1195
-			$sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd,";
1196
-			$sql.= " ".MAIN_DB_PREFIX."expeditiondet as ed";
1197
-			$sql.= " WHERE ed.fk_expedition = ".$this->id;
1198
-			$sql.= " AND cd.rowid = ed.fk_origin_line";
1199
-
1200
-			dol_syslog(get_class($this)."::delete select details", LOG_DEBUG);
1201
-			$resql=$this->db->query($sql);
1202
-			if ($resql)
1203
-			{
1204
-				$cpt = $this->db->num_rows($resql);
1205
-				for ($i = 0; $i < $cpt; $i++)
1206
-				{
1207
-					dol_syslog(get_class($this)."::delete movement index ".$i);
1208
-					$obj = $this->db->fetch_object($resql);
1209
-
1210
-					$mouvS = new MouvementStock($this->db);
1211
-					// we do not log origin because it will be deleted
1212
-					$mouvS->origin = null;
1213
-					// get lot/serial
1214
-					$lotArray = null;
1215
-					if ($conf->productbatch->enabled)
1216
-					{
1217
-						$lotArray = ExpeditionLineBatch::fetchAll($this->db,$obj->expeditiondet_id);
1218
-						if (! is_array($lotArray))
1219
-						{
1220
-							$error++;$this->errors[]="Error ".$this->db->lasterror();
1221
-						}
1222
-					}
1223
-					if (empty($lotArray)) {
1224
-						// no lot/serial
1225
-						// We increment stock of product (and sub-products)
1226
-						// We use warehouse selected for each line
1227
-						$result=$mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $obj->qty, 0, $langs->trans("ShipmentDeletedInDolibarr", $this->ref));  // Price is set to 0, because we don't want to see WAP changed
1228
-						if ($result < 0)
1229
-						{
1230
-							$error++;$this->errors=$this->errors + $mouvS->errors;
1231
-							break;
1232
-						}
1233
-					}
1234
-					else
1235
-					{
1236
-						// We increment stock of batches
1237
-						// We use warehouse selected for each line
1238
-						foreach($lotArray as $lot)
1239
-						{
1240
-							$result=$mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $lot->qty, 0, $langs->trans("ShipmentDeletedInDolibarr", $this->ref), $lot->eatby, $lot->sellby, $lot->batch);  // Price is set to 0, because we don't want to see WAP changed
1241
-							if ($result < 0)
1242
-							{
1243
-								$error++;$this->errors=$this->errors + $mouvS->errors;
1244
-								break;
1245
-							}
1246
-						}
1247
-						if ($error) break; // break for loop incase of error
1248
-					}
1249
-				}
1250
-			}
1251
-			else
1252
-			{
1253
-				$error++;$this->errors[]="Error ".$this->db->lasterror();
1254
-			}
1255
-		}
1256
-
1257
-		// delete batch expedition line
1258
-		if (! $error && $conf->productbatch->enabled)
1259
-		{
1260
-			if (ExpeditionLineBatch::deletefromexp($this->db,$this->id) < 0)
1261
-			{
1262
-				$error++;$this->errors[]="Error ".$this->db->lasterror();
1263
-			}
1264
-		}
1265 167
 
1266
-		if (! $error)
1267
-		{
1268
-			$sql = "DELETE FROM ".MAIN_DB_PREFIX."expeditiondet";
1269
-			$sql.= " WHERE fk_expedition = ".$this->id;
1270
-
1271
-			if ( $this->db->query($sql) )
1272
-			{
1273
-				// Delete linked object
1274
-				$res = $this->deleteObjectLinked();
1275
-				if ($res < 0) $error++;
1276
-
1277
-				if (! $error)
1278
-				{
1279
-					$sql = "DELETE FROM ".MAIN_DB_PREFIX."expedition";
1280
-					$sql.= " WHERE rowid = ".$this->id;
1281
-
1282
-					if ($this->db->query($sql))
1283
-					{
1284
-						if (! empty($this->origin) && $this->origin_id > 0)
1285
-						{
1286
-							$this->fetch_origin();
1287
-							$origin=$this->origin;
1288
-							if ($this->$origin->statut == Commande::STATUS_SHIPMENTONPROCESS)     // If order source of shipment is "shipment in progress"
1289
-							{
1290
-								// Check if there is no more shipment. If not, we can move back status of order to "validated" instead of "shipment in progress"
1291
-								$this->$origin->loadExpeditions();
1292
-								//var_dump($this->$origin->expeditions);exit;
1293
-								if (count($this->$origin->expeditions) <= 0)
1294
-								{
1295
-									$this->$origin->setStatut(Commande::STATUS_VALIDATED);
1296
-								}
1297
-							}
1298
-						}
1299
-
1300
-						if (! $error)
1301
-						{
1302
-							$this->db->commit();
1303
-
1304
-							// We delete PDFs
1305
-							$ref = dol_sanitizeFileName($this->ref);
1306
-							if (! empty($conf->expedition->dir_output))
1307
-							{
1308
-								$dir = $conf->expedition->dir_output . '/sending/' . $ref ;
1309
-								$file = $dir . '/' . $ref . '.pdf';
1310
-								if (file_exists($file))
1311
-								{
1312
-									if (! dol_delete_file($file))
1313
-									{
1314
-										return 0;
1315
-									}
1316
-								}
1317
-								if (file_exists($dir))
1318
-								{
1319
-									if (!dol_delete_dir_recursive($dir))
1320
-									{
1321
-										$this->error=$langs->trans("ErrorCanNotDeleteDir",$dir);
1322
-										return 0;
1323
-									}
1324
-								}
1325
-							}
1326
-
1327
-							return 1;
1328
-						}
1329
-						else
1330
-						{
1331
-							$this->db->rollback();
1332
-							return -1;
1333
-						}
1334
-					}
1335
-					else
1336
-					{
1337
-						$this->error=$this->db->lasterror()." - sql=$sql";
1338
-						$this->db->rollback();
1339
-						return -3;
1340
-					}
1341
-				}
1342
-				else
1343
-				{
1344
-					$this->error=$this->db->lasterror()." - sql=$sql";
1345
-					$this->db->rollback();
1346
-					return -2;
1347
-				}
1348
-			}
1349
-			else
1350
-			{
1351
-				$this->error=$this->db->lasterror()." - sql=$sql";
1352
-				$this->db->rollback();
1353
-				return -1;
1354
-			}
1355
-		}
1356
-		else
168
+
169
+    /**
170
+     *	Constructor
171
+     *
172
+     *  @param		DoliDB		$db      Database handler
173
+     */
174
+    function __construct($db)
175
+    {
176
+        global $conf;
177
+
178
+        $this->db = $db;
179
+        $this->lines = array();
180
+        $this->products = array();
181
+
182
+        // List of long language codes for status
183
+        $this->statuts = array();
184
+        $this->statuts[-1] = 'StatusSendingCanceled';
185
+        $this->statuts[0]  = 'StatusSendingDraft';
186
+        $this->statuts[1]  = 'StatusSendingValidated';
187
+        $this->statuts[2]  = 'StatusSendingProcessed';
188
+
189
+        // List of short language codes for status
190
+        $this->statutshorts = array();
191
+        $this->statutshorts[-1] = 'StatusSendingCanceledShort';
192
+        $this->statutshorts[0]  = 'StatusSendingDraftShort';
193
+        $this->statutshorts[1]  = 'StatusSendingValidatedShort';
194
+        $this->statutshorts[2]  = 'StatusSendingProcessedShort';
195
+
196
+        /* Status "billed" or not is managed by another field than status
197
+		if (! empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))
1357 198
 		{
1358
-			$this->db->rollback();
1359
-			return -1;
1360
-		}
1361
-	}
199
+			$this->statuts[2]  = 'StatusSendingBilled';
200
+			$this->statutshorts[2]  = 'StatusSendingBilledShort';
201
+		}*/
202
+    }
203
+
204
+    /**
205
+     *	Return next contract ref
206
+     *
207
+     *	@param	Societe		$soc	Thirdparty object
208
+     *	@return string				Free reference for contract
209
+     */
210
+    function getNextNumRef($soc)
211
+    {
212
+        global $langs, $conf;
213
+        $langs->load("sendings");
214
+
215
+        if (!empty($conf->global->EXPEDITION_ADDON_NUMBER))
216
+        {
217
+            $mybool = false;
218
+
219
+            $file = $conf->global->EXPEDITION_ADDON_NUMBER.".php";
220
+            $classname = $conf->global->EXPEDITION_ADDON_NUMBER;
221
+
222
+            // Include file with class
223
+            $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
224
+
225
+            foreach ($dirmodels as $reldir) {
226
+
227
+                $dir = dol_buildpath($reldir."core/modules/expedition/");
228
+
229
+                // Load file with numbering class (if found)
230
+                $mybool|=@include_once $dir.$file;
231
+            }
232
+
233
+            if (! $mybool)
234
+            {
235
+                dol_print_error('',"Failed to include file ".$file);
236
+                return '';
237
+            }
238
+
239
+            $obj = new $classname();
240
+            $numref = "";
241
+            $numref = $obj->getNextValue($soc,$this);
242
+
243
+            if ( $numref != "")
244
+            {
245
+                return $numref;
246
+            }
247
+            else
248
+            {
249
+                dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
250
+                return "";
251
+            }
252
+        }
253
+        else
254
+        {
255
+            print $langs->trans("Error")." ".$langs->trans("Error_EXPEDITION_ADDON_NUMBER_NotDefined");
256
+            return "";
257
+        }
258
+    }
259
+
260
+    /**
261
+     *  Create expedition en base
262
+     *
263
+     *  @param	User	$user       Objet du user qui cree
264
+     * 	@param		int		$notrigger	1=Does not execute triggers, 0= execute triggers
265
+     *  @return int 				<0 si erreur, id expedition creee si ok
266
+     */
267
+    function create($user, $notrigger=0)
268
+    {
269
+        global $conf, $hookmanager;
270
+
271
+        $now=dol_now();
272
+
273
+        require_once DOL_DOCUMENT_ROOT .'/product/stock/class/mouvementstock.class.php';
274
+        $error = 0;
275
+
276
+        // Clean parameters
277
+        $this->brouillon = 1;
278
+        $this->tracking_number = dol_sanitizeFileName($this->tracking_number);
279
+        if (empty($this->fk_project)) $this->fk_project = 0;
280
+
281
+        $this->user = $user;
282
+
283
+
284
+        $this->db->begin();
285
+
286
+        $sql = "INSERT INTO ".MAIN_DB_PREFIX."expedition (";
287
+        $sql.= "ref";
288
+        $sql.= ", entity";
289
+        $sql.= ", ref_customer";
290
+        $sql.= ", ref_int";
291
+        $sql.= ", date_creation";
292
+        $sql.= ", fk_user_author";
293
+        $sql.= ", date_expedition";
294
+        $sql.= ", date_delivery";
295
+        $sql.= ", fk_soc";
296
+        $sql.= ", fk_projet";
297
+        $sql.= ", fk_address";
298
+        $sql.= ", fk_shipping_method";
299
+        $sql.= ", tracking_number";
300
+        $sql.= ", weight";
301
+        $sql.= ", size";
302
+        $sql.= ", width";
303
+        $sql.= ", height";
304
+        $sql.= ", weight_units";
305
+        $sql.= ", size_units";
306
+        $sql.= ", note_private";
307
+        $sql.= ", note_public";
308
+        $sql.= ", model_pdf";
309
+        $sql.= ", fk_incoterms, location_incoterms";
310
+        $sql.= ") VALUES (";
311
+        $sql.= "'(PROV)'";
312
+        $sql.= ", ".$conf->entity;
313
+        $sql.= ", ".($this->ref_customer?"'".$this->db->escape($this->ref_customer)."'":"null");
314
+        $sql.= ", ".($this->ref_int?"'".$this->db->escape($this->ref_int)."'":"null");
315
+        $sql.= ", '".$this->db->idate($now)."'";
316
+        $sql.= ", ".$user->id;
317
+        $sql.= ", ".($this->date_expedition>0?"'".$this->db->idate($this->date_expedition)."'":"null");
318
+        $sql.= ", ".($this->date_delivery>0?"'".$this->db->idate($this->date_delivery)."'":"null");
319
+        $sql.= ", ".$this->socid;
320
+        $sql.= ", ".$this->fk_project;
321
+        $sql.= ", ".($this->fk_delivery_address>0?$this->fk_delivery_address:"null");
322
+        $sql.= ", ".($this->shipping_method_id>0?$this->shipping_method_id:"null");
323
+        $sql.= ", '".$this->db->escape($this->tracking_number)."'";
324
+        $sql.= ", ".$this->weight;
325
+        $sql.= ", ".$this->sizeS;	// TODO Should use this->trueDepth
326
+        $sql.= ", ".$this->sizeW;	// TODO Should use this->trueWidth
327
+        $sql.= ", ".$this->sizeH;	// TODO Should use this->trueHeight
328
+        $sql.= ", ".$this->weight_units;
329
+        $sql.= ", ".$this->size_units;
330
+        $sql.= ", ".(!empty($this->note_private)?"'".$this->db->escape($this->note_private)."'":"null");
331
+        $sql.= ", ".(!empty($this->note_public)?"'".$this->db->escape($this->note_public)."'":"null");
332
+        $sql.= ", ".(!empty($this->model_pdf)?"'".$this->db->escape($this->model_pdf)."'":"null");
333
+        $sql.= ", ".(int) $this->fk_incoterms;
334
+        $sql.= ", '".$this->db->escape($this->location_incoterms)."'";
335
+        $sql.= ")";
336
+
337
+        dol_syslog(get_class($this)."::create", LOG_DEBUG);
338
+        $resql=$this->db->query($sql);
339
+        if ($resql)
340
+        {
341
+            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."expedition");
342
+
343
+            $sql = "UPDATE ".MAIN_DB_PREFIX."expedition";
344
+            $sql.= " SET ref = '(PROV".$this->id.")'";
345
+            $sql.= " WHERE rowid = ".$this->id;
346
+
347
+            dol_syslog(get_class($this)."::create", LOG_DEBUG);
348
+            if ($this->db->query($sql))
349
+            {
350
+                // Insertion des lignes
351
+                $num=count($this->lines);
352
+                for ($i = 0; $i < $num; $i++)
353
+                {
354
+                    if (! isset($this->lines[$i]->detail_batch))
355
+                    {	// no batch management
356
+                        if (! $this->create_line($this->lines[$i]->entrepot_id, $this->lines[$i]->origin_line_id, $this->lines[$i]->qty, $this->lines[$i]->array_options) > 0)
357
+                        {
358
+                            $error++;
359
+                        }
360
+                    }
361
+                    else
362
+                    {	// with batch management
363
+                        if (! $this->create_line_batch($this->lines[$i],$this->lines[$i]->array_options) > 0)
364
+                        {
365
+                            $error++;
366
+                        }
367
+                    }
368
+                }
369
+
370
+                if (! $error && $this->id && $this->origin_id)
371
+                {
372
+                    $ret = $this->add_object_linked();
373
+                    if (!$ret)
374
+                    {
375
+                        $error++;
376
+                    }
377
+                }
378
+
379
+                // Actions on extra fields
380
+                if (! $error && empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))
381
+                {
382
+                    $result=$this->insertExtraFields();
383
+                    if ($result < 0)
384
+                    {
385
+                        $error++;
386
+                    }
387
+                }
388
+
389
+                if (! $error && ! $notrigger)
390
+                {
391
+                    // Call trigger
392
+                    $result=$this->call_trigger('SHIPPING_CREATE',$user);
393
+                    if ($result < 0) { $error++; }
394
+                    // End call triggers
395
+
396
+                    if (! $error)
397
+                    {
398
+                        $this->db->commit();
399
+                        return $this->id;
400
+                    }
401
+                    else
402
+                    {
403
+                        foreach($this->errors as $errmsg)
404
+                        {
405
+                            dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
406
+                            $this->error.=($this->error?', '.$errmsg:$errmsg);
407
+                        }
408
+                        $this->db->rollback();
409
+                        return -1*$error;
410
+                    }
411
+                }
412
+                else
413
+                {
414
+                    $error++;
415
+                    $this->error=$this->db->lasterror()." - sql=$sql";
416
+                    $this->db->rollback();
417
+                    return -3;
418
+                }
419
+            }
420
+            else
421
+            {
422
+                $error++;
423
+                $this->error=$this->db->lasterror()." - sql=$sql";
424
+                $this->db->rollback();
425
+                return -2;
426
+            }
427
+        }
428
+        else
429
+        {
430
+            $error++;
431
+            $this->error=$this->db->error()." - sql=$sql";
432
+            $this->db->rollback();
433
+            return -1;
434
+        }
435
+    }
1362 436
 
1363 437
     // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1364
-	/**
1365
-	 *	Load lines
1366
-	 *
1367
-	 *	@return	int		>0 if OK, Otherwise if KO
1368
-	 */
1369
-	function fetch_lines()
1370
-	{
1371
-        // phpcs:enable
1372
-		global $conf, $mysoc;
1373
-		// TODO: recuperer les champs du document associe a part
1374
-
1375
-		$sql = "SELECT cd.rowid, cd.fk_product, cd.label as custom_label, cd.description, cd.qty as qty_asked, cd.product_type";
1376
-		$sql.= ", cd.total_ht, cd.total_localtax1, cd.total_localtax2, cd.total_ttc, cd.total_tva";
1377
-		$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";
1378
-		$sql.= ", cd.fk_multicurrency, cd.multicurrency_code, cd.multicurrency_subprice, cd.multicurrency_total_ht, cd.multicurrency_total_tva, cd.multicurrency_total_ttc";
1379
-		$sql.= ", ed.rowid as line_id, ed.qty as qty_shipped, ed.fk_origin_line, ed.fk_entrepot";
1380
-		$sql.= ", p.ref as product_ref, p.label as product_label, p.fk_product_type";
1381
-		$sql.= ", p.weight, p.weight_units, p.length, p.length_units, p.surface, p.surface_units, p.volume, p.volume_units, p.tobatch as product_tobatch";
1382
-		$sql.= " FROM ".MAIN_DB_PREFIX."expeditiondet as ed, ".MAIN_DB_PREFIX."commandedet as cd";
1383
-		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = cd.fk_product";
1384
-		$sql.= " WHERE ed.fk_expedition = ".$this->id;
1385
-		$sql.= " AND ed.fk_origin_line = cd.rowid";
1386
-		$sql.= " ORDER BY cd.rang, ed.fk_origin_line";
1387
-
1388
-		dol_syslog(get_class($this)."::fetch_lines", LOG_DEBUG);
1389
-		$resql = $this->db->query($sql);
1390
-		if ($resql)
1391
-		{
1392
-			include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
1393
-
1394
-			$num = $this->db->num_rows($resql);
1395
-			$i = 0;
1396
-			$lineindex = 0;
1397
-			$originline = 0;
1398
-
1399
-			$this->total_ht = 0;
1400
-			$this->total_tva = 0;
1401
-			$this->total_ttc = 0;
1402
-			$this->total_localtax1 = 0;
1403
-			$this->total_localtax2 = 0;
1404
-
1405
-			while ($i < $num)
1406
-			{
1407
-				$obj = $this->db->fetch_object($resql);
1408
-
1409
-				if ($originline == $obj->fk_origin_line) {
1410
-					$line->entrepot_id       = 0; // entrepod_id in details_entrepot
1411
-					$line->qty_shipped    	+= $obj->qty_shipped;
1412
-				} else {
1413
-					$line = new ExpeditionLigne($this->db);
1414
-					$line->entrepot_id    	= $obj->fk_entrepot;
1415
-					$line->qty_shipped    	= $obj->qty_shipped;
1416
-				}
1417
-
1418
-				$detail_entrepot              = new stdClass;
1419
-				$detail_entrepot->entrepot_id = $obj->fk_entrepot;
1420
-				$detail_entrepot->qty_shipped = $obj->qty_shipped;
1421
-				$detail_entrepot->line_id     = $obj->line_id;
1422
-				$line->details_entrepot[]     = $detail_entrepot;
1423
-
1424
-				$line->line_id          = $obj->line_id;
1425
-				$line->rowid            = $obj->line_id;    // TODO deprecated
1426
-				$line->id               = $obj->line_id;
1427
-
1428
-				$line->fk_origin     	= 'orderline';
1429
-				$line->fk_origin_line 	= $obj->fk_origin_line;
1430
-				$line->origin_line_id 	= $obj->fk_origin_line;	    // TODO deprecated
1431
-
1432
-				$line->fk_expedition    = $this->id;                // id of parent
1433
-
1434
-				$line->product_type     = $obj->product_type;
1435
-				$line->fk_product     	= $obj->fk_product;
1436
-				$line->fk_product_type	= $obj->fk_product_type;
1437
-				$line->ref				= $obj->product_ref;		// TODO deprecated
1438
-				$line->product_ref		= $obj->product_ref;
1439
-				$line->product_label	= $obj->product_label;
1440
-				$line->libelle        	= $obj->product_label;		// TODO deprecated
1441
-				$line->product_tobatch  = $obj->product_tobatch;
1442
-				$line->label			= $obj->custom_label;
1443
-				$line->description    	= $obj->description;
1444
-				$line->qty_asked      	= $obj->qty_asked;
1445
-				$line->weight         	= $obj->weight;
1446
-				$line->weight_units   	= $obj->weight_units;
1447
-				$line->length         	= $obj->length;
1448
-				$line->length_units   	= $obj->length_units;
1449
-				$line->surface        	= $obj->surface;
1450
-				$line->surface_units   	= $obj->surface_units;
1451
-				$line->volume         	= $obj->volume;
1452
-				$line->volume_units   	= $obj->volume_units;
1453
-
1454
-				$line->pa_ht 			= $obj->pa_ht;
1455
-
1456
-				// Local taxes
1457
-				$localtax_array=array(0=>$obj->localtax1_type, 1=>$obj->localtax1_tx, 2=>$obj->localtax2_type, 3=>$obj->localtax2_tx);
1458
-				$localtax1_tx = get_localtax($obj->tva_tx, 1, $this->thirdparty);
1459
-				$localtax2_tx = get_localtax($obj->tva_tx, 2, $this->thirdparty);
1460
-
1461
-				// For invoicing
1462
-				$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);	// We force type to 0
1463
-				$line->desc	         	= $obj->description;		// We need ->desc because some code into CommonObject use desc (property defined for other elements)
1464
-				$line->qty 				= $line->qty_shipped;
1465
-				$line->total_ht			= $tabprice[0];
1466
-				$line->total_localtax1 	= $tabprice[9];
1467
-				$line->total_localtax2 	= $tabprice[10];
1468
-				$line->total_ttc	 	= $tabprice[2];
1469
-				$line->total_tva	 	= $tabprice[1];
1470
-				$line->vat_src_code	 	= $obj->vat_src_code;
1471
-				$line->tva_tx 		 	= $obj->tva_tx;
1472
-				$line->localtax1_tx 	= $obj->localtax1_tx;
1473
-				$line->localtax2_tx 	= $obj->localtax2_tx;
1474
-				$line->info_bits        = $obj->info_bits;
1475
-				$line->price			= $obj->price;
1476
-				$line->subprice			= $obj->subprice;
1477
-				$line->remise_percent	= $obj->remise_percent;
1478
-
1479
-				$this->total_ht+= $tabprice[0];
1480
-				$this->total_tva+= $tabprice[1];
1481
-				$this->total_ttc+= $tabprice[2];
1482
-				$this->total_localtax1+= $tabprice[9];
1483
-				$this->total_localtax2+= $tabprice[10];
1484
-
1485
-				// Multicurrency
1486
-				$this->fk_multicurrency 		= $obj->fk_multicurrency;
1487
-				$this->multicurrency_code 		= $obj->multicurrency_code;
1488
-				$this->multicurrency_subprice 	= $obj->multicurrency_subprice;
1489
-				$this->multicurrency_total_ht 	= $obj->multicurrency_total_ht;
1490
-				$this->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
1491
-				$this->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
1492
-
1493
-				if ($originline != $obj->fk_origin_line)
1494
-				{
1495
-					$line->detail_batch = array();
1496
-				}
1497
-
1498
-				// Detail of batch
1499
-				if (! empty($conf->productbatch->enabled) && $obj->line_id > 0 && $obj->product_tobatch > 0)
1500
-				{
1501
-					require_once DOL_DOCUMENT_ROOT.'/expedition/class/expeditionbatch.class.php';
1502
-
1503
-					$newdetailbatch = ExpeditionLineBatch::fetchAll($this->db, $obj->line_id, $obj->fk_product);
1504
-					if (is_array($newdetailbatch))
1505
-					{
1506
-						if ($originline != $obj->fk_origin_line)
1507
-						{
1508
-							$line->detail_batch = $newdetailbatch;
1509
-						}
1510
-						else
1511
-						{
1512
-							$line->detail_batch = array_merge($line->detail_batch, $newdetailbatch);
1513
-						}
1514
-					}
1515
-				}
1516
-
1517
-				if ($originline != $obj->fk_origin_line)
1518
-				{
1519
-					$this->lines[$lineindex] = $line;
1520
-					$lineindex++;
1521
-				}
1522
-				else
1523
-				{
1524
-					$line->total_ht			+= $tabprice[0];
1525
-					$line->total_localtax1 	+= $tabprice[9];
1526
-					$line->total_localtax2 	+= $tabprice[10];
1527
-					$line->total_ttc	 	+= $tabprice[2];
1528
-					$line->total_tva	 	+= $tabprice[1];
1529
-				}
1530
-
1531
-				$i++;
1532
-				$originline = $obj->fk_origin_line;
1533
-			}
1534
-			$this->db->free($resql);
1535
-			return 1;
1536
-		}
1537
-		else
1538
-		{
1539
-			$this->error=$this->db->error();
1540
-			return -3;
1541
-		}
1542
-	}
1543
-
1544
-	/**
1545
-	 *  Delete detail line
1546
-	 *
1547
-	 *  @param		User	$user			User making deletion
1548
-	 *  @param		int		$lineid			Id of line to delete
1549
-	 *  @return     int         			>0 if OK, <0 if KO
1550
-	 */
1551
-	function deleteline($user, $lineid)
1552
-	{
1553
-		global $user;
1554
-
1555
-		if ($this->statut == self::STATUS_DRAFT)
1556
-		{
1557
-			$this->db->begin();
1558
-
1559
-			$line=new ExpeditionLigne($this->db);
1560
-
1561
-			// For triggers
1562
-			$line->fetch($lineid);
1563
-
1564
-			if ($line->delete($user) > 0)
1565
-			{
1566
-				//$this->update_price(1);
1567
-
1568
-				$this->db->commit();
1569
-				return 1;
1570
-			}
1571
-			else
1572
-			{
1573
-				$this->db->rollback();
1574
-				return -1;
1575
-			}
1576
-		}
1577
-		else
1578
-		{
1579
-			$this->error='ErrorDeleteLineNotAllowedByObjectStatus';
1580
-			return -2;
1581
-		}
1582
-	}
1583
-
1584
-
1585
-	/**
1586
-	 *	Return clicable link of object (with eventually picto)
1587
-	 *
1588
-	 *	@param      int			$withpicto      			Add picto into link
1589
-	 *	@param      string		$option         			Where the link point to
1590
-	 *	@param      int			$max          				Max length to show
1591
-	 *	@param      int			$short						Use short labels
1592
-	 *  @param      int         $notooltip      			1=No tooltip
1593
-	 *  @param      int     	$save_lastsearch_value		-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
1594
-	 *	@return     string          						String with URL
1595
-	 */
1596
-	function getNomUrl($withpicto=0, $option='', $max=0, $short=0, $notooltip=0, $save_lastsearch_value=-1)
1597
-	{
1598
-		global $langs;
1599
-
1600
-		$result='';
1601
-		$label = '<u>' . $langs->trans("ShowSending") . '</u>';
1602
-		$label .= '<br><b>' . $langs->trans('Ref') . ':</b> '.$this->ref;
1603
-		$label .= '<br><b>'.$langs->trans('RefCustomer').':</b> '.($this->ref_customer ? $this->ref_customer : $this->ref_client);
1604
-
1605
-		$url = DOL_URL_ROOT.'/expedition/card.php?id='.$this->id;
1606
-
1607
-		if ($short) return $url;
1608
-
1609
-		if ($option !== 'nolink')
1610
-		{
1611
-			// Add param to save lastsearch_values or not
1612
-			$add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
1613
-			if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
1614
-			if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
1615
-		}
1616
-
1617
-		$linkclose='';
1618
-		if (empty($notooltip))
1619
-		{
1620
-			if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
1621
-			{
1622
-				$label=$langs->trans("ShowSending");
1623
-				$linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"';
1624
-			}
1625
-			$linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
1626
-			$linkclose.=' class="classfortooltip"';
1627
-		}
1628
-
1629
-		$linkstart = '<a href="'.$url.'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';
1630
-		$linkend='</a>';
1631
-
1632
-		$result .= $linkstart;
1633
-		if ($withpicto) $result.=img_object(($notooltip?'':$label), $this->picto, ($notooltip?(($withpicto != 2) ? 'class="paddingright"' : ''):'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip?0:1);
1634
-		if ($withpicto != 2) $result.= $this->ref;
1635
-		$result .= $linkend;
1636
-
1637
-		return $result;
1638
-	}
1639
-
1640
-	/**
1641
-	 *	Return status label
1642
-	 *
1643
-	 *	@param      int		$mode      	0=Long label, 1=Short label, 2=Picto + Short label, 3=Picto, 4=Picto + Long label, 5=Short label + Picto
1644
-	 *	@return     string      		Libelle
1645
-	 */
1646
-	function getLibStatut($mode=0)
1647
-	{
1648
-		return $this->LibStatut($this->statut,$mode);
1649
-	}
438
+    /**
439
+     * Create a expedition line
440
+     *
441
+     * @param 	int		$entrepot_id		Id of warehouse
442
+     * @param 	int		$origin_line_id		Id of source line
443
+     * @param 	int		$qty				Quantity
444
+     * @param	array	$array_options		extrafields array
445
+     * @return	int							<0 if KO, line_id if OK
446
+     */
447
+    function create_line($entrepot_id, $origin_line_id, $qty,$array_options=0)
448
+    {
449
+        //phpcs:enable
450
+        $expeditionline = new ExpeditionLigne($this->db);
451
+        $expeditionline->fk_expedition = $this->id;
452
+        $expeditionline->entrepot_id = $entrepot_id;
453
+        $expeditionline->fk_origin_line = $origin_line_id;
454
+        $expeditionline->qty = $qty;
455
+        $expeditionline->array_options = $array_options;
456
+
457
+        if (($lineId = $expeditionline->insert()) < 0)
458
+        {
459
+            $this->errors[]=$expeditionline->error;
460
+        }
461
+        return $lineId;
462
+    }
463
+
1650 464
 
1651 465
     // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1652
-	/**
1653
-	 * Return label of a status
1654
-	 *
1655
-	 * @param      int		$statut		Id statut
1656
-	 * @param      int		$mode       0=Long label, 1=Short label, 2=Picto + Short label, 3=Picto, 4=Picto + Long label, 5=Short label + Picto
1657
-	 * @return     string				Label of status
1658
-	 */
1659
-	function LibStatut($statut,$mode)
1660
-	{
466
+    /**
467
+     * Create the detail (eat-by date) of the expedition line
468
+     *
469
+     * @param 	object		$line_ext		full line informations
470
+     * @param	array		$array_options		extrafields array
471
+     * @return	int							<0 if KO, >0 if OK
472
+     */
473
+    function create_line_batch($line_ext,$array_options=0)
474
+    {
1661 475
         // phpcs:enable
1662
-		global $langs;
476
+        $error = 0;
477
+        $stockLocationQty = array(); // associated array with batch qty in stock location
478
+
479
+        $tab=$line_ext->detail_batch;
480
+        // create stockLocation Qty array
481
+        foreach ($tab as $detbatch)
482
+        {
483
+            if ($detbatch->entrepot_id)
484
+            {
485
+                $stockLocationQty[$detbatch->entrepot_id] += $detbatch->qty;
486
+            }
487
+        }
488
+        // create shipment lines
489
+        foreach ($stockLocationQty as $stockLocation => $qty)
490
+        {
491
+            if (($line_id = $this->create_line($stockLocation,$line_ext->origin_line_id,$qty,$array_options)) < 0)
492
+            {
493
+                $error++;
494
+            }
495
+            else
496
+            {
497
+                // create shipment batch lines for stockLocation
498
+                foreach ($tab as $detbatch)
499
+                {
500
+                    if ($detbatch->entrepot_id == $stockLocation){
501
+                        if (! ($detbatch->create($line_id) >0))		// Create an expeditionlinebatch
502
+                        {
503
+                            $error++;
504
+                        }
505
+                    }
506
+                }
507
+            }
508
+        }
509
+
510
+        if (! $error) return 1;
511
+        else return -1;
512
+    }
513
+
514
+    /**
515
+     *	Get object and lines from database
516
+     *
517
+     *	@param	int		$id       	Id of object to load
518
+     * 	@param	string	$ref		Ref of object
519
+     * 	@param	string	$ref_ext	External reference of object
520
+     * 	@param	string	$ref_int	Internal reference of other object
521
+     *	@return int			        >0 if OK, 0 if not found, <0 if KO
522
+     */
523
+    function fetch($id, $ref='', $ref_ext='', $ref_int='')
524
+    {
525
+        global $conf;
526
+
527
+        // Check parameters
528
+        if (empty($id) && empty($ref) && empty($ref_ext) && empty($ref_int)) return -1;
529
+
530
+        $sql = "SELECT e.rowid, 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, e.billed";
531
+        $sql.= ", e.weight, e.weight_units, e.size, e.size_units, e.width, e.height";
532
+        $sql.= ", e.date_expedition as date_expedition, e.model_pdf, e.fk_address, e.date_delivery";
533
+        $sql.= ", e.fk_shipping_method, e.tracking_number";
534
+        $sql.= ", e.note_private, e.note_public";
535
+        $sql.= ', e.fk_incoterms, e.location_incoterms';
536
+        $sql.= ', i.libelle as libelle_incoterms';
537
+        $sql.= ', s.libelle as shipping_method';
538
+        $sql.= ", el.fk_source as origin_id, el.sourcetype as origin";
539
+        $sql.= " FROM ".MAIN_DB_PREFIX."expedition as e";
540
+        $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."element_element as el ON el.fk_target = e.rowid AND el.targettype = '".$this->db->escape($this->element)."'";
541
+        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_incoterms as i ON e.fk_incoterms = i.rowid';
542
+        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_shipment_mode as s ON e.fk_shipping_method = s.rowid';
543
+        $sql.= " WHERE e.entity IN (".getEntity('expedition').")";
544
+        if ($id)   	  $sql.= " AND e.rowid=".$id;
545
+        if ($ref)     $sql.= " AND e.ref='".$this->db->escape($ref)."'";
546
+        if ($ref_ext) $sql.= " AND e.ref_ext='".$this->db->escape($ref_ext)."'";
547
+        if ($ref_int) $sql.= " AND e.ref_int='".$this->db->escape($ref_int)."'";
548
+
549
+        dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
550
+        $result = $this->db->query($sql);
551
+        if ($result)
552
+        {
553
+            if ($this->db->num_rows($result))
554
+            {
555
+                $obj = $this->db->fetch_object($result);
556
+
557
+                $this->id                   = $obj->rowid;
558
+                $this->ref                  = $obj->ref;
559
+                $this->socid                = $obj->socid;
560
+                $this->ref_customer	    = $obj->ref_customer;
561
+                $this->ref_ext		    = $obj->ref_ext;
562
+                $this->ref_int		    = $obj->ref_int;
563
+                $this->statut               = $obj->fk_statut;
564
+                $this->user_author_id       = $obj->fk_user_author;
565
+                $this->date_creation        = $this->db->jdate($obj->date_creation);
566
+                $this->date                 = $this->db->jdate($obj->date_expedition);	// TODO deprecated
567
+                $this->date_expedition      = $this->db->jdate($obj->date_expedition);	// TODO deprecated
568
+                $this->date_shipping        = $this->db->jdate($obj->date_expedition);	// Date real
569
+                $this->date_delivery        = $this->db->jdate($obj->date_delivery);	// Date planed
570
+                $this->fk_delivery_address  = $obj->fk_address;
571
+                $this->modelpdf             = $obj->model_pdf;
572
+                $this->shipping_method_id   = $obj->fk_shipping_method;
573
+                $this->shipping_method	    = $obj->shipping_method;
574
+                $this->tracking_number      = $obj->tracking_number;
575
+                $this->origin               = ($obj->origin?$obj->origin:'commande'); // For compatibility
576
+                $this->origin_id            = $obj->origin_id;
577
+                $this->billed               = $obj->billed;
578
+                $this->fk_project	    = $obj->fk_projet;
579
+
580
+                $this->trueWeight           = $obj->weight;
581
+                $this->weight_units         = $obj->weight_units;
582
+
583
+                $this->trueWidth            = $obj->width;
584
+                $this->width_units          = $obj->size_units;
585
+                $this->trueHeight           = $obj->height;
586
+                $this->height_units         = $obj->size_units;
587
+                $this->trueDepth            = $obj->size;
588
+                $this->depth_units          = $obj->size_units;
589
+
590
+                $this->note_public          = $obj->note_public;
591
+                $this->note_private         = $obj->note_private;
592
+
593
+                // A denormalized value
594
+                $this->trueSize             = $obj->size."x".$obj->width."x".$obj->height;
595
+                $this->size_units           = $obj->size_units;
596
+
597
+                //Incoterms
598
+                $this->fk_incoterms         = $obj->fk_incoterms;
599
+                $this->location_incoterms   = $obj->location_incoterms;
600
+                $this->libelle_incoterms    = $obj->libelle_incoterms;
601
+
602
+                $this->db->free($result);
603
+
604
+                if ($this->statut == 0) $this->brouillon = 1;
605
+
606
+                // Tracking url
607
+                $this->getUrlTrackingStatus($obj->tracking_number);
608
+
609
+                /*
610
+				 * Thirparty
611
+				 */
612
+                $result=$this->fetch_thirdparty();
613
+
614
+                // Retreive extrafields
615
+                $this->fetch_optionals();
616
+
617
+                /*
618
+				 * Lines
619
+				 */
620
+                $result=$this->fetch_lines();
621
+                if ($result < 0)
622
+                {
623
+                    return -3;
624
+                }
625
+
626
+                return 1;
627
+            }
628
+            else
629
+            {
630
+                dol_syslog(get_class($this).'::Fetch no expedition found', LOG_ERR);
631
+                $this->error='Delivery with id '.$id.' not found';
632
+                return 0;
633
+            }
634
+        }
635
+        else
636
+        {
637
+            $this->error=$this->db->error();
638
+            return -1;
639
+        }
640
+    }
641
+
642
+    /**
643
+     *  Validate object and update stock if option enabled
644
+     *
645
+     *  @param      User		$user       Object user that validate
646
+     *  @param		int			$notrigger	1=Does not execute triggers, 0= execute triggers
647
+     *  @return     int						<0 if OK, >0 if KO
648
+     */
649
+    function valid($user, $notrigger=0)
650
+    {
651
+        global $conf, $langs;
652
+
653
+        require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
654
+
655
+        dol_syslog(get_class($this)."::valid");
656
+
657
+        // Protection
658
+        if ($this->statut)
659
+        {
660
+            dol_syslog(get_class($this)."::valid no draft status", LOG_WARNING);
661
+            return 0;
662
+        }
663
+
664
+        if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->creer))
665
+           || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->shipping_advance->validate))))
666
+        {
667
+            $this->error='Permission denied';
668
+            dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
669
+            return -1;
670
+        }
671
+
672
+        $this->db->begin();
673
+
674
+        $error = 0;
675
+
676
+        // Define new ref
677
+        $soc = new Societe($this->db);
678
+        $soc->fetch($this->socid);
679
+
680
+        // Class of company linked to order
681
+        $result=$soc->set_as_client();
682
+
683
+        // Define new ref
684
+        if (! $error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life
685
+        {
686
+            $numref = $this->getNextNumRef($soc);
687
+        }
688
+        else
689
+        {
690
+            $numref = "EXP".$this->id;
691
+        }
692
+        $this->newref = $numref;
693
+
694
+        $now=dol_now();
695
+
696
+        // Validate
697
+        $sql = "UPDATE ".MAIN_DB_PREFIX."expedition SET";
698
+        $sql.= " ref='".$numref."'";
699
+        $sql.= ", fk_statut = 1";
700
+        $sql.= ", date_valid = '".$this->db->idate($now)."'";
701
+        $sql.= ", fk_user_valid = ".$user->id;
702
+        $sql.= " WHERE rowid = ".$this->id;
703
+
704
+        dol_syslog(get_class($this)."::valid update expedition", LOG_DEBUG);
705
+        $resql=$this->db->query($sql);
706
+        if (! $resql)
707
+        {
708
+            $this->error=$this->db->lasterror();
709
+            $error++;
710
+        }
711
+
712
+        // If stock increment is done on sending (recommanded choice)
713
+        if (! $error && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT))
714
+        {
715
+            require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
716
+
717
+            $langs->load("agenda");
718
+
719
+            // Loop on each product line to add a stock movement
720
+            $sql = "SELECT cd.fk_product, cd.subprice,";
721
+            $sql.= " ed.rowid, ed.qty, ed.fk_entrepot,";
722
+            $sql.= " edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
723
+            $sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd,";
724
+            $sql.= " ".MAIN_DB_PREFIX."expeditiondet as ed";
725
+            $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
726
+            $sql.= " WHERE ed.fk_expedition = ".$this->id;
727
+            $sql.= " AND cd.rowid = ed.fk_origin_line";
728
+
729
+            dol_syslog(get_class($this)."::valid select details", LOG_DEBUG);
730
+            $resql=$this->db->query($sql);
731
+            if ($resql)
732
+            {
733
+                $cpt = $this->db->num_rows($resql);
734
+                for ($i = 0; $i < $cpt; $i++)
735
+                {
736
+                    $obj = $this->db->fetch_object($resql);
737
+                    if (empty($obj->edbrowid))
738
+                    {
739
+                        $qty = $obj->qty;
740
+                    }
741
+                    else
742
+                    {
743
+                        $qty = $obj->edbqty;
744
+                    }
745
+                    if ($qty <= 0) continue;
746
+                    dol_syslog(get_class($this)."::valid movement index ".$i." ed.rowid=".$obj->rowid." edb.rowid=".$obj->edbrowid);
747
+
748
+                    //var_dump($this->lines[$i]);
749
+                    $mouvS = new MouvementStock($this->db);
750
+                    $mouvS->origin = &$this;
751
+
752
+                    if (empty($obj->edbrowid))
753
+                    {
754
+                        // line without batch detail
755
+
756
+                        // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record.
757
+                        $result=$mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans("ShipmentValidatedInDolibarr",$numref));
758
+                        if ($result < 0) {
759
+                            $error++;
760
+                            $this->errors[]=$mouvS->error;
761
+                            $this->errors = array_merge($this->errors, $mouvS->errors);
762
+                            break;
763
+                        }
764
+                    }
765
+                    else
766
+                    {
767
+                        // line with batch detail
768
+
769
+                        // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record.
770
+                        // Note: ->fk_origin_stock = id into table llx_product_batch (may be rename into llx_product_stock_batch in another version)
771
+                        $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);
772
+                        if ($result < 0) {
773
+                            $error++;
774
+                            $this->errors[]=$mouvS->error;
775
+                            $this->errors = array_merge($this->errors, $mouvS->errors);
776
+                            break;
777
+                        }
778
+                    }
779
+                }
780
+            }
781
+            else
782
+            {
783
+                $this->db->rollback();
784
+                $this->error=$this->db->error();
785
+                return -2;
786
+            }
787
+        }
788
+
789
+        // Change status of order to "shipment in process"
790
+        $ret = $this->setStatut(Commande::STATUS_SHIPMENTONPROCESS, $this->origin_id, $this->origin);
791
+
792
+        if (! $ret)
793
+        {
794
+            $error++;
795
+        }
796
+
797
+        if (! $error && ! $notrigger)
798
+        {
799
+            // Call trigger
800
+            $result=$this->call_trigger('SHIPPING_VALIDATE',$user);
801
+            if ($result < 0) { $error++; }
802
+            // End call triggers
803
+        }
804
+
805
+        if (! $error)
806
+        {
807
+            $this->oldref = $this->ref;
808
+
809
+            // Rename directory if dir was a temporary ref
810
+            if (preg_match('/^[\(]?PROV/i', $this->ref))
811
+            {
812
+                // On renomme repertoire ($this->ref = ancienne ref, $numfa = nouvelle ref)
813
+                // in order not to lose the attached files
814
+                $oldref = dol_sanitizeFileName($this->ref);
815
+                $newref = dol_sanitizeFileName($numref);
816
+                $dirsource = $conf->expedition->dir_output.'/sending/'.$oldref;
817
+                $dirdest = $conf->expedition->dir_output.'/sending/'.$newref;
818
+                if (file_exists($dirsource))
819
+                {
820
+                    dol_syslog(get_class($this)."::valid rename dir ".$dirsource." into ".$dirdest);
821
+
822
+                    if (@rename($dirsource, $dirdest))
823
+                    {
824
+                        dol_syslog("Rename ok");
825
+                        // Rename docs starting with $oldref with $newref
826
+                        $listoffiles=dol_dir_list($conf->expedition->dir_output.'/sending/'.$newref, 'files', 1, '^'.preg_quote($oldref,'/'));
827
+                        foreach($listoffiles as $fileentry)
828
+                        {
829
+                            $dirsource=$fileentry['name'];
830
+                            $dirdest=preg_replace('/^'.preg_quote($oldref,'/').'/',$newref, $dirsource);
831
+                            $dirsource=$fileentry['path'].'/'.$dirsource;
832
+                            $dirdest=$fileentry['path'].'/'.$dirdest;
833
+                            @rename($dirsource, $dirdest);
834
+                        }
835
+                    }
836
+                }
837
+            }
838
+        }
839
+
840
+        // Set new ref and current status
841
+        if (! $error)
842
+        {
843
+            $this->ref = $numref;
844
+            $this->statut = 1;
845
+        }
846
+
847
+        if (! $error)
848
+        {
849
+            $this->db->commit();
850
+            return 1;
851
+        }
852
+        else
853
+        {
854
+            foreach($this->errors as $errmsg)
855
+            {
856
+                dol_syslog(get_class($this)."::valid ".$errmsg, LOG_ERR);
857
+                $this->error.=($this->error?', '.$errmsg:$errmsg);
858
+            }
859
+            $this->db->rollback();
860
+            return -1*$error;
861
+        }
862
+    }
1663 863
 
1664
-		if ($mode==0)
1665
-		{
1666
-			if ($statut==0) return $langs->trans($this->statuts[$statut]);
1667
-			elseif ($statut==1) return $langs->trans($this->statuts[$statut]);
1668
-			elseif ($statut==2) return $langs->trans($this->statuts[$statut]);
1669
-		}
1670
-		elseif ($mode==1)
1671
-		{
1672
-			if ($statut==0) return $langs->trans($this->statutshorts[$statut]);
1673
-			elseif ($statut==1) return $langs->trans($this->statutshorts[$statut]);
1674
-			elseif ($statut==2) return $langs->trans($this->statutshorts[$statut]);
1675
-		}
1676
-		elseif ($mode == 3)
1677
-		{
1678
-			if ($statut==0) return img_picto($langs->trans($this->statuts[$statut]),'statut0');
1679
-			elseif ($statut==1) return img_picto($langs->trans($this->statuts[$statut]),'statut4');
1680
-			elseif ($statut==2) return img_picto($langs->trans($this->statuts[$statut]),'statut6');
1681
-		}
1682
-		elseif ($mode == 4)
1683
-		{
1684
-			if ($statut==0) return img_picto($langs->trans($this->statuts[$statut]),'statut0').' '.$langs->trans($this->statuts[$statut]);
1685
-			elseif ($statut==1) return img_picto($langs->trans($this->statuts[$statut]),'statut4').' '.$langs->trans($this->statuts[$statut]);
1686
-			elseif ($statut==2) return img_picto($langs->trans($this->statuts[$statut]),'statut6').' '.$langs->trans($this->statuts[$statut]);
1687
-		}
1688
-		elseif ($mode == 5)
1689
-		{
1690
-			if ($statut==0) return $langs->trans($this->statutshorts[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]),'statut0');
1691
-			elseif ($statut==1) return $langs->trans($this->statutshorts[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]),'statut4');
1692
-			elseif ($statut==2) return $langs->trans($this->statutshorts[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]),'statut6');
1693
-		}
1694
-	}
1695
-
1696
-	/**
1697
-	 *  Initialise an instance with random values.
1698
-	 *  Used to build previews or test instances.
1699
-	 *	id must be 0 if object instance is a specimen.
1700
-	 *
1701
-	 *  @return	void
1702
-	 */
1703
-	function initAsSpecimen()
1704
-	{
1705
-		global $langs;
1706
-
1707
-		$now=dol_now();
1708
-
1709
-		dol_syslog(get_class($this)."::initAsSpecimen");
1710
-
1711
-		// Load array of products prodids
1712
-		$num_prods = 0;
1713
-		$prodids = array();
1714
-		$sql = "SELECT rowid";
1715
-		$sql.= " FROM ".MAIN_DB_PREFIX."product";
1716
-		$sql.= " WHERE entity IN (".getEntity('product').")";
1717
-		$resql = $this->db->query($sql);
1718
-		if ($resql)
1719
-		{
1720
-			$num_prods = $this->db->num_rows($resql);
1721
-			$i = 0;
1722
-			while ($i < $num_prods)
1723
-			{
1724
-				$i++;
1725
-				$row = $this->db->fetch_row($resql);
1726
-				$prodids[$i] = $row[0];
1727
-			}
1728
-		}
1729
-
1730
-		$order=new Commande($this->db);
1731
-		$order->initAsSpecimen();
1732
-
1733
-		// Initialise parametres
1734
-		$this->id=0;
1735
-		$this->ref = 'SPECIMEN';
1736
-		$this->specimen=1;
1737
-		$this->statut               = 1;
1738
-		$this->livraison_id         = 0;
1739
-		$this->date                 = $now;
1740
-		$this->date_creation        = $now;
1741
-		$this->date_valid           = $now;
1742
-		$this->date_delivery        = $now;
1743
-		$this->date_expedition      = $now + 24*3600;
1744
-
1745
-		$this->entrepot_id          = 0;
1746
-		$this->fk_delivery_address  = 0;
1747
-		$this->socid                = 1;
1748
-
1749
-		$this->commande_id          = 0;
1750
-		$this->commande             = $order;
1751
-
1752
-		$this->origin_id            = 1;
1753
-		$this->origin               = 'commande';
1754
-
1755
-		$this->note_private			= 'Private note';
1756
-		$this->note_public			= 'Public note';
1757
-
1758
-		$nbp = 5;
1759
-		$xnbp = 0;
1760
-		while ($xnbp < $nbp)
1761
-		{
1762
-			$line=new ExpeditionLigne($this->db);
1763
-			$line->desc=$langs->trans("Description")." ".$xnbp;
1764
-			$line->libelle=$langs->trans("Description")." ".$xnbp;
1765
-			$line->qty=10;
1766
-			$line->qty_asked=5;
1767
-			$line->qty_shipped=4;
1768
-			$line->fk_product=$this->commande->lines[$xnbp]->fk_product;
1769
-
1770
-			$this->lines[]=$line;
1771
-			$xnbp++;
1772
-		}
1773
-	}
1774 864
 
1775 865
     // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1776
-	/**
1777
-	 *	Set the planned delivery date
1778
-	 *
1779
-	 *	@param      User			$user        		Objet utilisateur qui modifie
1780
-	 *	@param      timestamp		$date_livraison     Date de livraison
1781
-	 *	@return     int         						<0 if KO, >0 if OK
1782
-	 */
1783
-	function set_date_livraison($user, $date_livraison)
1784
-	{
866
+    /**
867
+     *	Create a delivery receipt from a shipment
868
+     *
869
+     *	@param	User	$user       User
870
+     *  @return int  				<0 if KO, >=0 if OK
871
+     */
872
+    function create_delivery($user)
873
+    {
1785 874
         // phpcs:enable
1786
-		if ($user->rights->expedition->creer)
1787
-		{
1788
-			$sql = "UPDATE ".MAIN_DB_PREFIX."expedition";
1789
-			$sql.= " SET date_delivery = ".($date_livraison ? "'".$this->db->idate($date_livraison)."'" : 'null');
1790
-			$sql.= " WHERE rowid = ".$this->id;
1791
-
1792
-			dol_syslog(get_class($this)."::set_date_livraison", LOG_DEBUG);
1793
-			$resql=$this->db->query($sql);
1794
-			if ($resql)
1795
-			{
1796
-				$this->date_delivery = $date_livraison;
1797
-				return 1;
1798
-			}
1799
-			else
1800
-			{
1801
-				$this->error=$this->db->error();
1802
-				return -1;
1803
-			}
1804
-		}
1805
-		else
1806
-		{
1807
-			return -2;
1808
-		}
1809
-	}
875
+        global $conf;
876
+
877
+        if ($conf->livraison_bon->enabled)
878
+        {
879
+            if ($this->statut == 1 || $this->statut == 2)
880
+            {
881
+                // Expedition validee
882
+                include_once DOL_DOCUMENT_ROOT.'/livraison/class/livraison.class.php';
883
+                $delivery = new Livraison($this->db);
884
+                $result=$delivery->create_from_sending($user, $this->id);
885
+                if ($result > 0)
886
+                {
887
+                    return $result;
888
+                }
889
+                else
890
+                {
891
+                    $this->error=$delivery->error;
892
+                    return $result;
893
+                }
894
+            }
895
+            else return 0;
896
+        }
897
+        else return 0;
898
+    }
899
+
900
+    /**
901
+     * Add an expedition line.
902
+     * If STOCK_WAREHOUSE_NOT_REQUIRED_FOR_SHIPMENTS is set, you can add a shipment line, with no stock source defined
903
+     * If STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT is not set, you can add a shipment line, even if not enough into stock
904
+     *
905
+     * @param 	int		$entrepot_id		Id of warehouse
906
+     * @param 	int		$id					Id of source line (order line)
907
+     * @param 	int		$qty				Quantity
908
+     * @param	array	$array_options		extrafields array
909
+     * @return	int							<0 if KO, >0 if OK
910
+     */
911
+    function addline($entrepot_id, $id, $qty,$array_options=0)
912
+    {
913
+        global $conf, $langs;
914
+
915
+        $num = count($this->lines);
916
+        $line = new ExpeditionLigne($this->db);
917
+
918
+        $line->entrepot_id = $entrepot_id;
919
+        $line->origin_line_id = $id;
920
+        $line->qty = $qty;
921
+
922
+        $orderline = new OrderLine($this->db);
923
+        $orderline->fetch($id);
924
+
925
+        if (! empty($conf->stock->enabled) && ! empty($orderline->fk_product))
926
+        {
927
+            $fk_product = $orderline->fk_product;
928
+
929
+            if (! ($entrepot_id > 0) && empty($conf->global->STOCK_WAREHOUSE_NOT_REQUIRED_FOR_SHIPMENTS))
930
+            {
931
+                $langs->load("errors");
932
+                $this->error=$langs->trans("ErrorWarehouseRequiredIntoShipmentLine");
933
+                return -1;
934
+            }
935
+
936
+            if ($conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT)
937
+            {
938
+                // Check must be done for stock of product into warehouse if $entrepot_id defined
939
+                $product=new Product($this->db);
940
+                $result=$product->fetch($fk_product);
941
+
942
+                if ($entrepot_id > 0) {
943
+                    $product->load_stock('warehouseopen');
944
+                    $product_stock = $product->stock_warehouse[$entrepot_id]->real;
945
+                }
946
+                else
947
+                    $product_stock = $product->stock_reel;
948
+
949
+                $product_type=$product->type;
950
+                if ($product_type == 0 && $product_stock < $qty)
951
+                {
952
+                    $langs->load("errors");
953
+                    $this->error=$langs->trans('ErrorStockIsNotEnoughToAddProductOnShipment', $product->ref);
954
+                    $this->db->rollback();
955
+                    return -3;
956
+                }
957
+            }
958
+        }
959
+
960
+        // If product need a batch number, we should not have called this function but addline_batch instead.
961
+        if (! empty($conf->productbatch->enabled) && ! empty($orderline->fk_product) && ! empty($orderline->product_tobatch))
962
+        {
963
+            $this->error='ADDLINE_WAS_CALLED_INSTEAD_OF_ADDLINEBATCH';
964
+            return -4;
965
+        }
966
+
967
+        // extrafields
968
+        if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options)>0) // For avoid conflicts if trigger used
969
+            $line->array_options = $array_options;
970
+
971
+        $this->lines[$num] = $line;
972
+    }
1810 973
 
1811 974
     // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1812
-	/**
1813
-	 *	Fetch deliveries method and return an array. Load array this->meths(rowid=>label).
1814
-	 *
1815
-	 * 	@return	void
1816
-	 */
1817
-	function fetch_delivery_methods()
1818
-	{
975
+    /**
976
+     * Add a shipment line with batch record
977
+     *
978
+     * @param 	array		$dbatch		Array of value (key 'detail' -> Array, key 'qty' total quantity for line, key ix_l : original line index)
979
+     * @param	array		$array_options		extrafields array
980
+     * @return	int						<0 if KO, >0 if OK
981
+     */
982
+    function addline_batch($dbatch,$array_options=0)
983
+    {
1819 984
         // phpcs:enable
1820
-		global $langs;
1821
-		$this->meths = array();
985
+        global $conf,$langs;
986
+
987
+        $num = count($this->lines);
988
+        if ($dbatch['qty']>0)
989
+        {
990
+            $line = new ExpeditionLigne($this->db);
991
+            $tab=array();
992
+            foreach ($dbatch['detail'] as $key=>$value)
993
+            {
994
+                if ($value['q']>0)
995
+                {
996
+                    // $value['q']=qty to move
997
+                    // $value['id_batch']=id into llx_product_batch of record to move
998
+                    //var_dump($value);
999
+
1000
+                    $linebatch = new ExpeditionLineBatch($this->db);
1001
+                    $ret=$linebatch->fetchFromStock($value['id_batch']);	// load serial, sellby, eatby
1002
+                    if ($ret<0)
1003
+                    {
1004
+                        $this->error=$linebatch->error;
1005
+                        return -1;
1006
+                    }
1007
+                    $linebatch->qty=$value['q'];
1008
+                    $tab[]=$linebatch;
1009
+
1010
+                    if ($conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT)
1011
+                    {
1012
+                        require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
1013
+                        $prod_batch = new Productbatch($this->db);
1014
+                        $prod_batch->fetch($value['id_batch']);
1015
+
1016
+                        if ($prod_batch->qty < $linebatch->qty)
1017
+                        {
1018
+                            $langs->load("errors");
1019
+                            $this->errors[]=$langs->trans('ErrorStockIsNotEnoughToAddProductOnShipment', $prod_batch->fk_product);
1020
+                            dol_syslog(get_class($this)."::addline_batch error=Product ".$prod_batch->batch.": ".$this->errorsToString(), LOG_ERR);
1021
+                            $this->db->rollback();
1022
+                            return -1;
1023
+                        }
1024
+                    }
1025
+
1026
+                    //var_dump($linebatch);
1027
+                }
1028
+            }
1029
+            $line->entrepot_id = $linebatch->entrepot_id;
1030
+            $line->origin_line_id = $dbatch['ix_l'];
1031
+            $line->qty = $dbatch['qty'];
1032
+            $line->detail_batch=$tab;
1033
+
1034
+            // extrafields
1035
+            if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options)>0) // For avoid conflicts if trigger used
1036
+                $line->array_options = $array_options;
1037
+
1038
+            //var_dump($line);
1039
+            $this->lines[$num] = $line;
1040
+            return 1;
1041
+        }
1042
+    }
1822 1043
 
1823
-		$sql = "SELECT em.rowid, em.code, em.libelle";
1824
-		$sql.= " FROM ".MAIN_DB_PREFIX."c_shipment_mode as em";
1825
-		$sql.= " WHERE em.active = 1";
1826
-		$sql.= " ORDER BY em.libelle ASC";
1044
+    /**
1045
+     *  Update database
1046
+     *
1047
+     *  @param	User	$user        	User that modify
1048
+     *  @param  int		$notrigger	    0=launch triggers after, 1=disable triggers
1049
+     *  @return int 			       	<0 if KO, >0 if OK
1050
+     */
1051
+    function update($user=null, $notrigger=0)
1052
+    {
1053
+        global $conf;
1054
+        $error=0;
1055
+
1056
+        // Clean parameters
1057
+
1058
+        if (isset($this->ref)) $this->ref=trim($this->ref);
1059
+        if (isset($this->entity)) $this->entity=trim($this->entity);
1060
+        if (isset($this->ref_customer)) $this->ref_customer=trim($this->ref_customer);
1061
+        if (isset($this->socid)) $this->socid=trim($this->socid);
1062
+        if (isset($this->fk_user_author)) $this->fk_user_author=trim($this->fk_user_author);
1063
+        if (isset($this->fk_user_valid)) $this->fk_user_valid=trim($this->fk_user_valid);
1064
+        if (isset($this->fk_delivery_address)) $this->fk_delivery_address=trim($this->fk_delivery_address);
1065
+        if (isset($this->shipping_method_id)) $this->shipping_method_id=trim($this->shipping_method_id);
1066
+        if (isset($this->tracking_number)) $this->tracking_number=trim($this->tracking_number);
1067
+        if (isset($this->statut)) $this->statut=(int) $this->statut;
1068
+        if (isset($this->trueDepth)) $this->trueDepth=trim($this->trueDepth);
1069
+        if (isset($this->trueWidth)) $this->trueWidth=trim($this->trueWidth);
1070
+        if (isset($this->trueHeight)) $this->trueHeight=trim($this->trueHeight);
1071
+        if (isset($this->size_units)) $this->size_units=trim($this->size_units);
1072
+        if (isset($this->weight_units)) $this->weight_units=trim($this->weight_units);
1073
+        if (isset($this->trueWeight)) $this->weight=trim($this->trueWeight);
1074
+        if (isset($this->note_private)) $this->note=trim($this->note_private);
1075
+        if (isset($this->note_public)) $this->note=trim($this->note_public);
1076
+        if (isset($this->modelpdf)) $this->modelpdf=trim($this->modelpdf);
1077
+
1078
+
1079
+
1080
+        // Check parameters
1081
+        // Put here code to add control on parameters values
1082
+
1083
+        // Update request
1084
+        $sql = "UPDATE ".MAIN_DB_PREFIX."expedition SET";
1085
+
1086
+        $sql.= " tms=".(dol_strlen($this->tms)!=0 ? "'".$this->db->idate($this->tms)."'" : 'null').",";
1087
+        $sql.= " ref=".(isset($this->ref)?"'".$this->db->escape($this->ref)."'":"null").",";
1088
+        $sql.= " ref_customer=".(isset($this->ref_customer)?"'".$this->db->escape($this->ref_customer)."'":"null").",";
1089
+        $sql.= " fk_soc=".(isset($this->socid)?$this->socid:"null").",";
1090
+        $sql.= " date_creation=".(dol_strlen($this->date_creation)!=0 ? "'".$this->db->idate($this->date_creation)."'" : 'null').",";
1091
+        $sql.= " fk_user_author=".(isset($this->fk_user_author)?$this->fk_user_author:"null").",";
1092
+        $sql.= " date_valid=".(dol_strlen($this->date_valid)!=0 ? "'".$this->db->idate($this->date_valid)."'" : 'null').",";
1093
+        $sql.= " fk_user_valid=".(isset($this->fk_user_valid)?$this->fk_user_valid:"null").",";
1094
+        $sql.= " date_expedition=".(dol_strlen($this->date_expedition)!=0 ? "'".$this->db->idate($this->date_expedition)."'" : 'null').",";
1095
+        $sql.= " date_delivery=".(dol_strlen($this->date_delivery)!=0 ? "'".$this->db->idate($this->date_delivery)."'" : 'null').",";
1096
+        $sql.= " fk_address=".(isset($this->fk_delivery_address)?$this->fk_delivery_address:"null").",";
1097
+        $sql.= " fk_shipping_method=".((isset($this->shipping_method_id) && $this->shipping_method_id > 0)?$this->shipping_method_id:"null").",";
1098
+        $sql.= " tracking_number=".(isset($this->tracking_number)?"'".$this->db->escape($this->tracking_number)."'":"null").",";
1099
+        $sql.= " fk_statut=".(isset($this->statut)?$this->statut:"null").",";
1100
+        $sql.= " fk_projet=".(isset($this->fk_project)?$this->fk_project:"null").",";
1101
+        $sql.= " height=".(($this->trueHeight != '')?$this->trueHeight:"null").",";
1102
+        $sql.= " width=".(($this->trueWidth != '')?$this->trueWidth:"null").",";
1103
+        $sql.= " size_units=".(isset($this->size_units)?$this->size_units:"null").",";
1104
+        $sql.= " size=".(($this->trueDepth != '')?$this->trueDepth:"null").",";
1105
+        $sql.= " weight_units=".(isset($this->weight_units)?$this->weight_units:"null").",";
1106
+        $sql.= " weight=".(($this->trueWeight != '')?$this->trueWeight:"null").",";
1107
+        $sql.= " note_private=".(isset($this->note_private)?"'".$this->db->escape($this->note_private)."'":"null").",";
1108
+        $sql.= " note_public=".(isset($this->note_public)?"'".$this->db->escape($this->note_public)."'":"null").",";
1109
+        $sql.= " model_pdf=".(isset($this->modelpdf)?"'".$this->db->escape($this->modelpdf)."'":"null").",";
1110
+        $sql.= " entity=".$conf->entity;
1111
+
1112
+        $sql.= " WHERE rowid=".$this->id;
1113
+
1114
+        $this->db->begin();
1115
+
1116
+        dol_syslog(get_class($this)."::update", LOG_DEBUG);
1117
+        $resql = $this->db->query($sql);
1118
+        if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
1119
+
1120
+        if (! $error)
1121
+        {
1122
+            if (! $notrigger)
1123
+            {
1124
+                // Call trigger
1125
+                $result=$this->call_trigger('SHIPPING_MODIFY',$user);
1126
+                if ($result < 0) { $error++; }
1127
+                // End call triggers
1128
+            }
1129
+        }
1130
+
1131
+        // Commit or rollback
1132
+        if ($error)
1133
+        {
1134
+            foreach($this->errors as $errmsg)
1135
+            {
1136
+                dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
1137
+                $this->error.=($this->error?', '.$errmsg:$errmsg);
1138
+            }
1139
+            $this->db->rollback();
1140
+            return -1*$error;
1141
+        }
1142
+        else
1143
+        {
1144
+            $this->db->commit();
1145
+            return 1;
1146
+        }
1147
+    }
1827 1148
 
1828
-		$resql = $this->db->query($sql);
1829
-		if ($resql)
1830
-		{
1831
-			while ($obj = $this->db->fetch_object($resql))
1832
-			{
1833
-				$label=$langs->trans('SendingMethod'.$obj->code);
1834
-				$this->meths[$obj->rowid] = ($label != 'SendingMethod'.$obj->code?$label:$obj->libelle);
1835
-			}
1836
-		}
1837
-	}
1149
+    /**
1150
+     * 	Delete shipment.
1151
+     * 	Warning, do not delete a shipment if a delivery is linked to (with table llx_element_element)
1152
+     *
1153
+     * 	@return	int		>0 if OK, 0 if deletion done but failed to delete files, <0 if KO
1154
+     */
1155
+    function delete()
1156
+    {
1157
+        global $conf, $langs, $user;
1158
+
1159
+        require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1160
+        require_once DOL_DOCUMENT_ROOT.'/expedition/class/expeditionbatch.class.php';
1161
+
1162
+        $error=0;
1163
+        $this->error='';
1164
+
1165
+        $this->db->begin();
1166
+
1167
+        // Add a protection to refuse deleting if shipment has at least one delivery
1168
+        $this->fetchObjectLinked($this->id, 'shipping', 0, 'delivery');	// Get deliveries linked to this shipment
1169
+        if (count($this->linkedObjectsIds) > 0)
1170
+        {
1171
+            $this->error='ErrorThereIsSomeDeliveries';
1172
+            $error++;
1173
+        }
1174
+
1175
+        if (! $error)
1176
+        {
1177
+            if (! $notrigger)
1178
+            {
1179
+                // Call trigger
1180
+                $result=$this->call_trigger('SHIPPING_DELETE',$user);
1181
+                if ($result < 0) { $error++; }
1182
+                // End call triggers
1183
+            }
1184
+        }
1185
+
1186
+        // Stock control
1187
+        if (! $error && $conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_SHIPMENT && $this->statut > 0)
1188
+        {
1189
+            require_once DOL_DOCUMENT_ROOT."/product/stock/class/mouvementstock.class.php";
1190
+
1191
+            $langs->load("agenda");
1192
+
1193
+            // Loop on each product line to add a stock movement
1194
+            $sql = "SELECT cd.fk_product, cd.subprice, ed.qty, ed.fk_entrepot, ed.rowid as expeditiondet_id";
1195
+            $sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd,";
1196
+            $sql.= " ".MAIN_DB_PREFIX."expeditiondet as ed";
1197
+            $sql.= " WHERE ed.fk_expedition = ".$this->id;
1198
+            $sql.= " AND cd.rowid = ed.fk_origin_line";
1199
+
1200
+            dol_syslog(get_class($this)."::delete select details", LOG_DEBUG);
1201
+            $resql=$this->db->query($sql);
1202
+            if ($resql)
1203
+            {
1204
+                $cpt = $this->db->num_rows($resql);
1205
+                for ($i = 0; $i < $cpt; $i++)
1206
+                {
1207
+                    dol_syslog(get_class($this)."::delete movement index ".$i);
1208
+                    $obj = $this->db->fetch_object($resql);
1209
+
1210
+                    $mouvS = new MouvementStock($this->db);
1211
+                    // we do not log origin because it will be deleted
1212
+                    $mouvS->origin = null;
1213
+                    // get lot/serial
1214
+                    $lotArray = null;
1215
+                    if ($conf->productbatch->enabled)
1216
+                    {
1217
+                        $lotArray = ExpeditionLineBatch::fetchAll($this->db,$obj->expeditiondet_id);
1218
+                        if (! is_array($lotArray))
1219
+                        {
1220
+                            $error++;$this->errors[]="Error ".$this->db->lasterror();
1221
+                        }
1222
+                    }
1223
+                    if (empty($lotArray)) {
1224
+                        // no lot/serial
1225
+                        // We increment stock of product (and sub-products)
1226
+                        // We use warehouse selected for each line
1227
+                        $result=$mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $obj->qty, 0, $langs->trans("ShipmentDeletedInDolibarr", $this->ref));  // Price is set to 0, because we don't want to see WAP changed
1228
+                        if ($result < 0)
1229
+                        {
1230
+                            $error++;$this->errors=$this->errors + $mouvS->errors;
1231
+                            break;
1232
+                        }
1233
+                    }
1234
+                    else
1235
+                    {
1236
+                        // We increment stock of batches
1237
+                        // We use warehouse selected for each line
1238
+                        foreach($lotArray as $lot)
1239
+                        {
1240
+                            $result=$mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $lot->qty, 0, $langs->trans("ShipmentDeletedInDolibarr", $this->ref), $lot->eatby, $lot->sellby, $lot->batch);  // Price is set to 0, because we don't want to see WAP changed
1241
+                            if ($result < 0)
1242
+                            {
1243
+                                $error++;$this->errors=$this->errors + $mouvS->errors;
1244
+                                break;
1245
+                            }
1246
+                        }
1247
+                        if ($error) break; // break for loop incase of error
1248
+                    }
1249
+                }
1250
+            }
1251
+            else
1252
+            {
1253
+                $error++;$this->errors[]="Error ".$this->db->lasterror();
1254
+            }
1255
+        }
1256
+
1257
+        // delete batch expedition line
1258
+        if (! $error && $conf->productbatch->enabled)
1259
+        {
1260
+            if (ExpeditionLineBatch::deletefromexp($this->db,$this->id) < 0)
1261
+            {
1262
+                $error++;$this->errors[]="Error ".$this->db->lasterror();
1263
+            }
1264
+        }
1265
+
1266
+        if (! $error)
1267
+        {
1268
+            $sql = "DELETE FROM ".MAIN_DB_PREFIX."expeditiondet";
1269
+            $sql.= " WHERE fk_expedition = ".$this->id;
1270
+
1271
+            if ( $this->db->query($sql) )
1272
+            {
1273
+                // Delete linked object
1274
+                $res = $this->deleteObjectLinked();
1275
+                if ($res < 0) $error++;
1276
+
1277
+                if (! $error)
1278
+                {
1279
+                    $sql = "DELETE FROM ".MAIN_DB_PREFIX."expedition";
1280
+                    $sql.= " WHERE rowid = ".$this->id;
1281
+
1282
+                    if ($this->db->query($sql))
1283
+                    {
1284
+                        if (! empty($this->origin) && $this->origin_id > 0)
1285
+                        {
1286
+                            $this->fetch_origin();
1287
+                            $origin=$this->origin;
1288
+                            if ($this->$origin->statut == Commande::STATUS_SHIPMENTONPROCESS)     // If order source of shipment is "shipment in progress"
1289
+                            {
1290
+                                // Check if there is no more shipment. If not, we can move back status of order to "validated" instead of "shipment in progress"
1291
+                                $this->$origin->loadExpeditions();
1292
+                                //var_dump($this->$origin->expeditions);exit;
1293
+                                if (count($this->$origin->expeditions) <= 0)
1294
+                                {
1295
+                                    $this->$origin->setStatut(Commande::STATUS_VALIDATED);
1296
+                                }
1297
+                            }
1298
+                        }
1299
+
1300
+                        if (! $error)
1301
+                        {
1302
+                            $this->db->commit();
1303
+
1304
+                            // We delete PDFs
1305
+                            $ref = dol_sanitizeFileName($this->ref);
1306
+                            if (! empty($conf->expedition->dir_output))
1307
+                            {
1308
+                                $dir = $conf->expedition->dir_output . '/sending/' . $ref ;
1309
+                                $file = $dir . '/' . $ref . '.pdf';
1310
+                                if (file_exists($file))
1311
+                                {
1312
+                                    if (! dol_delete_file($file))
1313
+                                    {
1314
+                                        return 0;
1315
+                                    }
1316
+                                }
1317
+                                if (file_exists($dir))
1318
+                                {
1319
+                                    if (!dol_delete_dir_recursive($dir))
1320
+                                    {
1321
+                                        $this->error=$langs->trans("ErrorCanNotDeleteDir",$dir);
1322
+                                        return 0;
1323
+                                    }
1324
+                                }
1325
+                            }
1326
+
1327
+                            return 1;
1328
+                        }
1329
+                        else
1330
+                        {
1331
+                            $this->db->rollback();
1332
+                            return -1;
1333
+                        }
1334
+                    }
1335
+                    else
1336
+                    {
1337
+                        $this->error=$this->db->lasterror()." - sql=$sql";
1338
+                        $this->db->rollback();
1339
+                        return -3;
1340
+                    }
1341
+                }
1342
+                else
1343
+                {
1344
+                    $this->error=$this->db->lasterror()." - sql=$sql";
1345
+                    $this->db->rollback();
1346
+                    return -2;
1347
+                }
1348
+            }
1349
+            else
1350
+            {
1351
+                $this->error=$this->db->lasterror()." - sql=$sql";
1352
+                $this->db->rollback();
1353
+                return -1;
1354
+            }
1355
+        }
1356
+        else
1357
+        {
1358
+            $this->db->rollback();
1359
+            return -1;
1360
+        }
1361
+    }
1838 1362
 
1839 1363
     // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1840
-	/**
1841
-	 *  Fetch all deliveries method and return an array. Load array this->listmeths.
1842
-	 *
1843
-	 *  @param  id      $id     only this carrier, all if none
1844
-	 *  @return void
1845
-	 */
1846
-	function list_delivery_methods($id='')
1847
-	{
1364
+    /**
1365
+     *	Load lines
1366
+     *
1367
+     *	@return	int		>0 if OK, Otherwise if KO
1368
+     */
1369
+    function fetch_lines()
1370
+    {
1848 1371
         // phpcs:enable
1849
-		global $langs;
1372
+        global $conf, $mysoc;
1373
+        // TODO: recuperer les champs du document associe a part
1374
+
1375
+        $sql = "SELECT cd.rowid, cd.fk_product, cd.label as custom_label, cd.description, cd.qty as qty_asked, cd.product_type";
1376
+        $sql.= ", cd.total_ht, cd.total_localtax1, cd.total_localtax2, cd.total_ttc, cd.total_tva";
1377
+        $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";
1378
+        $sql.= ", cd.fk_multicurrency, cd.multicurrency_code, cd.multicurrency_subprice, cd.multicurrency_total_ht, cd.multicurrency_total_tva, cd.multicurrency_total_ttc";
1379
+        $sql.= ", ed.rowid as line_id, ed.qty as qty_shipped, ed.fk_origin_line, ed.fk_entrepot";
1380
+        $sql.= ", p.ref as product_ref, p.label as product_label, p.fk_product_type";
1381
+        $sql.= ", p.weight, p.weight_units, p.length, p.length_units, p.surface, p.surface_units, p.volume, p.volume_units, p.tobatch as product_tobatch";
1382
+        $sql.= " FROM ".MAIN_DB_PREFIX."expeditiondet as ed, ".MAIN_DB_PREFIX."commandedet as cd";
1383
+        $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = cd.fk_product";
1384
+        $sql.= " WHERE ed.fk_expedition = ".$this->id;
1385
+        $sql.= " AND ed.fk_origin_line = cd.rowid";
1386
+        $sql.= " ORDER BY cd.rang, ed.fk_origin_line";
1387
+
1388
+        dol_syslog(get_class($this)."::fetch_lines", LOG_DEBUG);
1389
+        $resql = $this->db->query($sql);
1390
+        if ($resql)
1391
+        {
1392
+            include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
1393
+
1394
+            $num = $this->db->num_rows($resql);
1395
+            $i = 0;
1396
+            $lineindex = 0;
1397
+            $originline = 0;
1398
+
1399
+            $this->total_ht = 0;
1400
+            $this->total_tva = 0;
1401
+            $this->total_ttc = 0;
1402
+            $this->total_localtax1 = 0;
1403
+            $this->total_localtax2 = 0;
1404
+
1405
+            while ($i < $num)
1406
+            {
1407
+                $obj = $this->db->fetch_object($resql);
1408
+
1409
+                if ($originline == $obj->fk_origin_line) {
1410
+                    $line->entrepot_id       = 0; // entrepod_id in details_entrepot
1411
+                    $line->qty_shipped    	+= $obj->qty_shipped;
1412
+                } else {
1413
+                    $line = new ExpeditionLigne($this->db);
1414
+                    $line->entrepot_id    	= $obj->fk_entrepot;
1415
+                    $line->qty_shipped    	= $obj->qty_shipped;
1416
+                }
1417
+
1418
+                $detail_entrepot              = new stdClass;
1419
+                $detail_entrepot->entrepot_id = $obj->fk_entrepot;
1420
+                $detail_entrepot->qty_shipped = $obj->qty_shipped;
1421
+                $detail_entrepot->line_id     = $obj->line_id;
1422
+                $line->details_entrepot[]     = $detail_entrepot;
1423
+
1424
+                $line->line_id          = $obj->line_id;
1425
+                $line->rowid            = $obj->line_id;    // TODO deprecated
1426
+                $line->id               = $obj->line_id;
1427
+
1428
+                $line->fk_origin     	= 'orderline';
1429
+                $line->fk_origin_line 	= $obj->fk_origin_line;
1430
+                $line->origin_line_id 	= $obj->fk_origin_line;	    // TODO deprecated
1431
+
1432
+                $line->fk_expedition    = $this->id;                // id of parent
1433
+
1434
+                $line->product_type     = $obj->product_type;
1435
+                $line->fk_product     	= $obj->fk_product;
1436
+                $line->fk_product_type	= $obj->fk_product_type;
1437
+                $line->ref				= $obj->product_ref;		// TODO deprecated
1438
+                $line->product_ref		= $obj->product_ref;
1439
+                $line->product_label	= $obj->product_label;
1440
+                $line->libelle        	= $obj->product_label;		// TODO deprecated
1441
+                $line->product_tobatch  = $obj->product_tobatch;
1442
+                $line->label			= $obj->custom_label;
1443
+                $line->description    	= $obj->description;
1444
+                $line->qty_asked      	= $obj->qty_asked;
1445
+                $line->weight         	= $obj->weight;
1446
+                $line->weight_units   	= $obj->weight_units;
1447
+                $line->length         	= $obj->length;
1448
+                $line->length_units   	= $obj->length_units;
1449
+                $line->surface        	= $obj->surface;
1450
+                $line->surface_units   	= $obj->surface_units;
1451
+                $line->volume         	= $obj->volume;
1452
+                $line->volume_units   	= $obj->volume_units;
1453
+
1454
+                $line->pa_ht 			= $obj->pa_ht;
1455
+
1456
+                // Local taxes
1457
+                $localtax_array=array(0=>$obj->localtax1_type, 1=>$obj->localtax1_tx, 2=>$obj->localtax2_type, 3=>$obj->localtax2_tx);
1458
+                $localtax1_tx = get_localtax($obj->tva_tx, 1, $this->thirdparty);
1459
+                $localtax2_tx = get_localtax($obj->tva_tx, 2, $this->thirdparty);
1460
+
1461
+                // For invoicing
1462
+                $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);	// We force type to 0
1463
+                $line->desc	         	= $obj->description;		// We need ->desc because some code into CommonObject use desc (property defined for other elements)
1464
+                $line->qty 				= $line->qty_shipped;
1465
+                $line->total_ht			= $tabprice[0];
1466
+                $line->total_localtax1 	= $tabprice[9];
1467
+                $line->total_localtax2 	= $tabprice[10];
1468
+                $line->total_ttc	 	= $tabprice[2];
1469
+                $line->total_tva	 	= $tabprice[1];
1470
+                $line->vat_src_code	 	= $obj->vat_src_code;
1471
+                $line->tva_tx 		 	= $obj->tva_tx;
1472
+                $line->localtax1_tx 	= $obj->localtax1_tx;
1473
+                $line->localtax2_tx 	= $obj->localtax2_tx;
1474
+                $line->info_bits        = $obj->info_bits;
1475
+                $line->price			= $obj->price;
1476
+                $line->subprice			= $obj->subprice;
1477
+                $line->remise_percent	= $obj->remise_percent;
1478
+
1479
+                $this->total_ht+= $tabprice[0];
1480
+                $this->total_tva+= $tabprice[1];
1481
+                $this->total_ttc+= $tabprice[2];
1482
+                $this->total_localtax1+= $tabprice[9];
1483
+                $this->total_localtax2+= $tabprice[10];
1484
+
1485
+                // Multicurrency
1486
+                $this->fk_multicurrency 		= $obj->fk_multicurrency;
1487
+                $this->multicurrency_code 		= $obj->multicurrency_code;
1488
+                $this->multicurrency_subprice 	= $obj->multicurrency_subprice;
1489
+                $this->multicurrency_total_ht 	= $obj->multicurrency_total_ht;
1490
+                $this->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
1491
+                $this->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
1492
+
1493
+                if ($originline != $obj->fk_origin_line)
1494
+                {
1495
+                    $line->detail_batch = array();
1496
+                }
1497
+
1498
+                // Detail of batch
1499
+                if (! empty($conf->productbatch->enabled) && $obj->line_id > 0 && $obj->product_tobatch > 0)
1500
+                {
1501
+                    require_once DOL_DOCUMENT_ROOT.'/expedition/class/expeditionbatch.class.php';
1502
+
1503
+                    $newdetailbatch = ExpeditionLineBatch::fetchAll($this->db, $obj->line_id, $obj->fk_product);
1504
+                    if (is_array($newdetailbatch))
1505
+                    {
1506
+                        if ($originline != $obj->fk_origin_line)
1507
+                        {
1508
+                            $line->detail_batch = $newdetailbatch;
1509
+                        }
1510
+                        else
1511
+                        {
1512
+                            $line->detail_batch = array_merge($line->detail_batch, $newdetailbatch);
1513
+                        }
1514
+                    }
1515
+                }
1516
+
1517
+                if ($originline != $obj->fk_origin_line)
1518
+                {
1519
+                    $this->lines[$lineindex] = $line;
1520
+                    $lineindex++;
1521
+                }
1522
+                else
1523
+                {
1524
+                    $line->total_ht			+= $tabprice[0];
1525
+                    $line->total_localtax1 	+= $tabprice[9];
1526
+                    $line->total_localtax2 	+= $tabprice[10];
1527
+                    $line->total_ttc	 	+= $tabprice[2];
1528
+                    $line->total_tva	 	+= $tabprice[1];
1529
+                }
1530
+
1531
+                $i++;
1532
+                $originline = $obj->fk_origin_line;
1533
+            }
1534
+            $this->db->free($resql);
1535
+            return 1;
1536
+        }
1537
+        else
1538
+        {
1539
+            $this->error=$this->db->error();
1540
+            return -3;
1541
+        }
1542
+    }
1850 1543
 
1851
-		$this->listmeths = array();
1852
-		$i=0;
1544
+    /**
1545
+     *  Delete detail line
1546
+     *
1547
+     *  @param		User	$user			User making deletion
1548
+     *  @param		int		$lineid			Id of line to delete
1549
+     *  @return     int         			>0 if OK, <0 if KO
1550
+     */
1551
+    function deleteline($user, $lineid)
1552
+    {
1553
+        global $user;
1554
+
1555
+        if ($this->statut == self::STATUS_DRAFT)
1556
+        {
1557
+            $this->db->begin();
1558
+
1559
+            $line=new ExpeditionLigne($this->db);
1560
+
1561
+            // For triggers
1562
+            $line->fetch($lineid);
1563
+
1564
+            if ($line->delete($user) > 0)
1565
+            {
1566
+                //$this->update_price(1);
1567
+
1568
+                $this->db->commit();
1569
+                return 1;
1570
+            }
1571
+            else
1572
+            {
1573
+                $this->db->rollback();
1574
+                return -1;
1575
+            }
1576
+        }
1577
+        else
1578
+        {
1579
+            $this->error='ErrorDeleteLineNotAllowedByObjectStatus';
1580
+            return -2;
1581
+        }
1582
+    }
1853 1583
 
1854
-		$sql = "SELECT em.rowid, em.code, em.libelle, em.description, em.tracking, em.active";
1855
-		$sql.= " FROM ".MAIN_DB_PREFIX."c_shipment_mode as em";
1856
-		if ($id!='') $sql.= " WHERE em.rowid=".$id;
1857 1584
 
1858
-		$resql = $this->db->query($sql);
1859
-		if ($resql)
1860
-		{
1861
-			while ($obj = $this->db->fetch_object($resql))
1862
-			{
1863
-				$this->listmeths[$i]['rowid'] = $obj->rowid;
1864
-				$this->listmeths[$i]['code'] = $obj->code;
1865
-				$label=$langs->trans('SendingMethod'.$obj->code);
1866
-				$this->listmeths[$i]['libelle'] = ($label != 'SendingMethod'.$obj->code?$label:$obj->libelle);
1867
-				$this->listmeths[$i]['description'] = $obj->description;
1868
-				$this->listmeths[$i]['tracking'] = $obj->tracking;
1869
-				$this->listmeths[$i]['active'] = $obj->active;
1870
-				$i++;
1871
-			}
1872
-		}
1873
-	}
1585
+    /**
1586
+     *	Return clicable link of object (with eventually picto)
1587
+     *
1588
+     *	@param      int			$withpicto      			Add picto into link
1589
+     *	@param      string		$option         			Where the link point to
1590
+     *	@param      int			$max          				Max length to show
1591
+     *	@param      int			$short						Use short labels
1592
+     *  @param      int         $notooltip      			1=No tooltip
1593
+     *  @param      int     	$save_lastsearch_value		-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
1594
+     *	@return     string          						String with URL
1595
+     */
1596
+    function getNomUrl($withpicto=0, $option='', $max=0, $short=0, $notooltip=0, $save_lastsearch_value=-1)
1597
+    {
1598
+        global $langs;
1599
+
1600
+        $result='';
1601
+        $label = '<u>' . $langs->trans("ShowSending") . '</u>';
1602
+        $label .= '<br><b>' . $langs->trans('Ref') . ':</b> '.$this->ref;
1603
+        $label .= '<br><b>'.$langs->trans('RefCustomer').':</b> '.($this->ref_customer ? $this->ref_customer : $this->ref_client);
1604
+
1605
+        $url = DOL_URL_ROOT.'/expedition/card.php?id='.$this->id;
1606
+
1607
+        if ($short) return $url;
1608
+
1609
+        if ($option !== 'nolink')
1610
+        {
1611
+            // Add param to save lastsearch_values or not
1612
+            $add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
1613
+            if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
1614
+            if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
1615
+        }
1616
+
1617
+        $linkclose='';
1618
+        if (empty($notooltip))
1619
+        {
1620
+            if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
1621
+            {
1622
+                $label=$langs->trans("ShowSending");
1623
+                $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"';
1624
+            }
1625
+            $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
1626
+            $linkclose.=' class="classfortooltip"';
1627
+        }
1628
+
1629
+        $linkstart = '<a href="'.$url.'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';
1630
+        $linkend='</a>';
1631
+
1632
+        $result .= $linkstart;
1633
+        if ($withpicto) $result.=img_object(($notooltip?'':$label), $this->picto, ($notooltip?(($withpicto != 2) ? 'class="paddingright"' : ''):'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip?0:1);
1634
+        if ($withpicto != 2) $result.= $this->ref;
1635
+        $result .= $linkend;
1636
+
1637
+        return $result;
1638
+    }
1639
+
1640
+    /**
1641
+     *	Return status label
1642
+     *
1643
+     *	@param      int		$mode      	0=Long label, 1=Short label, 2=Picto + Short label, 3=Picto, 4=Picto + Long label, 5=Short label + Picto
1644
+     *	@return     string      		Libelle
1645
+     */
1646
+    function getLibStatut($mode=0)
1647
+    {
1648
+        return $this->LibStatut($this->statut,$mode);
1649
+    }
1874 1650
 
1875 1651
     // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1876
-	/**
1877
-	 *  Update/create delivery method.
1878
-	 *
1879
-	 *  @param	string      $id     id method to activate
1880
-	 *
1881
-	 *  @return void
1882
-	 */
1883
-	function update_delivery_method($id='')
1884
-	{
1652
+    /**
1653
+     * Return label of a status
1654
+     *
1655
+     * @param      int		$statut		Id statut
1656
+     * @param      int		$mode       0=Long label, 1=Short label, 2=Picto + Short label, 3=Picto, 4=Picto + Long label, 5=Short label + Picto
1657
+     * @return     string				Label of status
1658
+     */
1659
+    function LibStatut($statut,$mode)
1660
+    {
1885 1661
         // phpcs:enable
1886
-		if ($id=='')
1887
-		{
1888
-			$sql = "INSERT INTO ".MAIN_DB_PREFIX."c_shipment_mode (code, libelle, description, tracking)";
1889
-			$sql.=" VALUES ('".$this->db->escape($this->update['code'])."','".$this->db->escape($this->update['libelle'])."','".$this->db->escape($this->update['description'])."','".$this->db->escape($this->update['tracking'])."')";
1890
-			$resql = $this->db->query($sql);
1891
-		}
1892
-		else
1893
-		{
1894
-			$sql = "UPDATE ".MAIN_DB_PREFIX."c_shipment_mode SET";
1895
-			$sql.= " code='".$this->db->escape($this->update['code'])."'";
1896
-			$sql.= ",libelle='".$this->db->escape($this->update['libelle'])."'";
1897
-			$sql.= ",description='".$this->db->escape($this->update['description'])."'";
1898
-			$sql.= ",tracking='".$this->db->escape($this->update['tracking'])."'";
1899
-			$sql.= " WHERE rowid=".$id;
1900
-			$resql = $this->db->query($sql);
1901
-		}
1902
-		if ($resql < 0) dol_print_error($this->db,'');
1903
-	}
1662
+        global $langs;
1663
+
1664
+        if ($mode==0)
1665
+        {
1666
+            if ($statut==0) return $langs->trans($this->statuts[$statut]);
1667
+            elseif ($statut==1) return $langs->trans($this->statuts[$statut]);
1668
+            elseif ($statut==2) return $langs->trans($this->statuts[$statut]);
1669
+        }
1670
+        elseif ($mode==1)
1671
+        {
1672
+            if ($statut==0) return $langs->trans($this->statutshorts[$statut]);
1673
+            elseif ($statut==1) return $langs->trans($this->statutshorts[$statut]);
1674
+            elseif ($statut==2) return $langs->trans($this->statutshorts[$statut]);
1675
+        }
1676
+        elseif ($mode == 3)
1677
+        {
1678
+            if ($statut==0) return img_picto($langs->trans($this->statuts[$statut]),'statut0');
1679
+            elseif ($statut==1) return img_picto($langs->trans($this->statuts[$statut]),'statut4');
1680
+            elseif ($statut==2) return img_picto($langs->trans($this->statuts[$statut]),'statut6');
1681
+        }
1682
+        elseif ($mode == 4)
1683
+        {
1684
+            if ($statut==0) return img_picto($langs->trans($this->statuts[$statut]),'statut0').' '.$langs->trans($this->statuts[$statut]);
1685
+            elseif ($statut==1) return img_picto($langs->trans($this->statuts[$statut]),'statut4').' '.$langs->trans($this->statuts[$statut]);
1686
+            elseif ($statut==2) return img_picto($langs->trans($this->statuts[$statut]),'statut6').' '.$langs->trans($this->statuts[$statut]);
1687
+        }
1688
+        elseif ($mode == 5)
1689
+        {
1690
+            if ($statut==0) return $langs->trans($this->statutshorts[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]),'statut0');
1691
+            elseif ($statut==1) return $langs->trans($this->statutshorts[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]),'statut4');
1692
+            elseif ($statut==2) return $langs->trans($this->statutshorts[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]),'statut6');
1693
+        }
1694
+    }
1695
+
1696
+    /**
1697
+     *  Initialise an instance with random values.
1698
+     *  Used to build previews or test instances.
1699
+     *	id must be 0 if object instance is a specimen.
1700
+     *
1701
+     *  @return	void
1702
+     */
1703
+    function initAsSpecimen()
1704
+    {
1705
+        global $langs;
1706
+
1707
+        $now=dol_now();
1708
+
1709
+        dol_syslog(get_class($this)."::initAsSpecimen");
1710
+
1711
+        // Load array of products prodids
1712
+        $num_prods = 0;
1713
+        $prodids = array();
1714
+        $sql = "SELECT rowid";
1715
+        $sql.= " FROM ".MAIN_DB_PREFIX."product";
1716
+        $sql.= " WHERE entity IN (".getEntity('product').")";
1717
+        $resql = $this->db->query($sql);
1718
+        if ($resql)
1719
+        {
1720
+            $num_prods = $this->db->num_rows($resql);
1721
+            $i = 0;
1722
+            while ($i < $num_prods)
1723
+            {
1724
+                $i++;
1725
+                $row = $this->db->fetch_row($resql);
1726
+                $prodids[$i] = $row[0];
1727
+            }
1728
+        }
1729
+
1730
+        $order=new Commande($this->db);
1731
+        $order->initAsSpecimen();
1732
+
1733
+        // Initialise parametres
1734
+        $this->id=0;
1735
+        $this->ref = 'SPECIMEN';
1736
+        $this->specimen=1;
1737
+        $this->statut               = 1;
1738
+        $this->livraison_id         = 0;
1739
+        $this->date                 = $now;
1740
+        $this->date_creation        = $now;
1741
+        $this->date_valid           = $now;
1742
+        $this->date_delivery        = $now;
1743
+        $this->date_expedition      = $now + 24*3600;
1744
+
1745
+        $this->entrepot_id          = 0;
1746
+        $this->fk_delivery_address  = 0;
1747
+        $this->socid                = 1;
1748
+
1749
+        $this->commande_id          = 0;
1750
+        $this->commande             = $order;
1751
+
1752
+        $this->origin_id            = 1;
1753
+        $this->origin               = 'commande';
1754
+
1755
+        $this->note_private			= 'Private note';
1756
+        $this->note_public			= 'Public note';
1757
+
1758
+        $nbp = 5;
1759
+        $xnbp = 0;
1760
+        while ($xnbp < $nbp)
1761
+        {
1762
+            $line=new ExpeditionLigne($this->db);
1763
+            $line->desc=$langs->trans("Description")." ".$xnbp;
1764
+            $line->libelle=$langs->trans("Description")." ".$xnbp;
1765
+            $line->qty=10;
1766
+            $line->qty_asked=5;
1767
+            $line->qty_shipped=4;
1768
+            $line->fk_product=$this->commande->lines[$xnbp]->fk_product;
1769
+
1770
+            $this->lines[]=$line;
1771
+            $xnbp++;
1772
+        }
1773
+    }
1774
+
1775
+    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1776
+    /**
1777
+     *	Set the planned delivery date
1778
+     *
1779
+     *	@param      User			$user        		Objet utilisateur qui modifie
1780
+     *	@param      timestamp		$date_livraison     Date de livraison
1781
+     *	@return     int         						<0 if KO, >0 if OK
1782
+     */
1783
+    function set_date_livraison($user, $date_livraison)
1784
+    {
1785
+        // phpcs:enable
1786
+        if ($user->rights->expedition->creer)
1787
+        {
1788
+            $sql = "UPDATE ".MAIN_DB_PREFIX."expedition";
1789
+            $sql.= " SET date_delivery = ".($date_livraison ? "'".$this->db->idate($date_livraison)."'" : 'null');
1790
+            $sql.= " WHERE rowid = ".$this->id;
1791
+
1792
+            dol_syslog(get_class($this)."::set_date_livraison", LOG_DEBUG);
1793
+            $resql=$this->db->query($sql);
1794
+            if ($resql)
1795
+            {
1796
+                $this->date_delivery = $date_livraison;
1797
+                return 1;
1798
+            }
1799
+            else
1800
+            {
1801
+                $this->error=$this->db->error();
1802
+                return -1;
1803
+            }
1804
+        }
1805
+        else
1806
+        {
1807
+            return -2;
1808
+        }
1809
+    }
1904 1810
 
1905 1811
     // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1906
-	/**
1907
-	 *  Activate delivery method.
1908
-	 *
1909
-	 *  @param      id      $id     id method to activate
1910
-	 *
1911
-	 *  @return void
1912
-	 */
1913
-	function activ_delivery_method($id)
1914
-	{
1812
+    /**
1813
+     *	Fetch deliveries method and return an array. Load array this->meths(rowid=>label).
1814
+     *
1815
+     * 	@return	void
1816
+     */
1817
+    function fetch_delivery_methods()
1818
+    {
1915 1819
         // phpcs:enable
1916
-		$sql = 'UPDATE '.MAIN_DB_PREFIX.'c_shipment_mode SET active=1';
1917
-		$sql.= ' WHERE rowid='.$id;
1820
+        global $langs;
1821
+        $this->meths = array();
1822
+
1823
+        $sql = "SELECT em.rowid, em.code, em.libelle";
1824
+        $sql.= " FROM ".MAIN_DB_PREFIX."c_shipment_mode as em";
1825
+        $sql.= " WHERE em.active = 1";
1826
+        $sql.= " ORDER BY em.libelle ASC";
1827
+
1828
+        $resql = $this->db->query($sql);
1829
+        if ($resql)
1830
+        {
1831
+            while ($obj = $this->db->fetch_object($resql))
1832
+            {
1833
+                $label=$langs->trans('SendingMethod'.$obj->code);
1834
+                $this->meths[$obj->rowid] = ($label != 'SendingMethod'.$obj->code?$label:$obj->libelle);
1835
+            }
1836
+        }
1837
+    }
1918 1838
 
1919
-		$resql = $this->db->query($sql);
1920
-	}
1839
+    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1840
+    /**
1841
+     *  Fetch all deliveries method and return an array. Load array this->listmeths.
1842
+     *
1843
+     *  @param  id      $id     only this carrier, all if none
1844
+     *  @return void
1845
+     */
1846
+    function list_delivery_methods($id='')
1847
+    {
1848
+        // phpcs:enable
1849
+        global $langs;
1850
+
1851
+        $this->listmeths = array();
1852
+        $i=0;
1853
+
1854
+        $sql = "SELECT em.rowid, em.code, em.libelle, em.description, em.tracking, em.active";
1855
+        $sql.= " FROM ".MAIN_DB_PREFIX."c_shipment_mode as em";
1856
+        if ($id!='') $sql.= " WHERE em.rowid=".$id;
1857
+
1858
+        $resql = $this->db->query($sql);
1859
+        if ($resql)
1860
+        {
1861
+            while ($obj = $this->db->fetch_object($resql))
1862
+            {
1863
+                $this->listmeths[$i]['rowid'] = $obj->rowid;
1864
+                $this->listmeths[$i]['code'] = $obj->code;
1865
+                $label=$langs->trans('SendingMethod'.$obj->code);
1866
+                $this->listmeths[$i]['libelle'] = ($label != 'SendingMethod'.$obj->code?$label:$obj->libelle);
1867
+                $this->listmeths[$i]['description'] = $obj->description;
1868
+                $this->listmeths[$i]['tracking'] = $obj->tracking;
1869
+                $this->listmeths[$i]['active'] = $obj->active;
1870
+                $i++;
1871
+            }
1872
+        }
1873
+    }
1921 1874
 
1922 1875
     // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1923
-	/**
1924
-	 *  DesActivate delivery method.
1925
-	 *
1926
-	 *  @param      id      $id     id method to desactivate
1927
-	 *
1928
-	 *  @return void
1929
-	 */
1930
-	function disable_delivery_method($id)
1931
-	{
1876
+    /**
1877
+     *  Update/create delivery method.
1878
+     *
1879
+     *  @param	string      $id     id method to activate
1880
+     *
1881
+     *  @return void
1882
+     */
1883
+    function update_delivery_method($id='')
1884
+    {
1932 1885
         // phpcs:enable
1933
-		$sql = 'UPDATE '.MAIN_DB_PREFIX.'c_shipment_mode SET active=0';
1934
-		$sql.= ' WHERE rowid='.$id;
1935
-
1936
-		$resql = $this->db->query($sql);
1937
-	}
1938
-
1939
-
1940
-	/**
1941
-	 * Forge an set tracking url
1942
-	 *
1943
-	 * @param	string	$value		Value
1944
-	 * @return	void
1945
-	 */
1946
-	function getUrlTrackingStatus($value='')
1947
-	{
1948
-		if (! empty($this->shipping_method_id))
1949
-		{
1950
-			$sql = "SELECT em.code, em.tracking";
1951
-			$sql.= " FROM ".MAIN_DB_PREFIX."c_shipment_mode as em";
1952
-			$sql.= " WHERE em.rowid = ".$this->shipping_method_id;
1953
-
1954
-			$resql = $this->db->query($sql);
1955
-			if ($resql)
1956
-			{
1957
-				if ($obj = $this->db->fetch_object($resql))
1958
-				{
1959
-					$tracking = $obj->tracking;
1960
-				}
1961
-			}
1962
-		}
1963
-
1964
-		if (!empty($tracking) && !empty($value))
1965
-		{
1966
-			$url = str_replace('{TRACKID}', $value, $tracking);
1967
-			$this->tracking_url = sprintf('<a target="_blank" href="%s">'.($value?$value:'url').'</a>',$url,$url);
1968
-		}
1969
-		else
1970
-		{
1971
-			$this->tracking_url = $value;
1972
-		}
1973
-	}
1886
+        if ($id=='')
1887
+        {
1888
+            $sql = "INSERT INTO ".MAIN_DB_PREFIX."c_shipment_mode (code, libelle, description, tracking)";
1889
+            $sql.=" VALUES ('".$this->db->escape($this->update['code'])."','".$this->db->escape($this->update['libelle'])."','".$this->db->escape($this->update['description'])."','".$this->db->escape($this->update['tracking'])."')";
1890
+            $resql = $this->db->query($sql);
1891
+        }
1892
+        else
1893
+        {
1894
+            $sql = "UPDATE ".MAIN_DB_PREFIX."c_shipment_mode SET";
1895
+            $sql.= " code='".$this->db->escape($this->update['code'])."'";
1896
+            $sql.= ",libelle='".$this->db->escape($this->update['libelle'])."'";
1897
+            $sql.= ",description='".$this->db->escape($this->update['description'])."'";
1898
+            $sql.= ",tracking='".$this->db->escape($this->update['tracking'])."'";
1899
+            $sql.= " WHERE rowid=".$id;
1900
+            $resql = $this->db->query($sql);
1901
+        }
1902
+        if ($resql < 0) dol_print_error($this->db,'');
1903
+    }
1974 1904
 
1975
-	/**
1976
-	 *	Classify the shipping as closed.
1977
-	 *
1978
-	 *	@return     int     <0 if KO, >0 if OK
1979
-	 */
1980
-	function setClosed()
1981
-	{
1982
-		global $conf,$langs,$user;
1905
+    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1906
+    /**
1907
+     *  Activate delivery method.
1908
+     *
1909
+     *  @param      id      $id     id method to activate
1910
+     *
1911
+     *  @return void
1912
+     */
1913
+    function activ_delivery_method($id)
1914
+    {
1915
+        // phpcs:enable
1916
+        $sql = 'UPDATE '.MAIN_DB_PREFIX.'c_shipment_mode SET active=1';
1917
+        $sql.= ' WHERE rowid='.$id;
1983 1918
 
1984
-		$error=0;
1919
+        $resql = $this->db->query($sql);
1920
+    }
1985 1921
 
1986
-		$this->db->begin();
1922
+    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1923
+    /**
1924
+     *  DesActivate delivery method.
1925
+     *
1926
+     *  @param      id      $id     id method to desactivate
1927
+     *
1928
+     *  @return void
1929
+     */
1930
+    function disable_delivery_method($id)
1931
+    {
1932
+        // phpcs:enable
1933
+        $sql = 'UPDATE '.MAIN_DB_PREFIX.'c_shipment_mode SET active=0';
1934
+        $sql.= ' WHERE rowid='.$id;
1987 1935
 
1988
-		$sql = 'UPDATE '.MAIN_DB_PREFIX.'expedition SET fk_statut='.self::STATUS_CLOSED;
1989
-		$sql .= ' WHERE rowid = '.$this->id.' AND fk_statut > 0';
1936
+        $resql = $this->db->query($sql);
1937
+    }
1990 1938
 
1991
-		$resql=$this->db->query($sql);
1992
-		if ($resql)
1993
-		{
1994
-			// Set order billed if 100% of order is shipped (qty in shipment lines match qty in order lines)
1995
-			if ($this->origin == 'commande' && $this->origin_id > 0)
1996
-			{
1997
-				$order = new Commande($this->db);
1998
-				$order->fetch($this->origin_id);
1999
-
2000
-				$order->loadExpeditions(self::STATUS_CLOSED);		// Fill $order->expeditions = array(orderlineid => qty)
2001
-
2002
-				$shipments_match_order = 1;
2003
-				foreach($order->lines as $line)
2004
-				{
2005
-					$lineid = $line->id;
2006
-					$qty = $line->qty;
2007
-					if (($line->product_type == 0 || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) && $order->expeditions[$lineid] != $qty)
2008
-					{
2009
-						$shipments_match_order = 0;
2010
-						$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';
2011
-						dol_syslog($text);
2012
-						break;
2013
-					}
2014
-				}
2015
-				if ($shipments_match_order)
2016
-				{
2017
-					dol_syslog("Qty for the ".count($order->lines)." lines of order have same value for shipments with status Expedition::STATUS_CLOSED=".self::STATUS_CLOSED.', so we close order');
2018
-					$order->cloture($user);
2019
-				}
2020
-			}
2021
-
2022
-			$this->statut=self::STATUS_CLOSED;
2023
-
2024
-
2025
-			// If stock increment is done on closing
2026
-			if (! $error && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE))
2027
-			{
2028
-				require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
2029
-
2030
-				$langs->load("agenda");
2031
-
2032
-				// Loop on each product line to add a stock movement
2033
-				// TODO possibilite d'expedier a partir d'une propale ou autre origine ?
2034
-				$sql = "SELECT cd.fk_product, cd.subprice,";
2035
-				$sql.= " ed.rowid, ed.qty, ed.fk_entrepot,";
2036
-				$sql.= " edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
2037
-				$sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd,";
2038
-				$sql.= " ".MAIN_DB_PREFIX."expeditiondet as ed";
2039
-				$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
2040
-				$sql.= " WHERE ed.fk_expedition = ".$this->id;
2041
-				$sql.= " AND cd.rowid = ed.fk_origin_line";
2042
-
2043
-				dol_syslog(get_class($this)."::valid select details", LOG_DEBUG);
2044
-				$resql=$this->db->query($sql);
2045
-				if ($resql)
2046
-				{
2047
-					$cpt = $this->db->num_rows($resql);
2048
-					for ($i = 0; $i < $cpt; $i++)
2049
-					{
2050
-						$obj = $this->db->fetch_object($resql);
2051
-						if (empty($obj->edbrowid))
2052
-						{
2053
-							$qty = $obj->qty;
2054
-						}
2055
-						else
2056
-						{
2057
-							$qty = $obj->edbqty;
2058
-						}
2059
-						if ($qty <= 0) continue;
2060
-						dol_syslog(get_class($this)."::valid movement index ".$i." ed.rowid=".$obj->rowid." edb.rowid=".$obj->edbrowid);
2061
-
2062
-						$mouvS = new MouvementStock($this->db);
2063
-						$mouvS->origin = &$this;
2064
-
2065
-						if (empty($obj->edbrowid))
2066
-						{
2067
-							// line without batch detail
2068
-
2069
-							// We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
2070
-							$result=$mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans("ShipmentClassifyClosedInDolibarr",$numref));
2071
-							if ($result < 0) {
2072
-								$this->error = $mouvS->error;
2073
-								$this->errors = $mouvS->errors;
2074
-								$error++; break;
2075
-							}
2076
-						}
2077
-						else
2078
-						{
2079
-							// line with batch detail
2080
-
2081
-							// We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
2082
-							$result=$mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans("ShipmentClassifyClosedInDolibarr",$numref), '', $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, $obj->fk_origin_stock);
2083
-							if ($result < 0) {
2084
-								$this->error = $mouvS->error;
2085
-								$this->errors = $mouvS->errors;
2086
-								$error++; break;
2087
-							}
2088
-						}
2089
-					}
2090
-				}
2091
-				else
2092
-				{
2093
-					$this->error=$this->db->lasterror();
2094
-					$error++;
2095
-				}
2096
-			}
2097
-
2098
-			// Call trigger
2099
-			if (! $error)
2100
-			{
2101
-				$result=$this->call_trigger('SHIPPING_CLOSED',$user);
2102
-				if ($result < 0) {
2103
-					$error++;
2104
-				}
2105
-			}
2106
-		}
2107
-		else
2108
-		{
2109
-			dol_print_error($this->db);
2110
-			$error++;
2111
-		}
2112 1939
 
2113
-		if (! $error)
2114
-		{
2115
-			$this->db->commit();
2116
-			return 1;
2117
-		}
2118
-		else
2119
-		{
2120
-			$this->db->rollback();
2121
-			return -1;
2122
-		}
2123
-	}
1940
+    /**
1941
+     * Forge an set tracking url
1942
+     *
1943
+     * @param	string	$value		Value
1944
+     * @return	void
1945
+     */
1946
+    function getUrlTrackingStatus($value='')
1947
+    {
1948
+        if (! empty($this->shipping_method_id))
1949
+        {
1950
+            $sql = "SELECT em.code, em.tracking";
1951
+            $sql.= " FROM ".MAIN_DB_PREFIX."c_shipment_mode as em";
1952
+            $sql.= " WHERE em.rowid = ".$this->shipping_method_id;
1953
+
1954
+            $resql = $this->db->query($sql);
1955
+            if ($resql)
1956
+            {
1957
+                if ($obj = $this->db->fetch_object($resql))
1958
+                {
1959
+                    $tracking = $obj->tracking;
1960
+                }
1961
+            }
1962
+        }
1963
+
1964
+        if (!empty($tracking) && !empty($value))
1965
+        {
1966
+            $url = str_replace('{TRACKID}', $value, $tracking);
1967
+            $this->tracking_url = sprintf('<a target="_blank" href="%s">'.($value?$value:'url').'</a>',$url,$url);
1968
+        }
1969
+        else
1970
+        {
1971
+            $this->tracking_url = $value;
1972
+        }
1973
+    }
1974
+
1975
+    /**
1976
+     *	Classify the shipping as closed.
1977
+     *
1978
+     *	@return     int     <0 if KO, >0 if OK
1979
+     */
1980
+    function setClosed()
1981
+    {
1982
+        global $conf,$langs,$user;
1983
+
1984
+        $error=0;
1985
+
1986
+        $this->db->begin();
1987
+
1988
+        $sql = 'UPDATE '.MAIN_DB_PREFIX.'expedition SET fk_statut='.self::STATUS_CLOSED;
1989
+        $sql .= ' WHERE rowid = '.$this->id.' AND fk_statut > 0';
1990
+
1991
+        $resql=$this->db->query($sql);
1992
+        if ($resql)
1993
+        {
1994
+            // Set order billed if 100% of order is shipped (qty in shipment lines match qty in order lines)
1995
+            if ($this->origin == 'commande' && $this->origin_id > 0)
1996
+            {
1997
+                $order = new Commande($this->db);
1998
+                $order->fetch($this->origin_id);
1999
+
2000
+                $order->loadExpeditions(self::STATUS_CLOSED);		// Fill $order->expeditions = array(orderlineid => qty)
2001
+
2002
+                $shipments_match_order = 1;
2003
+                foreach($order->lines as $line)
2004
+                {
2005
+                    $lineid = $line->id;
2006
+                    $qty = $line->qty;
2007
+                    if (($line->product_type == 0 || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) && $order->expeditions[$lineid] != $qty)
2008
+                    {
2009
+                        $shipments_match_order = 0;
2010
+                        $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';
2011
+                        dol_syslog($text);
2012
+                        break;
2013
+                    }
2014
+                }
2015
+                if ($shipments_match_order)
2016
+                {
2017
+                    dol_syslog("Qty for the ".count($order->lines)." lines of order have same value for shipments with status Expedition::STATUS_CLOSED=".self::STATUS_CLOSED.', so we close order');
2018
+                    $order->cloture($user);
2019
+                }
2020
+            }
2021
+
2022
+            $this->statut=self::STATUS_CLOSED;
2023
+
2024
+
2025
+            // If stock increment is done on closing
2026
+            if (! $error && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE))
2027
+            {
2028
+                require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
2029
+
2030
+                $langs->load("agenda");
2031
+
2032
+                // Loop on each product line to add a stock movement
2033
+                // TODO possibilite d'expedier a partir d'une propale ou autre origine ?
2034
+                $sql = "SELECT cd.fk_product, cd.subprice,";
2035
+                $sql.= " ed.rowid, ed.qty, ed.fk_entrepot,";
2036
+                $sql.= " edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
2037
+                $sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd,";
2038
+                $sql.= " ".MAIN_DB_PREFIX."expeditiondet as ed";
2039
+                $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
2040
+                $sql.= " WHERE ed.fk_expedition = ".$this->id;
2041
+                $sql.= " AND cd.rowid = ed.fk_origin_line";
2042
+
2043
+                dol_syslog(get_class($this)."::valid select details", LOG_DEBUG);
2044
+                $resql=$this->db->query($sql);
2045
+                if ($resql)
2046
+                {
2047
+                    $cpt = $this->db->num_rows($resql);
2048
+                    for ($i = 0; $i < $cpt; $i++)
2049
+                    {
2050
+                        $obj = $this->db->fetch_object($resql);
2051
+                        if (empty($obj->edbrowid))
2052
+                        {
2053
+                            $qty = $obj->qty;
2054
+                        }
2055
+                        else
2056
+                        {
2057
+                            $qty = $obj->edbqty;
2058
+                        }
2059
+                        if ($qty <= 0) continue;
2060
+                        dol_syslog(get_class($this)."::valid movement index ".$i." ed.rowid=".$obj->rowid." edb.rowid=".$obj->edbrowid);
2061
+
2062
+                        $mouvS = new MouvementStock($this->db);
2063
+                        $mouvS->origin = &$this;
2064
+
2065
+                        if (empty($obj->edbrowid))
2066
+                        {
2067
+                            // line without batch detail
2068
+
2069
+                            // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
2070
+                            $result=$mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans("ShipmentClassifyClosedInDolibarr",$numref));
2071
+                            if ($result < 0) {
2072
+                                $this->error = $mouvS->error;
2073
+                                $this->errors = $mouvS->errors;
2074
+                                $error++; break;
2075
+                            }
2076
+                        }
2077
+                        else
2078
+                        {
2079
+                            // line with batch detail
2080
+
2081
+                            // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
2082
+                            $result=$mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans("ShipmentClassifyClosedInDolibarr",$numref), '', $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, $obj->fk_origin_stock);
2083
+                            if ($result < 0) {
2084
+                                $this->error = $mouvS->error;
2085
+                                $this->errors = $mouvS->errors;
2086
+                                $error++; break;
2087
+                            }
2088
+                        }
2089
+                    }
2090
+                }
2091
+                else
2092
+                {
2093
+                    $this->error=$this->db->lasterror();
2094
+                    $error++;
2095
+                }
2096
+            }
2097
+
2098
+            // Call trigger
2099
+            if (! $error)
2100
+            {
2101
+                $result=$this->call_trigger('SHIPPING_CLOSED',$user);
2102
+                if ($result < 0) {
2103
+                    $error++;
2104
+                }
2105
+            }
2106
+        }
2107
+        else
2108
+        {
2109
+            dol_print_error($this->db);
2110
+            $error++;
2111
+        }
2112
+
2113
+        if (! $error)
2114
+        {
2115
+            $this->db->commit();
2116
+            return 1;
2117
+        }
2118
+        else
2119
+        {
2120
+            $this->db->rollback();
2121
+            return -1;
2122
+        }
2123
+    }
2124 2124
 
2125 2125
     // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2126
-	/**
2127
-	 *	Classify the shipping as invoiced (used when WORKFLOW_BILL_ON_SHIPMENT is on)
2128
-	 *
2129
-	 *	@return     int     <0 if ko, >0 if ok
2130
-	 */
2131
-	function set_billed()
2132
-	{
2126
+    /**
2127
+     *	Classify the shipping as invoiced (used when WORKFLOW_BILL_ON_SHIPMENT is on)
2128
+     *
2129
+     *	@return     int     <0 if ko, >0 if ok
2130
+     */
2131
+    function set_billed()
2132
+    {
2133 2133
         // phpcs:enable
2134
-		global $user;
2135
-		$error=0;
2134
+        global $user;
2135
+        $error=0;
2136
+
2137
+        $this->db->begin();
2138
+
2139
+        $sql = 'UPDATE '.MAIN_DB_PREFIX.'expedition SET fk_statut=2, billed=1';    // TODO Update only billed
2140
+        $sql .= ' WHERE rowid = '.$this->id.' AND fk_statut > 0';
2141
+
2142
+        $resql=$this->db->query($sql);
2143
+        if ($resql)
2144
+        {
2145
+            $this->statut=2;
2146
+            $this->billed=1;
2147
+
2148
+            // Call trigger
2149
+            $result=$this->call_trigger('SHIPPING_BILLED',$user);
2150
+            if ($result < 0) {
2151
+                $error++;
2152
+            }
2153
+        } else {
2154
+            $error++;
2155
+            $this->errors[]=$this->db->lasterror;
2156
+        }
2157
+
2158
+        if (empty($error)) {
2159
+            $this->db->commit();
2160
+            return 1;
2161
+        }
2162
+        else
2163
+        {
2164
+            $this->db->rollback();
2165
+            return -1;
2166
+        }
2167
+    }
2136 2168
 
2137
-		$this->db->begin();
2169
+    /**
2170
+     *	Classify the shipping as validated/opened
2171
+     *
2172
+     *	@return     int     <0 if KO, 0 if already open, >0 if OK
2173
+     */
2174
+    function reOpen()
2175
+    {
2176
+        global $conf,$langs,$user;
2177
+
2178
+        $error=0;
2179
+
2180
+        // Protection. This avoid to move stock later when we should not
2181
+        if ($this->statut == self::STATUS_VALIDATED)
2182
+        {
2183
+            return 0;
2184
+        }
2185
+
2186
+        $this->db->begin();
2187
+
2188
+        $sql = 'UPDATE '.MAIN_DB_PREFIX.'expedition SET fk_statut=1';
2189
+        $sql .= ' WHERE rowid = '.$this->id.' AND fk_statut > 0';
2190
+
2191
+        $resql=$this->db->query($sql);
2192
+        if ($resql)
2193
+        {
2194
+            $this->statut=1;
2195
+            $this->billed=0;
2196
+
2197
+            // If stock increment is done on closing
2198
+            if (! $error && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE))
2199
+            {
2200
+                require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
2201
+
2202
+                $langs->load("agenda");
2203
+
2204
+                // Loop on each product line to add a stock movement
2205
+                // TODO possibilite d'expedier a partir d'une propale ou autre origine
2206
+                $sql = "SELECT cd.fk_product, cd.subprice,";
2207
+                $sql.= " ed.rowid, ed.qty, ed.fk_entrepot,";
2208
+                $sql.= " edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
2209
+                $sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd,";
2210
+                $sql.= " ".MAIN_DB_PREFIX."expeditiondet as ed";
2211
+                $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
2212
+                $sql.= " WHERE ed.fk_expedition = ".$this->id;
2213
+                $sql.= " AND cd.rowid = ed.fk_origin_line";
2214
+
2215
+                dol_syslog(get_class($this)."::valid select details", LOG_DEBUG);
2216
+                $resql=$this->db->query($sql);
2217
+                if ($resql)
2218
+                {
2219
+                    $cpt = $this->db->num_rows($resql);
2220
+                    for ($i = 0; $i < $cpt; $i++)
2221
+                    {
2222
+                        $obj = $this->db->fetch_object($resql);
2223
+                        if (empty($obj->edbrowid))
2224
+                        {
2225
+                            $qty = $obj->qty;
2226
+                        }
2227
+                        else
2228
+                        {
2229
+                            $qty = $obj->edbqty;
2230
+                        }
2231
+                        if ($qty <= 0) continue;
2232
+                        dol_syslog(get_class($this)."::reopen expedition movement index ".$i." ed.rowid=".$obj->rowid." edb.rowid=".$obj->edbrowid);
2233
+
2234
+                        //var_dump($this->lines[$i]);
2235
+                        $mouvS = new MouvementStock($this->db);
2236
+                        $mouvS->origin = &$this;
2237
+
2238
+                        if (empty($obj->edbrowid))
2239
+                        {
2240
+                            // line without batch detail
2241
+
2242
+                            // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
2243
+                            $result=$mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ShipmentUnClassifyCloseddInDolibarr",$numref));
2244
+                            if ($result < 0) {
2245
+                                $this->error = $mouvS->error;
2246
+                                $this->errors = $mouvS->errors;
2247
+                                $error++; break;
2248
+                            }
2249
+                        }
2250
+                        else
2251
+                        {
2252
+                            // line with batch detail
2253
+
2254
+                            // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
2255
+                            $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);
2256
+                            if ($result < 0) {
2257
+                                $this->error = $mouvS->error;
2258
+                                $this->errors = $mouvS->errors;
2259
+                                $error++; break;
2260
+                            }
2261
+                        }
2262
+                    }
2263
+                }
2264
+                else
2265
+                {
2266
+                    $this->error=$this->db->lasterror();
2267
+                    $error++;
2268
+                }
2269
+            }
2270
+
2271
+            if (! $error)
2272
+            {
2273
+                // Call trigger
2274
+                $result=$this->call_trigger('SHIPPING_REOPEN',$user);
2275
+                if ($result < 0) {
2276
+                    $error++;
2277
+                }
2278
+                }
2279
+        } else {
2280
+            $error++;
2281
+            $this->errors[]=$this->db->lasterror();
2282
+        }
2283
+
2284
+        if (! $error)
2285
+        {
2286
+            $this->db->commit();
2287
+            return 1;
2288
+        }
2289
+        else
2290
+        {
2291
+            $this->db->rollback();
2292
+            return -1;
2293
+        }
2294
+    }
2138 2295
 
2139
-		$sql = 'UPDATE '.MAIN_DB_PREFIX.'expedition SET fk_statut=2, billed=1';    // TODO Update only billed
2140
-		$sql .= ' WHERE rowid = '.$this->id.' AND fk_statut > 0';
2296
+    /**
2297
+     *  Create a document onto disk according to template module.
2298
+     *
2299
+     *  @param	    string		$modele			Force the model to using ('' to not force)
2300
+     *  @param		Translate	$outputlangs	object lang to use for translations
2301
+     *  @param      int			$hidedetails    Hide details of lines
2302
+     *  @param      int			$hidedesc       Hide description
2303
+     *  @param      int			$hideref        Hide ref
2304
+     *  @param      null|array  $moreparams     Array to provide more information
2305
+     *  @return     int         				0 if KO, 1 if OK
2306
+     */
2307
+    public function generateDocument($modele, $outputlangs,$hidedetails=0, $hidedesc=0, $hideref=0,$moreparams=null)
2308
+    {
2309
+        global $conf,$langs;
2141 2310
 
2142
-		$resql=$this->db->query($sql);
2143
-		if ($resql)
2144
-		{
2145
-			$this->statut=2;
2146
-			$this->billed=1;
2147
-
2148
-			// Call trigger
2149
-			$result=$this->call_trigger('SHIPPING_BILLED',$user);
2150
-			if ($result < 0) {
2151
-				$error++;
2152
-			}
2153
-		} else {
2154
-			$error++;
2155
-			$this->errors[]=$this->db->lasterror;
2156
-		}
2157
-
2158
-		if (empty($error)) {
2159
-			$this->db->commit();
2160
-			return 1;
2161
-		}
2162
-		else
2163
-		{
2164
-			$this->db->rollback();
2165
-			return -1;
2166
-		}
2167
-	}
2168
-
2169
-	/**
2170
-	 *	Classify the shipping as validated/opened
2171
-	 *
2172
-	 *	@return     int     <0 if KO, 0 if already open, >0 if OK
2173
-	 */
2174
-	function reOpen()
2175
-	{
2176
-		global $conf,$langs,$user;
2177
-
2178
-		$error=0;
2179
-
2180
-		// Protection. This avoid to move stock later when we should not
2181
-		if ($this->statut == self::STATUS_VALIDATED)
2182
-		{
2183
-			return 0;
2184
-		}
2311
+        $langs->load("sendings");
2185 2312
 
2186
-		$this->db->begin();
2313
+        if (! dol_strlen($modele)) {
2187 2314
 
2188
-		$sql = 'UPDATE '.MAIN_DB_PREFIX.'expedition SET fk_statut=1';
2189
-		$sql .= ' WHERE rowid = '.$this->id.' AND fk_statut > 0';
2315
+            $modele = 'rouget';
2190 2316
 
2191
-		$resql=$this->db->query($sql);
2192
-		if ($resql)
2193
-		{
2194
-			$this->statut=1;
2195
-			$this->billed=0;
2196
-
2197
-			// If stock increment is done on closing
2198
-			if (! $error && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE))
2199
-			{
2200
-				require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
2201
-
2202
-				$langs->load("agenda");
2203
-
2204
-				// Loop on each product line to add a stock movement
2205
-				// TODO possibilite d'expedier a partir d'une propale ou autre origine
2206
-				$sql = "SELECT cd.fk_product, cd.subprice,";
2207
-				$sql.= " ed.rowid, ed.qty, ed.fk_entrepot,";
2208
-				$sql.= " edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock";
2209
-				$sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd,";
2210
-				$sql.= " ".MAIN_DB_PREFIX."expeditiondet as ed";
2211
-				$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
2212
-				$sql.= " WHERE ed.fk_expedition = ".$this->id;
2213
-				$sql.= " AND cd.rowid = ed.fk_origin_line";
2214
-
2215
-				dol_syslog(get_class($this)."::valid select details", LOG_DEBUG);
2216
-				$resql=$this->db->query($sql);
2217
-				if ($resql)
2218
-				{
2219
-					$cpt = $this->db->num_rows($resql);
2220
-					for ($i = 0; $i < $cpt; $i++)
2221
-					{
2222
-						$obj = $this->db->fetch_object($resql);
2223
-						if (empty($obj->edbrowid))
2224
-						{
2225
-							$qty = $obj->qty;
2226
-						}
2227
-						else
2228
-						{
2229
-							$qty = $obj->edbqty;
2230
-						}
2231
-						if ($qty <= 0) continue;
2232
-						dol_syslog(get_class($this)."::reopen expedition movement index ".$i." ed.rowid=".$obj->rowid." edb.rowid=".$obj->edbrowid);
2233
-
2234
-						//var_dump($this->lines[$i]);
2235
-						$mouvS = new MouvementStock($this->db);
2236
-						$mouvS->origin = &$this;
2237
-
2238
-						if (empty($obj->edbrowid))
2239
-						{
2240
-							// line without batch detail
2241
-
2242
-							// We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
2243
-							$result=$mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ShipmentUnClassifyCloseddInDolibarr",$numref));
2244
-							if ($result < 0) {
2245
-								$this->error = $mouvS->error;
2246
-								$this->errors = $mouvS->errors;
2247
-								$error++; break;
2248
-							}
2249
-						}
2250
-						else
2251
-						{
2252
-							// line with batch detail
2253
-
2254
-							// We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
2255
-							$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);
2256
-							if ($result < 0) {
2257
-								$this->error = $mouvS->error;
2258
-								$this->errors = $mouvS->errors;
2259
-								$error++; break;
2260
-							}
2261
-						}
2262
-					}
2263
-				}
2264
-				else
2265
-				{
2266
-					$this->error=$this->db->lasterror();
2267
-					$error++;
2268
-				}
2269
-			}
2270
-
2271
-			if (! $error)
2272
-			{
2273
-				// Call trigger
2274
-				$result=$this->call_trigger('SHIPPING_REOPEN',$user);
2275
-				if ($result < 0) {
2276
-					$error++;
2277
-				}
2278
-   			}
2279
-		} else {
2280
-			$error++;
2281
-			$this->errors[]=$this->db->lasterror();
2282
-		}
2283
-
2284
-		if (! $error)
2285
-		{
2286
-			$this->db->commit();
2287
-			return 1;
2288
-		}
2289
-		else
2290
-		{
2291
-			$this->db->rollback();
2292
-			return -1;
2293
-		}
2294
-	}
2295
-
2296
-	/**
2297
-	 *  Create a document onto disk according to template module.
2298
-	 *
2299
-	 *  @param	    string		$modele			Force the model to using ('' to not force)
2300
-	 *  @param		Translate	$outputlangs	object lang to use for translations
2301
-	 *  @param      int			$hidedetails    Hide details of lines
2302
-	 *  @param      int			$hidedesc       Hide description
2303
-	 *  @param      int			$hideref        Hide ref
2304
-     *  @param      null|array  $moreparams     Array to provide more information
2305
-	 *  @return     int         				0 if KO, 1 if OK
2306
-	 */
2307
-	public function generateDocument($modele, $outputlangs,$hidedetails=0, $hidedesc=0, $hideref=0,$moreparams=null)
2308
-	{
2309
-		global $conf,$langs;
2310
-
2311
-		$langs->load("sendings");
2312
-
2313
-		if (! dol_strlen($modele)) {
2314
-
2315
-			$modele = 'rouget';
2316
-
2317
-			if ($this->modelpdf) {
2318
-				$modele = $this->modelpdf;
2319
-			} elseif (! empty($conf->global->EXPEDITION_ADDON_PDF)) {
2320
-				$modele = $conf->global->EXPEDITION_ADDON_PDF;
2321
-			}
2322
-		}
2323
-
2324
-		$modelpath = "core/modules/expedition/doc/";
2325
-
2326
-		$this->fetch_origin();
2327
-
2328
-		return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref,$moreparams);
2329
-	}
2330
-
2331
-	/**
2332
-	 * Function used to replace a thirdparty id with another one.
2333
-	 *
2334
-	 * @param DoliDB $db Database handler
2335
-	 * @param int $origin_id Old thirdparty id
2336
-	 * @param int $dest_id New thirdparty id
2337
-	 * @return bool
2338
-	 */
2339
-	public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
2340
-	{
2341
-		$tables = array(
2342
-			'expedition'
2343
-		);
2344
-
2345
-		return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2346
-	}
2317
+            if ($this->modelpdf) {
2318
+                $modele = $this->modelpdf;
2319
+            } elseif (! empty($conf->global->EXPEDITION_ADDON_PDF)) {
2320
+                $modele = $conf->global->EXPEDITION_ADDON_PDF;
2321
+            }
2322
+        }
2323
+
2324
+        $modelpath = "core/modules/expedition/doc/";
2325
+
2326
+        $this->fetch_origin();
2327
+
2328
+        return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref,$moreparams);
2329
+    }
2330
+
2331
+    /**
2332
+     * Function used to replace a thirdparty id with another one.
2333
+     *
2334
+     * @param DoliDB $db Database handler
2335
+     * @param int $origin_id Old thirdparty id
2336
+     * @param int $dest_id New thirdparty id
2337
+     * @return bool
2338
+     */
2339
+    public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
2340
+    {
2341
+        $tables = array(
2342
+            'expedition'
2343
+        );
2344
+
2345
+        return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2346
+    }
2347 2347
 }
2348 2348
 
2349 2349
 
@@ -2352,33 +2352,33 @@  discard block
 block discarded – undo
2352 2352
  */
2353 2353
 class ExpeditionLigne extends CommonObjectLine
2354 2354
 {
2355
-	/**
2356
-	 * @var string ID to identify managed object
2357
-	 */
2358
-	public $element='expeditiondet';
2359
-
2360
-	/**
2361
-	 * @var string Name of table without prefix where object is stored
2362
-	 */
2363
-	public $table_element='expeditiondet';
2364
-
2365
-	/**
2366
-	 * @deprecated
2367
-	 * @see fk_origin_line
2368
-	 */
2369
-	public $origin_line_id;
2370
-
2371
-	/**
2355
+    /**
2356
+     * @var string ID to identify managed object
2357
+     */
2358
+    public $element='expeditiondet';
2359
+
2360
+    /**
2361
+     * @var string Name of table without prefix where object is stored
2362
+     */
2363
+    public $table_element='expeditiondet';
2364
+
2365
+    /**
2366
+     * @deprecated
2367
+     * @see fk_origin_line
2368
+     */
2369
+    public $origin_line_id;
2370
+
2371
+    /**
2372 2372
      * @var int ID
2373 2373
      */
2374
-	public $fk_origin_line;
2374
+    public $fk_origin_line;
2375 2375
 
2376
-	/**
2377
-	 * @var int Id of shipment
2378
-	 */
2379
-	public $fk_expedition;
2376
+    /**
2377
+     * @var int Id of shipment
2378
+     */
2379
+    public $fk_expedition;
2380 2380
 
2381
-	/**
2381
+    /**
2382 2382
      * @var DoliDB Database handler.
2383 2383
      */
2384 2384
     public $db;
@@ -2402,13 +2402,13 @@  discard block
 block discarded – undo
2402 2402
     /**
2403 2403
      * @var int Id of warehouse
2404 2404
      */
2405
-	public $entrepot_id;
2405
+    public $entrepot_id;
2406 2406
 
2407 2407
 
2408 2408
     /**
2409 2409
      * @var float qty asked From llx_commandedet or llx_propaldet
2410 2410
      */
2411
-	public $qty_asked;
2411
+    public $qty_asked;
2412 2412
 
2413 2413
     /**
2414 2414
      * @deprecated
@@ -2416,21 +2416,21 @@  discard block
 block discarded – undo
2416 2416
      */
2417 2417
     public $ref;
2418 2418
 
2419
-	/**
2420
-	 * @var string product ref
2421
-	 */
2422
-	public $product_ref;
2419
+    /**
2420
+     * @var string product ref
2421
+     */
2422
+    public $product_ref;
2423 2423
 
2424
-	/**
2425
-	 * @deprecated
2426
-	 * @see product_label
2427
-	 */
2428
-	public $libelle;
2424
+    /**
2425
+     * @deprecated
2426
+     * @see product_label
2427
+     */
2428
+    public $libelle;
2429 2429
 
2430 2430
     /**
2431 2431
      * @var string product label
2432 2432
      */
2433
-	public $product_label;
2433
+    public $product_label;
2434 2434
 
2435 2435
     /**
2436 2436
      * @var string product description
@@ -2442,7 +2442,7 @@  discard block
 block discarded – undo
2442 2442
     /**
2443 2443
      * @var string product description
2444 2444
      */
2445
-	public $product_desc;
2445
+    public $product_desc;
2446 2446
 
2447 2447
     /**
2448 2448
      * @var float weight
@@ -2468,8 +2468,8 @@  discard block
 block discarded – undo
2468 2468
     public $volume;
2469 2469
     public $volume_units;
2470 2470
 
2471
-	// Invoicing
2472
-	public $remise_percent;
2471
+    // Invoicing
2472
+    public $remise_percent;
2473 2473
     public $tva_tx;
2474 2474
 
2475 2475
     /**
@@ -2503,400 +2503,400 @@  discard block
 block discarded – undo
2503 2503
      *
2504 2504
      *  @param		DoliDB		$db      Database handler
2505 2505
      */
2506
-	function __construct($db)
2507
-	{
2508
-		$this->db=$db;
2509
-	}
2510
-
2511
-	/**
2512
-	 *  Load line expedition
2513
-	 *
2514
-	 *  @param  int		$rowid          Id line order
2515
-	 *  @return	int						<0 if KO, >0 if OK
2516
-	 */
2517
-	function fetch($rowid)
2518
-	{
2519
-		$sql = 'SELECT ed.rowid, ed.fk_expedition, ed.fk_entrepot, ed.fk_origin_line, ed.qty, ed.rang';
2520
-		$sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as ed';
2521
-		$sql.= ' WHERE ed.rowid = '.$rowid;
2522
-		$result = $this->db->query($sql);
2523
-		if ($result)
2524
-		{
2525
-			$objp = $this->db->fetch_object($result);
2526
-			$this->id				= $objp->rowid;
2527
-			$this->fk_expedition	= $objp->fk_expedition;
2528
-			$this->entrepot_id		= $objp->fk_entrepot;
2529
-			$this->fk_origin_line	= $objp->fk_origin_line;
2530
-			$this->qty				= $objp->qty;
2531
-			$this->rang				= $objp->rang;
2532
-
2533
-			$this->db->free($result);
2534
-
2535
-			return 1;
2536
-		}
2537
-		else
2538
-		{
2539
-			$this->errors[] = $this->db->lasterror();
2540
-			$this->error = $this->db->lasterror();
2541
-			return -1;
2542
-		}
2543
-	}
2544
-
2545
-	/**
2546
-	 *	Insert line into database
2547
-	 *
2548
-	 *	@param      User	$user			User that modify
2549
-	 *	@param      int		$notrigger		1 = disable triggers
2550
-	 *	@return     int						<0 if KO, line id >0 if OK
2551
-	 */
2552
-	function insert($user=null, $notrigger=0)
2553
-	{
2554
-		global $langs, $conf;
2555
-
2556
-		$error=0;
2557
-
2558
-		// Check parameters
2559
-		if (empty($this->fk_expedition) || empty($this->fk_origin_line) || ! is_numeric($this->qty))
2560
-		{
2561
-			$this->error = 'ErrorMandatoryParametersNotProvided';
2562
-			return -1;
2563
-		}
2564
-		// Clean parameters
2565
-		if (empty($this->entrepot_id)) $this->entrepot_id='null';
2566
-
2567
-		$this->db->begin();
2568
-
2569
-		$sql = "INSERT INTO ".MAIN_DB_PREFIX."expeditiondet (";
2570
-		$sql.= "fk_expedition";
2571
-		$sql.= ", fk_entrepot";
2572
-		$sql.= ", fk_origin_line";
2573
-		$sql.= ", qty";
2574
-		$sql.= ") VALUES (";
2575
-		$sql.= $this->fk_expedition;
2576
-		$sql.= ", ".$this->entrepot_id;
2577
-		$sql.= ", ".$this->fk_origin_line;
2578
-		$sql.= ", ".$this->qty;
2579
-		$sql.= ")";
2580
-
2581
-		dol_syslog(get_class($this)."::insert", LOG_DEBUG);
2582
-		$resql = $this->db->query($sql);
2583
-		if ($resql)
2584
-		{
2585
-			$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."expeditiondet");
2586
-
2587
-			if (! $error && empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))
2588
-			{
2589
-				$result=$this->insertExtraFields();
2590
-				if ($result < 0)
2591
-				{
2592
-					$error++;
2593
-				}
2594
-			}
2595
-
2596
-			if (! $error && ! $notrigger)
2597
-			{
2598
-				// Call trigger
2599
-				$result=$this->call_trigger('LINESHIPPING_INSERT',$user);
2600
-				if ($result < 0)
2601
-				{
2602
-					$error++;
2603
-				}
2604
-				// End call triggers
2605
-			}
2606
-
2607
-			if (! $error) {
2608
-				$this->db->commit();
2609
-				return $this->id;
2610
-			}
2611
-
2612
-			foreach($this->errors as $errmsg)
2613
-			{
2614
-				dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
2615
-				$this->error.=($this->error?', '.$errmsg:$errmsg);
2616
-			}
2617
-
2618
-			$this->db->rollback();
2619
-			return -1*$error;
2620
-		}
2621
-		else
2622
-		{
2623
-			$error++;
2624
-		}
2625
-	}
2626
-
2627
-	/**
2628
-	 * 	Delete shipment line.
2629
-	 *
2630
-	 *	@param		User	$user			User that modify
2631
-	 *	@param		int		$notrigger		0=launch triggers after, 1=disable triggers
2632
-	 * 	@return		int		>0 if OK, <0 if KO
2633
-	 */
2634
-	function delete($user = null, $notrigger = 0)
2635
-	{
2636
-		global $conf;
2637
-
2638
-		$error=0;
2639
-
2640
-		$this->db->begin();
2641
-
2642
-		// delete batch expedition line
2643
-		if ($conf->productbatch->enabled)
2644
-		{
2645
-			$sql = "DELETE FROM ".MAIN_DB_PREFIX."expeditiondet_batch";
2646
-			$sql.= " WHERE fk_expeditiondet = ".$this->id;
2506
+    function __construct($db)
2507
+    {
2508
+        $this->db=$db;
2509
+    }
2647 2510
 
2648
-			if (!$this->db->query($sql))
2649
-			{
2650
-				$this->errors[]=$this->db->lasterror()." - sql=$sql";
2651
-				$error++;
2652
-			}
2653
-		}
2654
-
2655
-		$sql = "DELETE FROM ".MAIN_DB_PREFIX."expeditiondet";
2656
-		$sql.= " WHERE rowid = ".$this->id;
2511
+    /**
2512
+     *  Load line expedition
2513
+     *
2514
+     *  @param  int		$rowid          Id line order
2515
+     *  @return	int						<0 if KO, >0 if OK
2516
+     */
2517
+    function fetch($rowid)
2518
+    {
2519
+        $sql = 'SELECT ed.rowid, ed.fk_expedition, ed.fk_entrepot, ed.fk_origin_line, ed.qty, ed.rang';
2520
+        $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as ed';
2521
+        $sql.= ' WHERE ed.rowid = '.$rowid;
2522
+        $result = $this->db->query($sql);
2523
+        if ($result)
2524
+        {
2525
+            $objp = $this->db->fetch_object($result);
2526
+            $this->id				= $objp->rowid;
2527
+            $this->fk_expedition	= $objp->fk_expedition;
2528
+            $this->entrepot_id		= $objp->fk_entrepot;
2529
+            $this->fk_origin_line	= $objp->fk_origin_line;
2530
+            $this->qty				= $objp->qty;
2531
+            $this->rang				= $objp->rang;
2532
+
2533
+            $this->db->free($result);
2534
+
2535
+            return 1;
2536
+        }
2537
+        else
2538
+        {
2539
+            $this->errors[] = $this->db->lasterror();
2540
+            $this->error = $this->db->lasterror();
2541
+            return -1;
2542
+        }
2543
+    }
2657 2544
 
2658
-		if (! $error && $this->db->query($sql))
2659
-		{
2660
-			// Remove extrafields
2661
-			if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
2662
-			{
2663
-				$result=$this->deleteExtraFields();
2664
-				if ($result < 0)
2665
-				{
2666
-					$this->errors[]=$this->error;
2667
-					$error++;
2668
-				}
2669
-			}
2670
-			if (! $error && ! $notrigger)
2671
-			{
2672
-				// Call trigger
2673
-				$result=$this->call_trigger('LINESHIPPING_DELETE',$user);
2674
-				if ($result < 0)
2675
-				{
2676
-					$this->errors[]=$this->error;
2677
-					$error++;
2678
-				}
2679
-				// End call triggers
2680
-			}
2681
-		}
2682
-		else
2683
-		{
2684
-			$this->errors[]=$this->db->lasterror()." - sql=$sql";
2685
-			$error++;
2686
-		}
2687
-
2688
-		if (! $error) {
2689
-			$this->db->commit();
2690
-			return 1;
2691
-		}
2692
-		else
2693
-		{
2694
-			foreach($this->errors as $errmsg)
2695
-			{
2696
-				dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
2697
-				$this->error.=($this->error?', '.$errmsg:$errmsg);
2698
-			}
2699
-			$this->db->rollback();
2700
-			return -1*$error;
2701
-		}
2702
-	}
2703
-
2704
-	/**
2705
-	 *  Update a line in database
2706
-	 *
2707
-	 *	@param		User	$user			User that modify
2708
-	 *	@param		int		$notrigger		1 = disable triggers
2709
-	 *  @return		int					< 0 if KO, > 0 if OK
2710
-	 */
2711
-	function update($user = null, $notrigger = 0)
2712
-	{
2713
-		global $conf;
2714
-
2715
-		$error=0;
2716
-
2717
-		dol_syslog(get_class($this)."::update id=$this->id, entrepot_id=$this->entrepot_id, product_id=$this->fk_product, qty=$this->qty");
2718
-
2719
-		$this->db->begin();
2720
-
2721
-		// Clean parameters
2722
-		if (empty($this->qty)) $this->qty=0;
2723
-		$qty=price2num($this->qty);
2724
-		$remainingQty = 0;
2725
-		$batch = null;
2726
-		$batch_id = null;
2727
-		$expedition_batch_id = null;
2728
-		if (is_array($this->detail_batch)) 	// array of ExpeditionLineBatch
2729
-		{
2730
-			if (count($this->detail_batch) > 1)
2731
-			{
2732
-				dol_syslog(get_class($this).'::update only possible for one batch', LOG_ERR);
2733
-				$this->errors[]='ErrorBadParameters';
2734
-				$error++;
2735
-			}
2736
-			else
2737
-			{
2738
-				$batch = $this->detail_batch[0]->batch;
2739
-				$batch_id = $this->detail_batch[0]->fk_origin_stock;
2740
-				$expedition_batch_id = $this->detail_batch[0]->id;
2741
-				if ($this->entrepot_id != $this->detail_batch[0]->entrepot_id)
2742
-				{
2743
-					dol_syslog(get_class($this).'::update only possible for batch of same warehouse', LOG_ERR);
2744
-					$this->errors[]='ErrorBadParameters';
2745
-					$error++;
2746
-				}
2747
-				$qty = price2num($this->detail_batch[0]->qty);
2748
-			}
2749
-		}
2750
-		else if (! empty($this->detail_batch))
2751
-		{
2752
-			$batch = $this->detail_batch->batch;
2753
-			$batch_id = $this->detail_batch->fk_origin_stock;
2754
-			$expedition_batch_id = $this->detail_batch->id;
2755
-			if ($this->entrepot_id != $this->detail_batch->entrepot_id)
2756
-			{
2757
-				dol_syslog(get_class($this).'::update only possible for batch of same warehouse', LOG_ERR);
2758
-				$this->errors[]='ErrorBadParameters';
2759
-				$error++;
2760
-			}
2761
-			$qty = price2num($this->detail_batch->qty);
2762
-		}
2763
-
2764
-		// check parameters
2765
-		if (! isset($this->id) || ! isset($this->entrepot_id))
2766
-		{
2767
-			dol_syslog(get_class($this).'::update missing line id and/or warehouse id', LOG_ERR);
2768
-			$this->errors[]='ErrorMandatoryParametersNotProvided';
2769
-			$error++;
2770
-			return -1;
2771
-		}
2545
+    /**
2546
+     *	Insert line into database
2547
+     *
2548
+     *	@param      User	$user			User that modify
2549
+     *	@param      int		$notrigger		1 = disable triggers
2550
+     *	@return     int						<0 if KO, line id >0 if OK
2551
+     */
2552
+    function insert($user=null, $notrigger=0)
2553
+    {
2554
+        global $langs, $conf;
2555
+
2556
+        $error=0;
2557
+
2558
+        // Check parameters
2559
+        if (empty($this->fk_expedition) || empty($this->fk_origin_line) || ! is_numeric($this->qty))
2560
+        {
2561
+            $this->error = 'ErrorMandatoryParametersNotProvided';
2562
+            return -1;
2563
+        }
2564
+        // Clean parameters
2565
+        if (empty($this->entrepot_id)) $this->entrepot_id='null';
2566
+
2567
+        $this->db->begin();
2568
+
2569
+        $sql = "INSERT INTO ".MAIN_DB_PREFIX."expeditiondet (";
2570
+        $sql.= "fk_expedition";
2571
+        $sql.= ", fk_entrepot";
2572
+        $sql.= ", fk_origin_line";
2573
+        $sql.= ", qty";
2574
+        $sql.= ") VALUES (";
2575
+        $sql.= $this->fk_expedition;
2576
+        $sql.= ", ".$this->entrepot_id;
2577
+        $sql.= ", ".$this->fk_origin_line;
2578
+        $sql.= ", ".$this->qty;
2579
+        $sql.= ")";
2580
+
2581
+        dol_syslog(get_class($this)."::insert", LOG_DEBUG);
2582
+        $resql = $this->db->query($sql);
2583
+        if ($resql)
2584
+        {
2585
+            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."expeditiondet");
2586
+
2587
+            if (! $error && empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))
2588
+            {
2589
+                $result=$this->insertExtraFields();
2590
+                if ($result < 0)
2591
+                {
2592
+                    $error++;
2593
+                }
2594
+            }
2595
+
2596
+            if (! $error && ! $notrigger)
2597
+            {
2598
+                // Call trigger
2599
+                $result=$this->call_trigger('LINESHIPPING_INSERT',$user);
2600
+                if ($result < 0)
2601
+                {
2602
+                    $error++;
2603
+                }
2604
+                // End call triggers
2605
+            }
2606
+
2607
+            if (! $error) {
2608
+                $this->db->commit();
2609
+                return $this->id;
2610
+            }
2611
+
2612
+            foreach($this->errors as $errmsg)
2613
+            {
2614
+                dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
2615
+                $this->error.=($this->error?', '.$errmsg:$errmsg);
2616
+            }
2617
+
2618
+            $this->db->rollback();
2619
+            return -1*$error;
2620
+        }
2621
+        else
2622
+        {
2623
+            $error++;
2624
+        }
2625
+    }
2772 2626
 
2773
-		// update lot
2627
+    /**
2628
+     * 	Delete shipment line.
2629
+     *
2630
+     *	@param		User	$user			User that modify
2631
+     *	@param		int		$notrigger		0=launch triggers after, 1=disable triggers
2632
+     * 	@return		int		>0 if OK, <0 if KO
2633
+     */
2634
+    function delete($user = null, $notrigger = 0)
2635
+    {
2636
+        global $conf;
2637
+
2638
+        $error=0;
2639
+
2640
+        $this->db->begin();
2641
+
2642
+        // delete batch expedition line
2643
+        if ($conf->productbatch->enabled)
2644
+        {
2645
+            $sql = "DELETE FROM ".MAIN_DB_PREFIX."expeditiondet_batch";
2646
+            $sql.= " WHERE fk_expeditiondet = ".$this->id;
2647
+
2648
+            if (!$this->db->query($sql))
2649
+            {
2650
+                $this->errors[]=$this->db->lasterror()." - sql=$sql";
2651
+                $error++;
2652
+            }
2653
+        }
2654
+
2655
+        $sql = "DELETE FROM ".MAIN_DB_PREFIX."expeditiondet";
2656
+        $sql.= " WHERE rowid = ".$this->id;
2657
+
2658
+        if (! $error && $this->db->query($sql))
2659
+        {
2660
+            // Remove extrafields
2661
+            if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
2662
+            {
2663
+                $result=$this->deleteExtraFields();
2664
+                if ($result < 0)
2665
+                {
2666
+                    $this->errors[]=$this->error;
2667
+                    $error++;
2668
+                }
2669
+            }
2670
+            if (! $error && ! $notrigger)
2671
+            {
2672
+                // Call trigger
2673
+                $result=$this->call_trigger('LINESHIPPING_DELETE',$user);
2674
+                if ($result < 0)
2675
+                {
2676
+                    $this->errors[]=$this->error;
2677
+                    $error++;
2678
+                }
2679
+                // End call triggers
2680
+            }
2681
+        }
2682
+        else
2683
+        {
2684
+            $this->errors[]=$this->db->lasterror()." - sql=$sql";
2685
+            $error++;
2686
+        }
2687
+
2688
+        if (! $error) {
2689
+            $this->db->commit();
2690
+            return 1;
2691
+        }
2692
+        else
2693
+        {
2694
+            foreach($this->errors as $errmsg)
2695
+            {
2696
+                dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
2697
+                $this->error.=($this->error?', '.$errmsg:$errmsg);
2698
+            }
2699
+            $this->db->rollback();
2700
+            return -1*$error;
2701
+        }
2702
+    }
2774 2703
 
2775
-		if (! empty($batch) && $conf->productbatch->enabled)
2776
-		{
2777
-			dol_syslog(get_class($this)."::update expedition batch id=$expedition_batch_id, batch_id=$batch_id, batch=$batch");
2778
-
2779
-			if (empty($batch_id) || empty($this->fk_product)) {
2780
-				dol_syslog(get_class($this).'::update missing fk_origin_stock (batch_id) and/or fk_product', LOG_ERR);
2781
-				$this->errors[]='ErrorMandatoryParametersNotProvided';
2782
-				$error++;
2783
-			}
2784
-
2785
-			// fetch remaining lot qty
2786
-			require_once DOL_DOCUMENT_ROOT.'/expedition/class/expeditionbatch.class.php';
2787
-			if (! $error && ($lotArray = ExpeditionLineBatch::fetchAll($this->db, $this->id)) < 0)
2788
-			{
2789
-				$this->errors[]=$this->db->lasterror()." - ExpeditionLineBatch::fetchAll";
2790
-				$error++;
2791
-			}
2792
-			else
2793
-			{
2794
-				// caculate new total line qty
2795
-				foreach ($lotArray as $lot)
2796
-				{
2797
-					if ($expedition_batch_id != $lot->id)
2798
-					{
2799
-						$remainingQty += $lot->qty;
2800
-					}
2801
-				}
2802
-				$qty += $remainingQty;
2803
-
2804
-				//fetch lot details
2805
-
2806
-				// fetch from product_lot
2807
-				require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
2808
-				$lot = new Productlot($this->db);
2809
-				if ($lot->fetch(0,$this->fk_product,$batch) < 0)
2810
-				{
2811
-					$this->errors[] = $lot->errors;
2812
-					$error++;
2813
-				}
2814
-				if (! $error && ! empty($expedition_batch_id))
2815
-				{
2816
-					// delete lot expedition line
2817
-					$sql = "DELETE FROM ".MAIN_DB_PREFIX."expeditiondet_batch";
2818
-					$sql.= " WHERE fk_expeditiondet = ".$this->id;
2819
-					$sql.= " AND rowid = ".$expedition_batch_id;
2820
-
2821
-					if (!$this->db->query($sql))
2822
-					{
2823
-						$this->errors[]=$this->db->lasterror()." - sql=$sql";
2824
-						$error++;
2825
-					}
2826
-				}
2827
-				if (! $error && $this->detail_batch->qty > 0)
2828
-				{
2829
-					// create lot expedition line
2830
-					if (isset($lot->id))
2831
-					{
2832
-						$shipmentLot = new ExpeditionLineBatch($this->db);
2833
-						$shipmentLot->batch = $lot->batch;
2834
-						$shipmentLot->eatby = $lot->eatby;
2835
-						$shipmentLot->sellby = $lot->sellby;
2836
-						$shipmentLot->entrepot_id = $this->detail_batch->entrepot_id;
2837
-						$shipmentLot->qty = $this->detail_batch->qty;
2838
-						$shipmentLot->fk_origin_stock = $batch_id;
2839
-						if ($shipmentLot->create($this->id) < 0)
2840
-						{
2841
-							$this->errors[]=$shipmentLot->errors;
2842
-							$error++;
2843
-						}
2844
-					}
2845
-				}
2846
-			}
2847
-		}
2848
-		if (! $error)
2849
-		{
2850
-			// update line
2851
-			$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
2852
-			$sql.= " fk_entrepot = ".($this->entrepot_id > 0 ? $this->entrepot_id : 'null');
2853
-			$sql.= " , qty = ".$qty;
2854
-			$sql.= " WHERE rowid = ".$this->id;
2855
-
2856
-			if (!$this->db->query($sql))
2857
-			{
2858
-				$this->errors[]=$this->db->lasterror()." - sql=$sql";
2859
-				$error++;
2860
-			}
2861
-		}
2862
-
2863
-		if (! $error)
2864
-		{
2865
-			if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
2866
-			{
2867
-				$result=$this->insertExtraFields();
2868
-				if ($result < 0)
2869
-				{
2870
-					$this->errors[]=$this->error;
2871
-					$error++;
2872
-				}
2873
-			}
2874
-		}
2875
-
2876
-		if (! $error && ! $notrigger)
2877
-		{
2878
-			// Call trigger
2879
-			$result=$this->call_trigger('LINESHIPPING_UPDATE',$user);
2880
-			if ($result < 0)
2881
-			{
2882
-				$this->errors[]=$this->error;
2883
-				$error++;
2884
-			}
2885
-			// End call triggers
2886
-		}
2887
-		if (!$error) {
2888
-			$this->db->commit();
2889
-			return 1;
2890
-		}
2891
-		else
2892
-		{
2893
-			foreach($this->errors as $errmsg)
2894
-			{
2895
-				dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
2896
-				$this->error.=($this->error?', '.$errmsg:$errmsg);
2897
-			}
2898
-			$this->db->rollback();
2899
-			return -1*$error;
2900
-		}
2901
-	}
2704
+    /**
2705
+     *  Update a line in database
2706
+     *
2707
+     *	@param		User	$user			User that modify
2708
+     *	@param		int		$notrigger		1 = disable triggers
2709
+     *  @return		int					< 0 if KO, > 0 if OK
2710
+     */
2711
+    function update($user = null, $notrigger = 0)
2712
+    {
2713
+        global $conf;
2714
+
2715
+        $error=0;
2716
+
2717
+        dol_syslog(get_class($this)."::update id=$this->id, entrepot_id=$this->entrepot_id, product_id=$this->fk_product, qty=$this->qty");
2718
+
2719
+        $this->db->begin();
2720
+
2721
+        // Clean parameters
2722
+        if (empty($this->qty)) $this->qty=0;
2723
+        $qty=price2num($this->qty);
2724
+        $remainingQty = 0;
2725
+        $batch = null;
2726
+        $batch_id = null;
2727
+        $expedition_batch_id = null;
2728
+        if (is_array($this->detail_batch)) 	// array of ExpeditionLineBatch
2729
+        {
2730
+            if (count($this->detail_batch) > 1)
2731
+            {
2732
+                dol_syslog(get_class($this).'::update only possible for one batch', LOG_ERR);
2733
+                $this->errors[]='ErrorBadParameters';
2734
+                $error++;
2735
+            }
2736
+            else
2737
+            {
2738
+                $batch = $this->detail_batch[0]->batch;
2739
+                $batch_id = $this->detail_batch[0]->fk_origin_stock;
2740
+                $expedition_batch_id = $this->detail_batch[0]->id;
2741
+                if ($this->entrepot_id != $this->detail_batch[0]->entrepot_id)
2742
+                {
2743
+                    dol_syslog(get_class($this).'::update only possible for batch of same warehouse', LOG_ERR);
2744
+                    $this->errors[]='ErrorBadParameters';
2745
+                    $error++;
2746
+                }
2747
+                $qty = price2num($this->detail_batch[0]->qty);
2748
+            }
2749
+        }
2750
+        else if (! empty($this->detail_batch))
2751
+        {
2752
+            $batch = $this->detail_batch->batch;
2753
+            $batch_id = $this->detail_batch->fk_origin_stock;
2754
+            $expedition_batch_id = $this->detail_batch->id;
2755
+            if ($this->entrepot_id != $this->detail_batch->entrepot_id)
2756
+            {
2757
+                dol_syslog(get_class($this).'::update only possible for batch of same warehouse', LOG_ERR);
2758
+                $this->errors[]='ErrorBadParameters';
2759
+                $error++;
2760
+            }
2761
+            $qty = price2num($this->detail_batch->qty);
2762
+        }
2763
+
2764
+        // check parameters
2765
+        if (! isset($this->id) || ! isset($this->entrepot_id))
2766
+        {
2767
+            dol_syslog(get_class($this).'::update missing line id and/or warehouse id', LOG_ERR);
2768
+            $this->errors[]='ErrorMandatoryParametersNotProvided';
2769
+            $error++;
2770
+            return -1;
2771
+        }
2772
+
2773
+        // update lot
2774
+
2775
+        if (! empty($batch) && $conf->productbatch->enabled)
2776
+        {
2777
+            dol_syslog(get_class($this)."::update expedition batch id=$expedition_batch_id, batch_id=$batch_id, batch=$batch");
2778
+
2779
+            if (empty($batch_id) || empty($this->fk_product)) {
2780
+                dol_syslog(get_class($this).'::update missing fk_origin_stock (batch_id) and/or fk_product', LOG_ERR);
2781
+                $this->errors[]='ErrorMandatoryParametersNotProvided';
2782
+                $error++;
2783
+            }
2784
+
2785
+            // fetch remaining lot qty
2786
+            require_once DOL_DOCUMENT_ROOT.'/expedition/class/expeditionbatch.class.php';
2787
+            if (! $error && ($lotArray = ExpeditionLineBatch::fetchAll($this->db, $this->id)) < 0)
2788
+            {
2789
+                $this->errors[]=$this->db->lasterror()." - ExpeditionLineBatch::fetchAll";
2790
+                $error++;
2791
+            }
2792
+            else
2793
+            {
2794
+                // caculate new total line qty
2795
+                foreach ($lotArray as $lot)
2796
+                {
2797
+                    if ($expedition_batch_id != $lot->id)
2798
+                    {
2799
+                        $remainingQty += $lot->qty;
2800
+                    }
2801
+                }
2802
+                $qty += $remainingQty;
2803
+
2804
+                //fetch lot details
2805
+
2806
+                // fetch from product_lot
2807
+                require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
2808
+                $lot = new Productlot($this->db);
2809
+                if ($lot->fetch(0,$this->fk_product,$batch) < 0)
2810
+                {
2811
+                    $this->errors[] = $lot->errors;
2812
+                    $error++;
2813
+                }
2814
+                if (! $error && ! empty($expedition_batch_id))
2815
+                {
2816
+                    // delete lot expedition line
2817
+                    $sql = "DELETE FROM ".MAIN_DB_PREFIX."expeditiondet_batch";
2818
+                    $sql.= " WHERE fk_expeditiondet = ".$this->id;
2819
+                    $sql.= " AND rowid = ".$expedition_batch_id;
2820
+
2821
+                    if (!$this->db->query($sql))
2822
+                    {
2823
+                        $this->errors[]=$this->db->lasterror()." - sql=$sql";
2824
+                        $error++;
2825
+                    }
2826
+                }
2827
+                if (! $error && $this->detail_batch->qty > 0)
2828
+                {
2829
+                    // create lot expedition line
2830
+                    if (isset($lot->id))
2831
+                    {
2832
+                        $shipmentLot = new ExpeditionLineBatch($this->db);
2833
+                        $shipmentLot->batch = $lot->batch;
2834
+                        $shipmentLot->eatby = $lot->eatby;
2835
+                        $shipmentLot->sellby = $lot->sellby;
2836
+                        $shipmentLot->entrepot_id = $this->detail_batch->entrepot_id;
2837
+                        $shipmentLot->qty = $this->detail_batch->qty;
2838
+                        $shipmentLot->fk_origin_stock = $batch_id;
2839
+                        if ($shipmentLot->create($this->id) < 0)
2840
+                        {
2841
+                            $this->errors[]=$shipmentLot->errors;
2842
+                            $error++;
2843
+                        }
2844
+                    }
2845
+                }
2846
+            }
2847
+        }
2848
+        if (! $error)
2849
+        {
2850
+            // update line
2851
+            $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
2852
+            $sql.= " fk_entrepot = ".($this->entrepot_id > 0 ? $this->entrepot_id : 'null');
2853
+            $sql.= " , qty = ".$qty;
2854
+            $sql.= " WHERE rowid = ".$this->id;
2855
+
2856
+            if (!$this->db->query($sql))
2857
+            {
2858
+                $this->errors[]=$this->db->lasterror()." - sql=$sql";
2859
+                $error++;
2860
+            }
2861
+        }
2862
+
2863
+        if (! $error)
2864
+        {
2865
+            if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
2866
+            {
2867
+                $result=$this->insertExtraFields();
2868
+                if ($result < 0)
2869
+                {
2870
+                    $this->errors[]=$this->error;
2871
+                    $error++;
2872
+                }
2873
+            }
2874
+        }
2875
+
2876
+        if (! $error && ! $notrigger)
2877
+        {
2878
+            // Call trigger
2879
+            $result=$this->call_trigger('LINESHIPPING_UPDATE',$user);
2880
+            if ($result < 0)
2881
+            {
2882
+                $this->errors[]=$this->error;
2883
+                $error++;
2884
+            }
2885
+            // End call triggers
2886
+        }
2887
+        if (!$error) {
2888
+            $this->db->commit();
2889
+            return 1;
2890
+        }
2891
+        else
2892
+        {
2893
+            foreach($this->errors as $errmsg)
2894
+            {
2895
+                dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
2896
+                $this->error.=($this->error?', '.$errmsg:$errmsg);
2897
+            }
2898
+            $this->db->rollback();
2899
+            return -1*$error;
2900
+        }
2901
+    }
2902 2902
 }
Please login to merge, or discard this patch.
dolibarr/htdocs/expedition/class/expeditionstats.class.php 1 patch
Indentation   +68 added lines, -68 removed lines patch added patch discarded remove patch
@@ -34,16 +34,16 @@  discard block
 block discarded – undo
34 34
  */
35 35
 class ExpeditionStats extends Stats
36 36
 {
37
-	/**
38
-	 * @var string Name of table without prefix where object is stored
39
-	 */
40
-	public $table_element;
37
+    /**
38
+     * @var string Name of table without prefix where object is stored
39
+     */
40
+    public $table_element;
41 41
 
42
-	var $socid;
42
+    var $socid;
43 43
     var $userid;
44 44
 
45 45
     var $from;
46
-	var $field;
46
+    var $field;
47 47
     var $where;
48 48
 
49 49
 
@@ -51,96 +51,96 @@  discard block
 block discarded – undo
51 51
      * Constructor
52 52
      *
53 53
      * @param	DoliDB	$db      	Database handler
54
-	 * @param 	int		$socid	   	Id third party for filter
55
-	 * @param 	string	$mode	   	Option (not used)
56
-	 * @param   int		$userid    	Id user for filter (creation user)
54
+     * @param 	int		$socid	   	Id third party for filter
55
+     * @param 	string	$mode	   	Option (not used)
56
+     * @param   int		$userid    	Id user for filter (creation user)
57 57
      */
58 58
     function __construct($db, $socid, $mode, $userid=0)
59 59
     {
60
-		global $user, $conf;
60
+        global $user, $conf;
61 61
 
62
-		$this->db = $db;
62
+        $this->db = $db;
63 63
 
64
-		$this->socid = ($socid > 0 ? $socid : 0);
64
+        $this->socid = ($socid > 0 ? $socid : 0);
65 65
         $this->userid = $userid;
66
-		$this->cachefilesuffix = $mode;
66
+        $this->cachefilesuffix = $mode;
67 67
 
68 68
         $object=new Expedition($this->db);
69
-		$this->from = MAIN_DB_PREFIX.$object->table_element." as c";
70
-		//$this->from.= ", ".MAIN_DB_PREFIX."societe as s";
71
-		$this->field='weight';	// Warning, unit of weight is NOT USED AND MUST BE
72
-		$this->where.= " c.fk_statut > 0";    // Not draft and not cancelled
73
-
74
-		//$this->where.= " AND c.fk_soc = s.rowid AND c.entity = ".$conf->entity;
75
-		$this->where.= " AND c.entity = ".$conf->entity;
76
-		if (!$user->rights->societe->client->voir && !$this->socid) $this->where .= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
77
-		if ($this->socid)
78
-		{
79
-			$this->where.=" AND c.fk_soc = ".$this->socid;
80
-		}
69
+        $this->from = MAIN_DB_PREFIX.$object->table_element." as c";
70
+        //$this->from.= ", ".MAIN_DB_PREFIX."societe as s";
71
+        $this->field='weight';	// Warning, unit of weight is NOT USED AND MUST BE
72
+        $this->where.= " c.fk_statut > 0";    // Not draft and not cancelled
73
+
74
+        //$this->where.= " AND c.fk_soc = s.rowid AND c.entity = ".$conf->entity;
75
+        $this->where.= " AND c.entity = ".$conf->entity;
76
+        if (!$user->rights->societe->client->voir && !$this->socid) $this->where .= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
77
+        if ($this->socid)
78
+        {
79
+            $this->where.=" AND c.fk_soc = ".$this->socid;
80
+        }
81 81
         if ($this->userid > 0) $this->where.=' AND c.fk_user_author = '.$this->userid;
82 82
     }
83 83
 
84 84
     /**
85 85
      * Return shipment number by month for a year
86 86
      *
87
-	 * @param	int		$year		Year to scan
87
+     * @param	int		$year		Year to scan
88 88
      *	@param	int		$format		0=Label of absiss is a translated text, 1=Label of absiss is month number, 2=Label of absiss is first letter of month
89
-	 * @return	array				Array with number by month
89
+     * @return	array				Array with number by month
90 90
      */
91 91
     function getNbByMonth($year, $format=0)
92 92
     {
93 93
         global $user;
94 94
 
95 95
         $sql = "SELECT date_format(c.date_valid,'%m') as dm, COUNT(*) as nb";
96
-		$sql.= " FROM ".$this->from;
97
-		if (!$user->rights->societe->client->voir && !$this->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
98
-		$sql.= " WHERE c.date_valid BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'";
99
-		$sql.= " AND ".$this->where;
100
-		$sql.= " GROUP BY dm";
96
+        $sql.= " FROM ".$this->from;
97
+        if (!$user->rights->societe->client->voir && !$this->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
98
+        $sql.= " WHERE c.date_valid BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'";
99
+        $sql.= " AND ".$this->where;
100
+        $sql.= " GROUP BY dm";
101 101
         $sql.= $this->db->order('dm','DESC');
102 102
 
103
-		$res=$this->_getNbByMonth($year, $sql, $format);
104
-		return $res;
103
+        $res=$this->_getNbByMonth($year, $sql, $format);
104
+        return $res;
105 105
     }
106 106
 
107
-	/**
108
-	 * Return shipments number per year
109
-	 *
110
-	 * @return	array	Array with number by year
111
-	 *
112
-	 */
113
-	function getNbByYear()
114
-	{
115
-		global $user;
116
-
117
-		$sql = "SELECT date_format(c.date_valid,'%Y') as dm, COUNT(*) as nb, SUM(c.".$this->field.")";
118
-		$sql.= " FROM ".$this->from;
119
-		if (!$user->rights->societe->client->voir && !$this->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
120
-		$sql.= " WHERE ".$this->where;
121
-		$sql.= " GROUP BY dm";
107
+    /**
108
+     * Return shipments number per year
109
+     *
110
+     * @return	array	Array with number by year
111
+     *
112
+     */
113
+    function getNbByYear()
114
+    {
115
+        global $user;
116
+
117
+        $sql = "SELECT date_format(c.date_valid,'%Y') as dm, COUNT(*) as nb, SUM(c.".$this->field.")";
118
+        $sql.= " FROM ".$this->from;
119
+        if (!$user->rights->societe->client->voir && !$this->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
120
+        $sql.= " WHERE ".$this->where;
121
+        $sql.= " GROUP BY dm";
122 122
         $sql.= $this->db->order('dm','DESC');
123 123
 
124
-		return $this->_getNbByYear($sql);
125
-	}
126
-
127
-	/**
128
-	 *	Return nb, total and average
129
-	 *
130
-	 *	@return	array	Array of values
131
-	 */
132
-	function getAllByYear()
133
-	{
134
-		global $user;
135
-
136
-		$sql = "SELECT date_format(c.date_valid,'%Y') as year, COUNT(*) as nb, SUM(c.".$this->field.") as total, AVG(".$this->field.") as avg";
137
-		$sql.= " FROM ".$this->from;
138
-		if (!$user->rights->societe->client->voir && !$this->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
139
-		$sql.= " WHERE ".$this->where;
140
-		$sql.= " GROUP BY year";
124
+        return $this->_getNbByYear($sql);
125
+    }
126
+
127
+    /**
128
+     *	Return nb, total and average
129
+     *
130
+     *	@return	array	Array of values
131
+     */
132
+    function getAllByYear()
133
+    {
134
+        global $user;
135
+
136
+        $sql = "SELECT date_format(c.date_valid,'%Y') as year, COUNT(*) as nb, SUM(c.".$this->field.") as total, AVG(".$this->field.") as avg";
137
+        $sql.= " FROM ".$this->from;
138
+        if (!$user->rights->societe->client->voir && !$this->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
139
+        $sql.= " WHERE ".$this->where;
140
+        $sql.= " GROUP BY year";
141 141
         $sql.= $this->db->order('year','DESC');
142 142
 
143
-		return $this->_getAllByYear($sql);
144
-	}
143
+        return $this->_getAllByYear($sql);
144
+    }
145 145
 }
146 146
 
Please login to merge, or discard this patch.
dolibarr/htdocs/expedition/class/api_shipments.class.php 1 patch
Indentation   +99 added lines, -99 removed lines patch added patch discarded remove patch
@@ -16,9 +16,9 @@  discard block
 block discarded – undo
16 16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
  */
18 18
 
19
- use Luracast\Restler\RestException;
19
+    use Luracast\Restler\RestException;
20 20
 
21
- require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
21
+    require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
22 22
 
23 23
 /**
24 24
  * API class for shipments
@@ -34,8 +34,8 @@  discard block
 block discarded – undo
34 34
      */
35 35
     static $FIELDS = array(
36 36
         'socid',
37
-    	'origin_id',
38
-    	'origin_type',
37
+        'origin_id',
38
+        'origin_type',
39 39
     );
40 40
 
41 41
     /**
@@ -48,8 +48,8 @@  discard block
 block discarded – undo
48 48
      */
49 49
     function __construct()
50 50
     {
51
-		global $db, $conf;
52
-		$this->db = $db;
51
+        global $db, $conf;
52
+        $this->db = $db;
53 53
         $this->shipment = new Expedition($this->db);
54 54
     }
55 55
 
@@ -60,26 +60,26 @@  discard block
 block discarded – undo
60 60
      *
61 61
      * @param       int         $id         ID of shipment
62 62
      * @return 	array|mixed data without useless information
63
-	 *
63
+     *
64 64
      * @throws 	RestException
65 65
      */
66 66
     function get($id)
67 67
     {
68
-		if(! DolibarrApiAccess::$user->rights->expedition->lire) {
69
-			throw new RestException(401);
70
-		}
68
+        if(! DolibarrApiAccess::$user->rights->expedition->lire) {
69
+            throw new RestException(401);
70
+        }
71 71
 
72 72
         $result = $this->shipment->fetch($id);
73 73
         if( ! $result ) {
74 74
             throw new RestException(404, 'Shipment not found');
75 75
         }
76 76
 
77
-		if( ! DolibarrApi::_checkAccessToResource('expedition',$this->shipment->id)) {
78
-			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
79
-		}
77
+        if( ! DolibarrApi::_checkAccessToResource('expedition',$this->shipment->id)) {
78
+            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
79
+        }
80 80
 
81 81
         $this->shipment->fetchObjectLinked();
82
-		return $this->_cleanObjectDatas($this->shipment);
82
+        return $this->_cleanObjectDatas($this->shipment);
83 83
     }
84 84
 
85 85
 
@@ -97,7 +97,7 @@  discard block
 block discarded – undo
97 97
      * @param string           $sqlfilters          Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
98 98
      * @return  array                               Array of shipment objects
99 99
      *
100
-	 * @throws RestException
100
+     * @throws RestException
101 101
      */
102 102
     function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '')
103 103
     {
@@ -134,7 +134,7 @@  discard block
 block discarded – undo
134 134
             {
135 135
                 throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
136 136
             }
137
-	        $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
137
+            $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
138 138
             $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
139 139
         }
140 140
 
@@ -173,7 +173,7 @@  discard block
 block discarded – undo
173 173
         if( ! count($obj_ret)) {
174 174
             throw new RestException(404, 'No shipment found');
175 175
         }
176
-		return $obj_ret;
176
+        return $obj_ret;
177 177
     }
178 178
 
179 179
     /**
@@ -184,9 +184,9 @@  discard block
 block discarded – undo
184 184
      */
185 185
     function post($request_data = null)
186 186
     {
187
-      if(! DolibarrApiAccess::$user->rights->expedition->creer) {
188
-			  throw new RestException(401, "Insuffisant rights");
189
-		  }
187
+        if(! DolibarrApiAccess::$user->rights->expedition->creer) {
188
+                throw new RestException(401, "Insuffisant rights");
189
+            }
190 190
         // Check mandatory fields
191 191
         $result = $this->_validate($request_data);
192 192
 
@@ -194,11 +194,11 @@  discard block
 block discarded – undo
194 194
             $this->shipment->$field = $value;
195 195
         }
196 196
         if (isset($request_data["lines"])) {
197
-          $lines = array();
198
-          foreach ($request_data["lines"] as $line) {
197
+            $lines = array();
198
+            foreach ($request_data["lines"] as $line) {
199 199
             array_push($lines, (object) $line);
200
-          }
201
-          $this->shipment->lines = $lines;
200
+            }
201
+            $this->shipment->lines = $lines;
202 202
         }
203 203
 
204 204
         if ($this->shipment->create(DolibarrApiAccess::$user) < 0) {
@@ -378,30 +378,30 @@  discard block
 block discarded – undo
378 378
      */
379 379
     function deleteLine($id, $lineid)
380 380
     {
381
-    	if(! DolibarrApiAccess::$user->rights->expedition->creer) {
382
-    		throw new RestException(401);
383
-    	}
384
-
385
-    	$result = $this->shipment->fetch($id);
386
-    	if( ! $result ) {
387
-    		throw new RestException(404, 'Shipment not found');
388
-    	}
389
-
390
-    	if( ! DolibarrApi::_checkAccessToResource('expedition',$this->shipment->id)) {
391
-    		throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
392
-    	}
393
-
394
-    	// TODO Check the lineid $lineid is a line of ojbect
395
-
396
-    	$request_data = (object) $request_data;
397
-    	$updateRes = $this->shipment->deleteline(DolibarrApiAccess::$user, $lineid);
398
-    	if ($updateRes > 0) {
399
-    		return $this->get($id);
400
-    	}
401
-    	else
402
-    	{
403
-    		throw new RestException(405, $this->shipment->error);
404
-    	}
381
+        if(! DolibarrApiAccess::$user->rights->expedition->creer) {
382
+            throw new RestException(401);
383
+        }
384
+
385
+        $result = $this->shipment->fetch($id);
386
+        if( ! $result ) {
387
+            throw new RestException(404, 'Shipment not found');
388
+        }
389
+
390
+        if( ! DolibarrApi::_checkAccessToResource('expedition',$this->shipment->id)) {
391
+            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
392
+        }
393
+
394
+        // TODO Check the lineid $lineid is a line of ojbect
395
+
396
+        $request_data = (object) $request_data;
397
+        $updateRes = $this->shipment->deleteline(DolibarrApiAccess::$user, $lineid);
398
+        if ($updateRes > 0) {
399
+            return $this->get($id);
400
+        }
401
+        else
402
+        {
403
+            throw new RestException(405, $this->shipment->error);
404
+        }
405 405
     }
406 406
 
407 407
     /**
@@ -414,18 +414,18 @@  discard block
 block discarded – undo
414 414
      */
415 415
     function put($id, $request_data = null)
416 416
     {
417
-      if (! DolibarrApiAccess::$user->rights->expedition->creer) {
418
-		  	throw new RestException(401);
419
-		  }
417
+        if (! DolibarrApiAccess::$user->rights->expedition->creer) {
418
+                throw new RestException(401);
419
+            }
420 420
 
421 421
         $result = $this->shipment->fetch($id);
422 422
         if (! $result) {
423 423
             throw new RestException(404, 'Shipment not found');
424 424
         }
425 425
 
426
-		if (! DolibarrApi::_checkAccessToResource('expedition',$this->shipment->id)) {
427
-			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
428
-		}
426
+        if (! DolibarrApi::_checkAccessToResource('expedition',$this->shipment->id)) {
427
+            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
428
+        }
429 429
         foreach($request_data as $field => $value) {
430 430
             if ($field == 'id') continue;
431 431
             $this->shipment->$field = $value;
@@ -437,7 +437,7 @@  discard block
 block discarded – undo
437 437
         }
438 438
         else
439 439
         {
440
-        	throw new RestException(500, $this->shipment->error);
440
+            throw new RestException(500, $this->shipment->error);
441 441
         }
442 442
     }
443 443
 
@@ -451,16 +451,16 @@  discard block
 block discarded – undo
451 451
     function delete($id)
452 452
     {
453 453
         if(! DolibarrApiAccess::$user->rights->shipment->supprimer) {
454
-			throw new RestException(401);
455
-		}
454
+            throw new RestException(401);
455
+        }
456 456
         $result = $this->shipment->fetch($id);
457 457
         if( ! $result ) {
458 458
             throw new RestException(404, 'Shipment not found');
459 459
         }
460 460
 
461
-		if( ! DolibarrApi::_checkAccessToResource('expedition',$this->shipment->id)) {
462
-			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
463
-		}
461
+        if( ! DolibarrApi::_checkAccessToResource('expedition',$this->shipment->id)) {
462
+            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
463
+        }
464 464
 
465 465
         if( ! $this->shipment->delete(DolibarrApiAccess::$user)) {
466 466
             throw new RestException(500, 'Error when deleting shipment : '.$this->shipment->error);
@@ -496,32 +496,32 @@  discard block
 block discarded – undo
496 496
     function validate($id, $notrigger=0)
497 497
     {
498 498
         if(! DolibarrApiAccess::$user->rights->expedition->creer) {
499
-			throw new RestException(401);
500
-		}
499
+            throw new RestException(401);
500
+        }
501 501
         $result = $this->shipment->fetch($id);
502 502
         if( ! $result ) {
503 503
             throw new RestException(404, 'Shipment not found');
504 504
         }
505 505
 
506
-		if( ! DolibarrApi::_checkAccessToResource('expedition',$this->shipment->id)) {
507
-			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
508
-		}
506
+        if( ! DolibarrApi::_checkAccessToResource('expedition',$this->shipment->id)) {
507
+            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
508
+        }
509 509
 
510
-		$result = $this->shipment->valid(DolibarrApiAccess::$user, $notrigger);
511
-		if ($result == 0) {
512
-		    throw new RestException(304, 'Error nothing done. May be object is already validated');
513
-		}
514
-		if ($result < 0) {
515
-		    throw new RestException(500, 'Error when validating Shipment: '.$this->shipment->error);
516
-		}
517
-	$result = $this->shipment->fetch($id);
510
+        $result = $this->shipment->valid(DolibarrApiAccess::$user, $notrigger);
511
+        if ($result == 0) {
512
+            throw new RestException(304, 'Error nothing done. May be object is already validated');
513
+        }
514
+        if ($result < 0) {
515
+            throw new RestException(500, 'Error when validating Shipment: '.$this->shipment->error);
516
+        }
517
+    $result = $this->shipment->fetch($id);
518 518
         if( ! $result ) {
519 519
             throw new RestException(404, 'Shipment not found');
520 520
         }
521 521
 
522
-	if( ! DolibarrApi::_checkAccessToResource('expedition',$this->shipment->id)) {
522
+    if( ! DolibarrApi::_checkAccessToResource('expedition',$this->shipment->id)) {
523 523
             throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
524
-       }
524
+        }
525 525
 
526 526
         $this->shipment->fetchObjectLinked();
527 527
         return $this->_cleanObjectDatas($this->shipment);
@@ -565,19 +565,19 @@  discard block
 block discarded – undo
565 565
 */
566 566
 
567 567
 
568
-     /**
569
-     * Create a shipment using an existing order.
570
-     *
571
-     * @param int   $orderid       Id of the order
572
-     *
573
-     * @url     POST /createfromorder/{orderid}
574
-     *
575
-     * @return int
576
-     * @throws 400
577
-     * @throws 401
578
-     * @throws 404
579
-     * @throws 405
580
-     */
568
+        /**
569
+         * Create a shipment using an existing order.
570
+         *
571
+         * @param int   $orderid       Id of the order
572
+         *
573
+         * @url     POST /createfromorder/{orderid}
574
+         *
575
+         * @return int
576
+         * @throws 400
577
+         * @throws 401
578
+         * @throws 404
579
+         * @throws 405
580
+         */
581 581
     /*
582 582
     function createShipmentFromOrder($orderid)
583 583
     {
@@ -631,17 +631,17 @@  discard block
 block discarded – undo
631 631
 
632 632
         if (! empty($object->lines) && is_array($object->lines))
633 633
         {
634
-        	foreach ($object->lines as $line)
635
-        	{
636
-        		unset($line->tva_tx);
637
-        		unset($line->vat_src_code);
638
-        		unset($line->total_ht);
639
-        		unset($line->total_ttc);
640
-        		unset($line->total_tva);
641
-        		unset($line->total_localtax1);
642
-        		unset($line->total_localtax2);
643
-        		unset($line->remise_percent);
644
-        	}
634
+            foreach ($object->lines as $line)
635
+            {
636
+                unset($line->tva_tx);
637
+                unset($line->vat_src_code);
638
+                unset($line->total_ht);
639
+                unset($line->total_ttc);
640
+                unset($line->total_tva);
641
+                unset($line->total_localtax1);
642
+                unset($line->total_localtax2);
643
+                unset($line->remise_percent);
644
+            }
645 645
         }
646 646
 
647 647
         return $object;
Please login to merge, or discard this patch.
dolibarr/htdocs/expedition/card.php 1 patch
Indentation   +1991 added lines, -1991 removed lines patch added patch discarded remove patch
@@ -73,8 +73,8 @@  discard block
 block discarded – undo
73 73
 
74 74
 if ($origin == 'expedition') $result=restrictedArea($user, $origin, $id);
75 75
 else {
76
-	$result=restrictedArea($user, 'expedition');
77
-	if (empty($user->rights->{$origin}->lire) && empty($user->rights->{$origin}->read)) accessforbidden();
76
+    $result=restrictedArea($user, 'expedition');
77
+    if (empty($user->rights->{$origin}->lire) && empty($user->rights->{$origin}->read)) accessforbidden();
78 78
 }
79 79
 
80 80
 $action		= GETPOST('action','alpha');
@@ -118,33 +118,33 @@  discard block
 block discarded – undo
118 118
 if (empty($reshook))
119 119
 {
120 120
     if ($cancel)
121
-	{
122
-		$action = '';
123
-		$object->fetch($id); // show shipment also after canceling modification
124
-	}
121
+    {
122
+        $action = '';
123
+        $object->fetch($id); // show shipment also after canceling modification
124
+    }
125 125
 
126
-	include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php';		// Must be include, not include_once
126
+    include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php';		// Must be include, not include_once
127 127
 
128
-	// Actions to build doc
129
-	$upload_dir = $conf->expedition->dir_output.'/sending';
130
-	$permissioncreate = $user->rights->expedition->creer;
131
-	include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
128
+    // Actions to build doc
129
+    $upload_dir = $conf->expedition->dir_output.'/sending';
130
+    $permissioncreate = $user->rights->expedition->creer;
131
+    include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
132 132
 
133
-	// Reopen
134
-	if ($action == 'reopen' && $user->rights->expedition->creer)
135
-	{
136
-	    $object->fetch($id);
137
-	    $result = $object->reOpen();
138
-	}
133
+    // Reopen
134
+    if ($action == 'reopen' && $user->rights->expedition->creer)
135
+    {
136
+        $object->fetch($id);
137
+        $result = $object->reOpen();
138
+    }
139 139
 
140
-	// Set incoterm
141
-	if ($action == 'set_incoterms' && !empty($conf->incoterm->enabled))
142
-	{
143
-	    $result = $object->setIncoterms(GETPOST('incoterm_id', 'int'), GETPOST('location_incoterms', 'alpha'));
144
-	}
140
+    // Set incoterm
141
+    if ($action == 'set_incoterms' && !empty($conf->incoterm->enabled))
142
+    {
143
+        $result = $object->setIncoterms(GETPOST('incoterm_id', 'int'), GETPOST('location_incoterms', 'alpha'));
144
+    }
145 145
 
146
-	if ($action == 'setref_customer')
147
-	{
146
+    if ($action == 'setref_customer')
147
+    {
148 148
         $result = $object->fetch($id);
149 149
         if ($result < 0) {
150 150
             setEventMessages($object->error, $object->errors, 'errors');
@@ -158,329 +158,329 @@  discard block
 block discarded – undo
158 158
             header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
159 159
             exit;
160 160
         }
161
-	}
161
+    }
162 162
 
163
-	if ($action == 'update_extras')
164
-	{
165
-		$object->oldcopy = dol_clone($object);
163
+    if ($action == 'update_extras')
164
+    {
165
+        $object->oldcopy = dol_clone($object);
166 166
 
167
-		// Fill array 'array_options' with data from update form
168
-	    $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
169
-	    $ret = $extrafields->setOptionalsFromPost($extralabels, $object, GETPOST('attribute','none'));
170
-	    if ($ret < 0) $error++;
167
+        // Fill array 'array_options' with data from update form
168
+        $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
169
+        $ret = $extrafields->setOptionalsFromPost($extralabels, $object, GETPOST('attribute','none'));
170
+        if ($ret < 0) $error++;
171 171
 
172
-	    if (! $error)
173
-	    {
174
-	        // Actions on extra fields
172
+        if (! $error)
173
+        {
174
+            // Actions on extra fields
175 175
             $result = $object->insertExtraFields('SHIPMENT_MODIFY');
176
-			if ($result < 0)
177
-			{
178
-				setEventMessages($object->error, $object->errors, 'errors');
179
-				$error++;
180
-			}
181
-	    }
176
+            if ($result < 0)
177
+            {
178
+                setEventMessages($object->error, $object->errors, 'errors');
179
+                $error++;
180
+            }
181
+        }
182 182
 
183
-	    if ($error)
184
-	        $action = 'edit_extras';
185
-	}
183
+        if ($error)
184
+            $action = 'edit_extras';
185
+    }
186 186
 
187
-	// Create shipment
188
-	if ($action == 'add' && $user->rights->expedition->creer)
189
-	{
190
-	    $error=0;
191
-	    $predef='';
187
+    // Create shipment
188
+    if ($action == 'add' && $user->rights->expedition->creer)
189
+    {
190
+        $error=0;
191
+        $predef='';
192 192
 
193
-	    $db->begin();
193
+        $db->begin();
194 194
 
195
-	    $object->note				= GETPOST('note','alpha');
196
-	    $object->origin				= $origin;
195
+        $object->note				= GETPOST('note','alpha');
196
+        $object->origin				= $origin;
197 197
         $object->origin_id			= $origin_id;
198 198
         $object->fk_project         = GETPOST('projectid','int');
199
-	    $object->weight				= GETPOST('weight','int')==''?"NULL":GETPOST('weight','int');
200
-	    $object->sizeH				= GETPOST('sizeH','int')==''?"NULL":GETPOST('sizeH','int');
201
-	    $object->sizeW				= GETPOST('sizeW','int')==''?"NULL":GETPOST('sizeW','int');
202
-	    $object->sizeS				= GETPOST('sizeS','int')==''?"NULL":GETPOST('sizeS','int');
203
-	    $object->size_units			= GETPOST('size_units','int');
204
-	    $object->weight_units		= GETPOST('weight_units','int');
205
-
206
-	    $date_delivery = dol_mktime(GETPOST('date_deliveryhour','int'), GETPOST('date_deliverymin','int'), 0, GETPOST('date_deliverymonth','int'), GETPOST('date_deliveryday','int'), GETPOST('date_deliveryyear','int'));
207
-
208
-	    // On va boucler sur chaque ligne du document d'origine pour completer objet expedition
209
-	    // avec info diverses + qte a livrer
210
-	    $classname = ucfirst($object->origin);
211
-	    $objectsrc = new $classname($db);
212
-	    $objectsrc->fetch($object->origin_id);
213
-
214
-	    $object->socid					= $objectsrc->socid;
215
-	    $object->ref_customer			= GETPOST('ref_customer','alpha');
216
-	    $object->model_pdf				= GETPOST('model');
217
-	    $object->date_delivery			= $date_delivery;	    // Date delivery planed
218
-	    $object->fk_delivery_address	= $objectsrc->fk_delivery_address;
219
-	    $object->shipping_method_id		= GETPOST('shipping_method_id','int');
220
-	    $object->tracking_number		= GETPOST('tracking_number','alpha');
221
-	    $object->ref_int				= GETPOST('ref_int','alpha');
222
-	    $object->note_private			= GETPOST('note_private','none');
223
-	    $object->note_public			= GETPOST('note_public','none');
224
-		$object->fk_incoterms 			= GETPOST('incoterm_id', 'int');
225
-		$object->location_incoterms 	= GETPOST('location_incoterms', 'alpha');
226
-
227
-	    $batch_line = array();
228
-		$stockLine = array();
229
-		$array_options=array();
230
-
231
-	    $num=count($objectsrc->lines);
232
-	    $totalqty=0;
233
-
234
-	    for ($i = 0; $i < $num; $i++)
235
-	    {
236
-			$idl="idl".$i;
237
-
238
-			$sub_qty=array();
239
-			$subtotalqty=0;
240
-
241
-			$j=0;
242
-			$batch="batchl".$i."_0";
243
-			$stockLocation="ent1".$i."_0";
244
-	    	$qty = "qtyl".$i;
245
-
246
-			if ($objectsrc->lines[$i]->product_tobatch)      // If product need a batch number
247
-			{
248
-			    if (isset($_POST[$batch]))
249
-			    {
250
-    				//shipment line with batch-enable product
251
-    				$qty .= '_'.$j;
252
-    				while (isset($_POST[$batch]))
253
-    				{
254
-    					// save line of detail into sub_qty
255
-    				    $sub_qty[$j]['q']=GETPOST($qty,'int');				// the qty we want to move for this stock record
256
-    				    $sub_qty[$j]['id_batch']=GETPOST($batch,'int');		// the id into llx_product_batch of stock record to move
257
-    					$subtotalqty+=$sub_qty[$j]['q'];
258
-
259
-    					//var_dump($qty);var_dump($batch);var_dump($sub_qty[$j]['q']);var_dump($sub_qty[$j]['id_batch']);
260
-
261
-    					$j++;
262
-    					$batch="batchl".$i."_".$j;
263
-    					$qty = "qtyl".$i.'_'.$j;
264
-    				}
265
-
266
-    				$batch_line[$i]['detail']=$sub_qty;		// array of details
267
-    				$batch_line[$i]['qty']=$subtotalqty;
268
-    				$batch_line[$i]['ix_l']=GETPOST($idl,'int');
269
-
270
-    				$totalqty+=$subtotalqty;
271
-			    }
272
-			    else
273
-			    {
274
-			        // No detail were provided for lots
275
-			        if (! empty($_POST[$qty]))
276
-			        {
277
-			            // We try to set an amount
278
-    			        // Case we dont use the list of available qty for each warehouse/lot
279
-    			        // GUI does not allow this yet
280
-    			        setEventMessages($langs->trans("StockIsRequiredToChooseWhichLotToUse"), null, 'errors');
281
-			        }
282
-			    }
283
-			}
284
-			else if (isset($_POST[$stockLocation]))
285
-			{
286
-			    //shipment line from multiple stock locations
287
-			    $qty .= '_'.$j;
288
-			    while (isset($_POST[$stockLocation]))
289
-			    {
290
-			        // save sub line of warehouse
291
-			        $stockLine[$i][$j]['qty']=GETPOST($qty,'int');
292
-			        $stockLine[$i][$j]['warehouse_id']=GETPOST($stockLocation,'int');
293
-			        $stockLine[$i][$j]['ix_l']=GETPOST($idl,'int');
294
-
295
-			        $totalqty+=GETPOST($qty,'int');
296
-
297
-			        $j++;
298
-			        $stockLocation="ent1".$i."_".$j;
299
-			        $qty = "qtyl".$i.'_'.$j;
300
-			    }
301
-			}
302
-			else
303
-			{
304
-			    //var_dump(GETPOST($qty,'int')); var_dump($_POST); var_dump($batch);exit;
305
-				//shipment line for product with no batch management and no multiple stock location
306
-				if (GETPOST($qty,'int') > 0) $totalqty+=GETPOST($qty,'int');
307
-			}
308
-
309
-			// Extrafields
310
-			$extralabelsline = $extrafieldsline->fetch_name_optionals_label($object->table_element_line);
199
+        $object->weight				= GETPOST('weight','int')==''?"NULL":GETPOST('weight','int');
200
+        $object->sizeH				= GETPOST('sizeH','int')==''?"NULL":GETPOST('sizeH','int');
201
+        $object->sizeW				= GETPOST('sizeW','int')==''?"NULL":GETPOST('sizeW','int');
202
+        $object->sizeS				= GETPOST('sizeS','int')==''?"NULL":GETPOST('sizeS','int');
203
+        $object->size_units			= GETPOST('size_units','int');
204
+        $object->weight_units		= GETPOST('weight_units','int');
205
+
206
+        $date_delivery = dol_mktime(GETPOST('date_deliveryhour','int'), GETPOST('date_deliverymin','int'), 0, GETPOST('date_deliverymonth','int'), GETPOST('date_deliveryday','int'), GETPOST('date_deliveryyear','int'));
207
+
208
+        // On va boucler sur chaque ligne du document d'origine pour completer objet expedition
209
+        // avec info diverses + qte a livrer
210
+        $classname = ucfirst($object->origin);
211
+        $objectsrc = new $classname($db);
212
+        $objectsrc->fetch($object->origin_id);
213
+
214
+        $object->socid					= $objectsrc->socid;
215
+        $object->ref_customer			= GETPOST('ref_customer','alpha');
216
+        $object->model_pdf				= GETPOST('model');
217
+        $object->date_delivery			= $date_delivery;	    // Date delivery planed
218
+        $object->fk_delivery_address	= $objectsrc->fk_delivery_address;
219
+        $object->shipping_method_id		= GETPOST('shipping_method_id','int');
220
+        $object->tracking_number		= GETPOST('tracking_number','alpha');
221
+        $object->ref_int				= GETPOST('ref_int','alpha');
222
+        $object->note_private			= GETPOST('note_private','none');
223
+        $object->note_public			= GETPOST('note_public','none');
224
+        $object->fk_incoterms 			= GETPOST('incoterm_id', 'int');
225
+        $object->location_incoterms 	= GETPOST('location_incoterms', 'alpha');
226
+
227
+        $batch_line = array();
228
+        $stockLine = array();
229
+        $array_options=array();
230
+
231
+        $num=count($objectsrc->lines);
232
+        $totalqty=0;
233
+
234
+        for ($i = 0; $i < $num; $i++)
235
+        {
236
+            $idl="idl".$i;
237
+
238
+            $sub_qty=array();
239
+            $subtotalqty=0;
240
+
241
+            $j=0;
242
+            $batch="batchl".$i."_0";
243
+            $stockLocation="ent1".$i."_0";
244
+            $qty = "qtyl".$i;
245
+
246
+            if ($objectsrc->lines[$i]->product_tobatch)      // If product need a batch number
247
+            {
248
+                if (isset($_POST[$batch]))
249
+                {
250
+                    //shipment line with batch-enable product
251
+                    $qty .= '_'.$j;
252
+                    while (isset($_POST[$batch]))
253
+                    {
254
+                        // save line of detail into sub_qty
255
+                        $sub_qty[$j]['q']=GETPOST($qty,'int');				// the qty we want to move for this stock record
256
+                        $sub_qty[$j]['id_batch']=GETPOST($batch,'int');		// the id into llx_product_batch of stock record to move
257
+                        $subtotalqty+=$sub_qty[$j]['q'];
258
+
259
+                        //var_dump($qty);var_dump($batch);var_dump($sub_qty[$j]['q']);var_dump($sub_qty[$j]['id_batch']);
260
+
261
+                        $j++;
262
+                        $batch="batchl".$i."_".$j;
263
+                        $qty = "qtyl".$i.'_'.$j;
264
+                    }
265
+
266
+                    $batch_line[$i]['detail']=$sub_qty;		// array of details
267
+                    $batch_line[$i]['qty']=$subtotalqty;
268
+                    $batch_line[$i]['ix_l']=GETPOST($idl,'int');
269
+
270
+                    $totalqty+=$subtotalqty;
271
+                }
272
+                else
273
+                {
274
+                    // No detail were provided for lots
275
+                    if (! empty($_POST[$qty]))
276
+                    {
277
+                        // We try to set an amount
278
+                        // Case we dont use the list of available qty for each warehouse/lot
279
+                        // GUI does not allow this yet
280
+                        setEventMessages($langs->trans("StockIsRequiredToChooseWhichLotToUse"), null, 'errors');
281
+                    }
282
+                }
283
+            }
284
+            else if (isset($_POST[$stockLocation]))
285
+            {
286
+                //shipment line from multiple stock locations
287
+                $qty .= '_'.$j;
288
+                while (isset($_POST[$stockLocation]))
289
+                {
290
+                    // save sub line of warehouse
291
+                    $stockLine[$i][$j]['qty']=GETPOST($qty,'int');
292
+                    $stockLine[$i][$j]['warehouse_id']=GETPOST($stockLocation,'int');
293
+                    $stockLine[$i][$j]['ix_l']=GETPOST($idl,'int');
294
+
295
+                    $totalqty+=GETPOST($qty,'int');
296
+
297
+                    $j++;
298
+                    $stockLocation="ent1".$i."_".$j;
299
+                    $qty = "qtyl".$i.'_'.$j;
300
+                }
301
+            }
302
+            else
303
+            {
304
+                //var_dump(GETPOST($qty,'int')); var_dump($_POST); var_dump($batch);exit;
305
+                //shipment line for product with no batch management and no multiple stock location
306
+                if (GETPOST($qty,'int') > 0) $totalqty+=GETPOST($qty,'int');
307
+            }
308
+
309
+            // Extrafields
310
+            $extralabelsline = $extrafieldsline->fetch_name_optionals_label($object->table_element_line);
311 311
             $array_options[$i] = $extrafieldsline->getOptionalsFromPost($extralabelsline, $i);
312
-			// Unset extrafield
313
-			if (is_array($extralabelsline)) {
314
-				// Get extra fields
315
-				foreach ($extralabelsline as $key => $value) {
316
-					unset($_POST["options_" . $key]);
317
-				}
318
-			}
319
-	    }
312
+            // Unset extrafield
313
+            if (is_array($extralabelsline)) {
314
+                // Get extra fields
315
+                foreach ($extralabelsline as $key => $value) {
316
+                    unset($_POST["options_" . $key]);
317
+                }
318
+            }
319
+        }
320 320
 
321
-	    //var_dump($batch_line[2]);
321
+        //var_dump($batch_line[2]);
322 322
 
323
-	    if ($totalqty > 0)		// There is at least one thing to ship
324
-	    {
325
-	        //var_dump($_POST);exit;
326
-	        for ($i = 0; $i < $num; $i++)
327
-	        {
328
-	            $qty = "qtyl".$i;
329
-				if (! isset($batch_line[$i]))
330
-				{
331
-					// not batch mode
332
-					if (isset($stockLine[$i]))
333
-					{
334
-    					//shipment from multiple stock locations
335
-					    $nbstockline = count($stockLine[$i]);
336
-    					for($j = 0; $j < $nbstockline; $j++)
337
-    					{
338
-    					    if ($stockLine[$i][$j]['qty']>0)
339
-    					    {
340
-    					        $ret=$object->addline($stockLine[$i][$j]['warehouse_id'], $stockLine[$i][$j]['ix_l'], $stockLine[$i][$j]['qty'], $array_options[$i]);
341
-    					        if ($ret < 0)
342
-    					        {
343
-    					            setEventMessages($object->error, $object->errors, 'errors');
344
-    					            $error++;
345
-    					        }
346
-    					    }
347
-    					}
348
-					}
349
-					else
350
-					{
351
-						if (GETPOST($qty,'int') > 0 || (GETPOST($qty,'int') == 0 && $conf->global->SHIPMENT_GETS_ALL_ORDER_PRODUCTS))
352
-						{
353
-							$ent = "entl".$i;
354
-							$idl = "idl".$i;
355
-							$entrepot_id = is_numeric(GETPOST($ent,'int'))?GETPOST($ent,'int'):GETPOST('entrepot_id','int');
356
-							if ($entrepot_id < 0) $entrepot_id='';
357
-							if (! ($objectsrc->lines[$i]->fk_product > 0)) $entrepot_id = 0;
358
-
359
-							$ret=$object->addline($entrepot_id, GETPOST($idl,'int'), GETPOST($qty,'int'), $array_options[$i]);
360
-							if ($ret < 0)
361
-							{
362
-								setEventMessages($object->error, $object->errors, 'errors');
363
-								$error++;
364
-							}
365
-						}
366
-					}
367
-				}
368
-				else
369
-				{
370
-					// batch mode
371
-					if ($batch_line[$i]['qty']>0)
372
-					{
373
-						$ret=$object->addline_batch($batch_line[$i],$array_options[$i]);
374
-						if ($ret < 0)
375
-						{
376
-							setEventMessages($object->error, $object->errors, 'errors');
377
-							$error++;
378
-						}
379
-					}
380
-				}
381
-	        }
382
-	        // Fill array 'array_options' with data from add form
383
-	        $ret = $extrafields->setOptionalsFromPost($extralabels, $object);
384
-	        if ($ret < 0) $error++;
385
-
386
-	        if (! $error)
387
-	        {
388
-	            $ret=$object->create($user);		// This create shipment (like Odoo picking) and line of shipments. Stock movement will when validating shipment.
389
-	            if ($ret <= 0)
390
-	            {
391
-	                setEventMessages($object->error, $object->errors, 'errors');
392
-	                $error++;
393
-	            }
394
-	        }
395
-	    }
396
-	    else
397
-	    {
398
-	        setEventMessages($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("QtyToShip").'/'.$langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
399
-	        $error++;
400
-	    }
323
+        if ($totalqty > 0)		// There is at least one thing to ship
324
+        {
325
+            //var_dump($_POST);exit;
326
+            for ($i = 0; $i < $num; $i++)
327
+            {
328
+                $qty = "qtyl".$i;
329
+                if (! isset($batch_line[$i]))
330
+                {
331
+                    // not batch mode
332
+                    if (isset($stockLine[$i]))
333
+                    {
334
+                        //shipment from multiple stock locations
335
+                        $nbstockline = count($stockLine[$i]);
336
+                        for($j = 0; $j < $nbstockline; $j++)
337
+                        {
338
+                            if ($stockLine[$i][$j]['qty']>0)
339
+                            {
340
+                                $ret=$object->addline($stockLine[$i][$j]['warehouse_id'], $stockLine[$i][$j]['ix_l'], $stockLine[$i][$j]['qty'], $array_options[$i]);
341
+                                if ($ret < 0)
342
+                                {
343
+                                    setEventMessages($object->error, $object->errors, 'errors');
344
+                                    $error++;
345
+                                }
346
+                            }
347
+                        }
348
+                    }
349
+                    else
350
+                    {
351
+                        if (GETPOST($qty,'int') > 0 || (GETPOST($qty,'int') == 0 && $conf->global->SHIPMENT_GETS_ALL_ORDER_PRODUCTS))
352
+                        {
353
+                            $ent = "entl".$i;
354
+                            $idl = "idl".$i;
355
+                            $entrepot_id = is_numeric(GETPOST($ent,'int'))?GETPOST($ent,'int'):GETPOST('entrepot_id','int');
356
+                            if ($entrepot_id < 0) $entrepot_id='';
357
+                            if (! ($objectsrc->lines[$i]->fk_product > 0)) $entrepot_id = 0;
358
+
359
+                            $ret=$object->addline($entrepot_id, GETPOST($idl,'int'), GETPOST($qty,'int'), $array_options[$i]);
360
+                            if ($ret < 0)
361
+                            {
362
+                                setEventMessages($object->error, $object->errors, 'errors');
363
+                                $error++;
364
+                            }
365
+                        }
366
+                    }
367
+                }
368
+                else
369
+                {
370
+                    // batch mode
371
+                    if ($batch_line[$i]['qty']>0)
372
+                    {
373
+                        $ret=$object->addline_batch($batch_line[$i],$array_options[$i]);
374
+                        if ($ret < 0)
375
+                        {
376
+                            setEventMessages($object->error, $object->errors, 'errors');
377
+                            $error++;
378
+                        }
379
+                    }
380
+                }
381
+            }
382
+            // Fill array 'array_options' with data from add form
383
+            $ret = $extrafields->setOptionalsFromPost($extralabels, $object);
384
+            if ($ret < 0) $error++;
401 385
 
402
-	    if (! $error)
403
-	    {
404
-	        $db->commit();
405
-	        header("Location: card.php?id=".$object->id);
406
-	        exit;
407
-	    }
408
-	    else
409
-	    {
410
-	        $db->rollback();
411
-	        $_GET["commande_id"]=GETPOST('commande_id','int');
412
-	        $action='create';
413
-	    }
414
-	}
386
+            if (! $error)
387
+            {
388
+                $ret=$object->create($user);		// This create shipment (like Odoo picking) and line of shipments. Stock movement will when validating shipment.
389
+                if ($ret <= 0)
390
+                {
391
+                    setEventMessages($object->error, $object->errors, 'errors');
392
+                    $error++;
393
+                }
394
+            }
395
+        }
396
+        else
397
+        {
398
+            setEventMessages($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("QtyToShip").'/'.$langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
399
+            $error++;
400
+        }
401
+
402
+        if (! $error)
403
+        {
404
+            $db->commit();
405
+            header("Location: card.php?id=".$object->id);
406
+            exit;
407
+        }
408
+        else
409
+        {
410
+            $db->rollback();
411
+            $_GET["commande_id"]=GETPOST('commande_id','int');
412
+            $action='create';
413
+        }
414
+    }
415 415
 
416
-	/*
416
+    /*
417 417
 	 * Build a receiving receipt
418 418
 	 */
419
-	else if ($action == 'create_delivery' && $conf->livraison_bon->enabled && $user->rights->expedition->livraison->creer)
420
-	{
421
-	    $result = $object->create_delivery($user);
422
-	    if ($result > 0)
423
-	    {
424
-	        header("Location: ".DOL_URL_ROOT.'/livraison/card.php?action=create_delivery&id='.$result);
425
-	        exit;
426
-	    }
427
-	    else
428
-	    {
429
-	        setEventMessages($object->error, $object->errors, 'errors');
430
-	    }
431
-	}
419
+    else if ($action == 'create_delivery' && $conf->livraison_bon->enabled && $user->rights->expedition->livraison->creer)
420
+    {
421
+        $result = $object->create_delivery($user);
422
+        if ($result > 0)
423
+        {
424
+            header("Location: ".DOL_URL_ROOT.'/livraison/card.php?action=create_delivery&id='.$result);
425
+            exit;
426
+        }
427
+        else
428
+        {
429
+            setEventMessages($object->error, $object->errors, 'errors');
430
+        }
431
+    }
432 432
 
433
-	else if ($action == 'confirm_valid' && $confirm == 'yes' &&
433
+    else if ($action == 'confirm_valid' && $confirm == 'yes' &&
434 434
         ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->creer))
435
-       	|| (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->shipping_advance->validate)))
436
-	)
437
-	{
438
-	    $object->fetch_thirdparty();
435
+           || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->shipping_advance->validate)))
436
+    )
437
+    {
438
+        $object->fetch_thirdparty();
439 439
 
440
-	    $result = $object->valid($user);
440
+        $result = $object->valid($user);
441 441
 
442
-	    if ($result < 0)
443
-	    {
444
-			$langs->load("errors");
445
-	        setEventMessages($langs->trans($object->error), null, 'errors');
446
-	    }
447
-	    else
448
-	    {
449
-	    	// Define output language
450
-	    	if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
451
-	    	{
452
-	    		$outputlangs = $langs;
453
-	    		$newlang = '';
454
-	    		if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
455
-	    		if ($conf->global->MAIN_MULTILANGS && empty($newlang))	$newlang = $object->thirdparty->default_lang;
456
-	    		if (! empty($newlang)) {
457
-	    			$outputlangs = new Translate("", $conf);
458
-	    			$outputlangs->setDefaultLang($newlang);
459
-	    		}
460
-	    		$model=$object->modelpdf;
461
-	    		$ret = $object->fetch($id); // Reload to get new records
462
-
463
-	    		$result=$object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
464
-	    		if ($result < 0) dol_print_error($db,$result);
465
-	    	}
466
-	    }
467
-	}
442
+        if ($result < 0)
443
+        {
444
+            $langs->load("errors");
445
+            setEventMessages($langs->trans($object->error), null, 'errors');
446
+        }
447
+        else
448
+        {
449
+            // Define output language
450
+            if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
451
+            {
452
+                $outputlangs = $langs;
453
+                $newlang = '';
454
+                if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
455
+                if ($conf->global->MAIN_MULTILANGS && empty($newlang))	$newlang = $object->thirdparty->default_lang;
456
+                if (! empty($newlang)) {
457
+                    $outputlangs = new Translate("", $conf);
458
+                    $outputlangs->setDefaultLang($newlang);
459
+                }
460
+                $model=$object->modelpdf;
461
+                $ret = $object->fetch($id); // Reload to get new records
468 462
 
469
-	else if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->expedition->supprimer)
470
-	{
471
-	    $result = $object->delete();
472
-	    if ($result > 0)
473
-	    {
474
-	        header("Location: ".DOL_URL_ROOT.'/expedition/index.php');
475
-	        exit;
476
-	    }
477
-	    else
478
-		{
479
-			setEventMessages($object->error, $object->errors, 'errors');
480
-	    }
481
-	}
482
-	// TODO add alternative status
483
-	/*else if ($action == 'reopen' && (! empty($user->rights->expedition->creer) || ! empty($user->rights->expedition->shipping_advance->validate)))
463
+                $result=$object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
464
+                if ($result < 0) dol_print_error($db,$result);
465
+            }
466
+        }
467
+    }
468
+
469
+    else if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->expedition->supprimer)
470
+    {
471
+        $result = $object->delete();
472
+        if ($result > 0)
473
+        {
474
+            header("Location: ".DOL_URL_ROOT.'/expedition/index.php');
475
+            exit;
476
+        }
477
+        else
478
+        {
479
+            setEventMessages($object->error, $object->errors, 'errors');
480
+        }
481
+    }
482
+    // TODO add alternative status
483
+    /*else if ($action == 'reopen' && (! empty($user->rights->expedition->creer) || ! empty($user->rights->expedition->shipping_advance->validate)))
484 484
 	{
485 485
 	    $result = $object->setStatut(0);
486 486
 	    if ($result < 0)
@@ -489,375 +489,375 @@  discard block
 block discarded – undo
489 489
 	    }
490 490
 	}*/
491 491
 
492
-	else if ($action == 'setdate_livraison' && $user->rights->expedition->creer)
493
-	{
494
-	    //print "x ".$_POST['liv_month'].", ".$_POST['liv_day'].", ".$_POST['liv_year'];
495
-	    $datedelivery=dol_mktime(GETPOST('liv_hour','int'), GETPOST('liv_min','int'), 0, GETPOST('liv_month','int'), GETPOST('liv_day','int'), GETPOST('liv_year','int'));
492
+    else if ($action == 'setdate_livraison' && $user->rights->expedition->creer)
493
+    {
494
+        //print "x ".$_POST['liv_month'].", ".$_POST['liv_day'].", ".$_POST['liv_year'];
495
+        $datedelivery=dol_mktime(GETPOST('liv_hour','int'), GETPOST('liv_min','int'), 0, GETPOST('liv_month','int'), GETPOST('liv_day','int'), GETPOST('liv_year','int'));
496 496
 
497
-	    $object->fetch($id);
498
-	    $result=$object->set_date_livraison($user,$datedelivery);
499
-	    if ($result < 0)
500
-	    {
501
-	        setEventMessages($object->error, $object->errors, 'errors');
502
-	    }
503
-	}
504
-
505
-	// Action update
506
-	else if (
507
-		($action == 'settracking_number'
508
-		|| $action == 'settracking_url'
509
-		|| $action == 'settrueWeight'
510
-		|| $action == 'settrueWidth'
511
-		|| $action == 'settrueHeight'
512
-		|| $action == 'settrueDepth'
513
-		|| $action == 'setshipping_method_id')
514
-		&& $user->rights->expedition->creer
515
-		)
516
-	{
517
-	    $error=0;
497
+        $object->fetch($id);
498
+        $result=$object->set_date_livraison($user,$datedelivery);
499
+        if ($result < 0)
500
+        {
501
+            setEventMessages($object->error, $object->errors, 'errors');
502
+        }
503
+    }
518 504
 
519
-	    if ($action == 'settracking_number')		$object->tracking_number = trim(GETPOST('tracking_number','alpha'));
520
-	    if ($action == 'settracking_url')		$object->tracking_url = trim(GETPOST('tracking_url','int'));
521
-	    if ($action == 'settrueWeight')	{
522
-	    	$object->trueWeight = trim(GETPOST('trueWeight','int'));
523
-			$object->weight_units = GETPOST('weight_units','int');
524
-	    }
525
-	    if ($action == 'settrueWidth')			$object->trueWidth = trim(GETPOST('trueWidth','int'));
526
-	    if ($action == 'settrueHeight'){
527
-	    				$object->trueHeight = trim(GETPOST('trueHeight','int'));
528
-						$object->size_units = GETPOST('size_units','int');
529
-		}
530
-	    if ($action == 'settrueDepth')			$object->trueDepth = trim(GETPOST('trueDepth','int'));
531
-	    if ($action == 'setshipping_method_id')	$object->shipping_method_id = trim(GETPOST('shipping_method_id','int'));
532
-
533
-	    if (! $error)
534
-	    {
535
-	        if ($object->update($user) >= 0)
536
-	        {
537
-	            header("Location: card.php?id=".$object->id);
538
-	            exit;
539
-	        }
540
-	        setEventMessages($object->error, $object->errors, 'errors');
541
-	    }
505
+    // Action update
506
+    else if (
507
+        ($action == 'settracking_number'
508
+        || $action == 'settracking_url'
509
+        || $action == 'settrueWeight'
510
+        || $action == 'settrueWidth'
511
+        || $action == 'settrueHeight'
512
+        || $action == 'settrueDepth'
513
+        || $action == 'setshipping_method_id')
514
+        && $user->rights->expedition->creer
515
+        )
516
+    {
517
+        $error=0;
542 518
 
543
-	    $action="";
544
-	}
519
+        if ($action == 'settracking_number')		$object->tracking_number = trim(GETPOST('tracking_number','alpha'));
520
+        if ($action == 'settracking_url')		$object->tracking_url = trim(GETPOST('tracking_url','int'));
521
+        if ($action == 'settrueWeight')	{
522
+            $object->trueWeight = trim(GETPOST('trueWeight','int'));
523
+            $object->weight_units = GETPOST('weight_units','int');
524
+        }
525
+        if ($action == 'settrueWidth')			$object->trueWidth = trim(GETPOST('trueWidth','int'));
526
+        if ($action == 'settrueHeight'){
527
+                        $object->trueHeight = trim(GETPOST('trueHeight','int'));
528
+                        $object->size_units = GETPOST('size_units','int');
529
+        }
530
+        if ($action == 'settrueDepth')			$object->trueDepth = trim(GETPOST('trueDepth','int'));
531
+        if ($action == 'setshipping_method_id')	$object->shipping_method_id = trim(GETPOST('shipping_method_id','int'));
545 532
 
546
-	elseif ($action == 'classifybilled')
547
-	{
548
-	    $object->fetch($id);
549
-	    $result = $object->set_billed();
550
-	    if($result >= 0) {
551
-	    	header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
552
-	    	exit();
553
-	    }
554
-	}
533
+        if (! $error)
534
+        {
535
+            if ($object->update($user) >= 0)
536
+            {
537
+                header("Location: card.php?id=".$object->id);
538
+                exit;
539
+            }
540
+            setEventMessages($object->error, $object->errors, 'errors');
541
+        }
555 542
 
556
-	elseif ($action == 'classifyclosed')
557
-	{
558
-	    $object->fetch($id);
559
-	    $result = $object->setClosed();
560
-	    if($result >= 0) {
561
-	    	header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
562
-	    	exit();
563
-	    }
564
-	}
543
+        $action="";
544
+    }
545
+
546
+    elseif ($action == 'classifybilled')
547
+    {
548
+        $object->fetch($id);
549
+        $result = $object->set_billed();
550
+        if($result >= 0) {
551
+            header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
552
+            exit();
553
+        }
554
+    }
555
+
556
+    elseif ($action == 'classifyclosed')
557
+    {
558
+        $object->fetch($id);
559
+        $result = $object->setClosed();
560
+        if($result >= 0) {
561
+            header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
562
+            exit();
563
+        }
564
+    }
565 565
 
566
-	/*
566
+    /*
567 567
 	 *  delete a line
568 568
 	 */
569
-	elseif ($action == 'deleteline' && ! empty($line_id))
570
-	{
571
-		$object->fetch($id);
572
-		$lines = $object->lines;
573
-		$line = new ExpeditionLigne($db);
574
-
575
-		$num_prod = count($lines);
576
-		for ($i = 0 ; $i < $num_prod ; $i++)
577
-		{
578
-			if ($lines[$i]->id == $line_id)
579
-			{
580
-				if (count($lines[$i]->details_entrepot) > 1)
581
-				{
582
-					// delete multi warehouse lines
583
-					foreach ($lines[$i]->details_entrepot as $details_entrepot) {
584
-						$line->id = $details_entrepot->line_id;
585
-						if (! $error && $line->delete($user) < 0)
586
-						{
587
-							$error++;
588
-						}
589
-					}
590
-				}
591
-				else
592
-				{
593
-					// delete single warehouse line
594
-					$line->id = $line_id;
595
-					if (! $error && $line->delete($user) < 0)
596
-					{
597
-						$error++;
598
-					}
599
-				}
600
-			}
601
-			unset($_POST["lineid"]);
602
-		}
603
-
604
-		if(! $error) {
605
-			header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
606
-			exit();
607
-		}
608
-		else
609
-		{
610
-			setEventMessages($line->error, $line->errors, 'errors');
611
-		}
612
-	}
613
-
614
-	/*
569
+    elseif ($action == 'deleteline' && ! empty($line_id))
570
+    {
571
+        $object->fetch($id);
572
+        $lines = $object->lines;
573
+        $line = new ExpeditionLigne($db);
574
+
575
+        $num_prod = count($lines);
576
+        for ($i = 0 ; $i < $num_prod ; $i++)
577
+        {
578
+            if ($lines[$i]->id == $line_id)
579
+            {
580
+                if (count($lines[$i]->details_entrepot) > 1)
581
+                {
582
+                    // delete multi warehouse lines
583
+                    foreach ($lines[$i]->details_entrepot as $details_entrepot) {
584
+                        $line->id = $details_entrepot->line_id;
585
+                        if (! $error && $line->delete($user) < 0)
586
+                        {
587
+                            $error++;
588
+                        }
589
+                    }
590
+                }
591
+                else
592
+                {
593
+                    // delete single warehouse line
594
+                    $line->id = $line_id;
595
+                    if (! $error && $line->delete($user) < 0)
596
+                    {
597
+                        $error++;
598
+                    }
599
+                }
600
+            }
601
+            unset($_POST["lineid"]);
602
+        }
603
+
604
+        if(! $error) {
605
+            header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
606
+            exit();
607
+        }
608
+        else
609
+        {
610
+            setEventMessages($line->error, $line->errors, 'errors');
611
+        }
612
+    }
613
+
614
+    /*
615 615
 	 *  Update a line
616 616
 	 */
617
-	else if ($action == 'updateline' && $user->rights->expedition->creer && GETPOST('save'))
618
-	{
619
-		// Clean parameters
620
-		$qty=0;
621
-		$entrepot_id = 0;
622
-		$batch_id = 0;
623
-
624
-		$lines = $object->lines;
625
-		$num_prod = count($lines);
626
-		for ($i = 0 ; $i < $num_prod ; $i++)
627
-		{
628
-			if ($lines[$i]->id == $line_id)		// we have found line to update
629
-			{
630
-				$line = new ExpeditionLigne($db);
631
-				// Extrafields Lines
632
-				$extrafieldsline = new ExtraFields($db);
633
-				$extralabelsline = $extrafieldsline->fetch_name_optionals_label($object->table_element_line);
634
-				$line->array_options = $extrafieldsline->getOptionalsFromPost($extralabelsline);
635
-				// Unset extrafield POST Data
636
-				if (is_array($extralabelsline)) {
637
-					foreach ($extralabelsline as $key => $value) {
638
-						unset($_POST["options_" . $key]);
639
-					}
640
-				}
641
-				$line->fk_product = $lines[$i]->fk_product;
642
-				if (is_array($lines[$i]->detail_batch) && count($lines[$i]->detail_batch) > 0)
643
-				{
644
-					// line with lot
645
-					foreach ($lines[$i]->detail_batch as $detail_batch)
646
-					{
647
-						$lotStock = new Productbatch($db);
648
-						$batch="batchl".$detail_batch->fk_expeditiondet."_".$detail_batch->fk_origin_stock;
649
-						$qty = "qtyl".$detail_batch->fk_expeditiondet.'_'.$detail_batch->id;
650
-						$batch_id = GETPOST($batch,'int');
651
-						$batch_qty = GETPOST($qty, 'int');
652
-						if (! empty($batch_id) && ($batch_id != $detail_batch->fk_origin_stock || $batch_qty != $detail_batch->qty))
653
-						{
654
-							if ($lotStock->fetch($batch_id) > 0 && $line->fetch($detail_batch->fk_expeditiondet) > 0)	// $line is ExpeditionLine
655
-							{
656
-								if ($lines[$i]->entrepot_id != 0)
657
-								{
658
-									// allow update line entrepot_id if not multi warehouse shipping
659
-									$line->entrepot_id = $lotStock->warehouseid;
660
-								}
661
-
662
-								// detail_batch can be an object with keys, or an array of ExpeditionLineBatch
663
-								if (empty($line->detail_batch)) $line->detail_batch=new stdClass();
664
-
665
-								$line->detail_batch->fk_origin_stock = $batch_id;
666
-								$line->detail_batch->batch = $lotStock->batch;
667
-								$line->detail_batch->id = $detail_batch->id;
668
-								$line->detail_batch->entrepot_id = $lotStock->warehouseid;
669
-								$line->detail_batch->qty = $batch_qty;
670
-								if ($line->update($user) < 0) {
671
-									setEventMessages($line->error, $line->errors, 'errors');
672
-									$error++;
673
-								}
674
-							}
675
-							else
676
-							{
677
-								setEventMessages($lotStock->error, $lotStock->errors, 'errors');
678
-								$error++;
679
-							}
680
-						}
681
-						unset($_POST[$batch]);
682
-						unset($_POST[$qty]);
683
-					}
684
-					// add new batch
685
-					$lotStock = new Productbatch($db);
686
-					$batch="batchl".$line_id."_0";
687
-					$qty = "qtyl".$line_id."_0";
688
-					$batch_id = GETPOST($batch,'int');
689
-					$batch_qty = GETPOST($qty, 'int');
690
-					$lineIdToAddLot = 0;
691
-					if ($batch_qty > 0 && ! empty($batch_id))
692
-					{
693
-						if ($lotStock->fetch($batch_id) > 0)
694
-						{
695
-							// check if lotStock warehouse id is same as line warehouse id
696
-							if ($lines[$i]->entrepot_id > 0)
697
-							{
698
-								// single warehouse shipment line
699
-								if ($lines[i]->entrepot_id == $lotStock->warehouseid)
700
-								{
701
-									$lineIdToAddLot = $line_id;
702
-								}
703
-							}
704
-							else if (count($lines[$i]->details_entrepot) > 1)
705
-							{
706
-								// multi warehouse shipment lines
707
-								foreach ($lines[$i]->details_entrepot as $detail_entrepot)
708
-								{
709
-									if ($detail_entrepot->entrepot_id == $lotStock->warehouseid)
710
-									{
711
-										$lineIdToAddLot = $detail_entrepot->line_id;
712
-									}
713
-								}
714
-							}
715
-							if ($lineIdToAddLot)
716
-							{
717
-								// add lot to existing line
718
-								if ($line->fetch($lineIdToAddLot) > 0)
719
-								{
720
-									$line->detail_batch->fk_origin_stock = $batch_id;
721
-									$line->detail_batch->batch = $lotStock->batch;
722
-									$line->detail_batch->entrepot_id = $lotStock->warehouseid;
723
-									$line->detail_batch->qty = $batch_qty;
724
-									if ($line->update($user) < 0) {
725
-										setEventMessages($line->error, $line->errors, 'errors');
726
-										$error++;
727
-									}
728
-								}
729
-								else
730
-								{
731
-									setEventMessages($line->error, $line->errors, 'errors');
732
-									$error++;
733
-								}
734
-							}
735
-							else
736
-							{
737
-								// create new line with new lot
738
-								$line->origin_line_id = $lines[$i]->origin_line_id;
739
-								$line->entrepot_id = $lotStock->warehouseid;
740
-								$line->detail_batch[0] = new ExpeditionLineBatch($db);
741
-								$line->detail_batch[0]->fk_origin_stock = $batch_id;
742
-								$line->detail_batch[0]->batch = $lotStock->batch;
743
-								$line->detail_batch[0]->entrepot_id = $lotStock->warehouseid;
744
-								$line->detail_batch[0]->qty = $batch_qty;
745
-								if ($object->create_line_batch($line, $line->array_options) < 0)
746
-								{
747
-									setEventMessages($object->error, $object->errors, 'errors');
748
-									$error++;
749
-								}
750
-							}
751
-						}
752
-						else
753
-						{
754
-							setEventMessages($lotStock->error, $lotStock->errors, 'errors');
755
-							$error++;
756
-						}
757
-					}
758
-				}
759
-				else
760
-				{
761
-					if ($lines[$i]->fk_product > 0)
762
-					{
763
-						// line without lot
764
-						if ($lines[$i]->entrepot_id > 0)
765
-						{
766
-							// single warehouse shipment line
767
-							$stockLocation="entl".$line_id;
768
-							$qty = "qtyl".$line_id;
769
-							$line->id = $line_id;
770
-							$line->entrepot_id = GETPOST($stockLocation,'int');
771
-							$line->qty = GETPOST($qty, 'int');
772
-							if ($line->update($user) < 0) {
773
-								setEventMessages($line->error, $line->errors, 'errors');
774
-								$error++;
775
-							}
776
-							unset($_POST[$stockLocation]);
777
-							unset($_POST[$qty]);
778
-						}
779
-						else if (count($lines[$i]->details_entrepot) > 1)
780
-						{
781
-							// multi warehouse shipment lines
782
-							foreach ($lines[$i]->details_entrepot as $detail_entrepot)
783
-							{
784
-								if (! $error) {
785
-									$stockLocation="entl".$detail_entrepot->line_id;
786
-									$qty = "qtyl".$detail_entrepot->line_id;
787
-									$warehouse = GETPOST($stockLocation,'int');
788
-									if (!empty ($warehouse))
789
-									{
790
-										$line->id = $detail_entrepot->line_id;
791
-										$line->entrepot_id = $warehouse;
792
-										$line->qty = GETPOST($qty, 'int');
793
-										if ($line->update($user) < 0) {
794
-											setEventMessages($line->error, $line->errors, 'errors');
795
-											$error++;
796
-										}
797
-									}
798
-									unset($_POST[$stockLocation]);
799
-									unset($_POST[$qty]);
800
-								}
801
-							}
802
-						}
803
-					}
804
-					else	// Product no predefined
805
-					{
806
-						$qty = "qtyl".$line_id;
807
-						$line->id = $line_id;
808
-						$line->qty = GETPOST($qty, 'int');
809
-						$line->entrepot_id = 0;
810
-						if ($line->update($user) < 0) {
811
-							setEventMessages($line->error, $line->errors, 'errors');
812
-							$error++;
813
-						}
814
-						unset($_POST[$qty]);
815
-					}
816
-				}
817
-			}
818
-		}
819
-
820
-		unset($_POST["lineid"]);
821
-
822
-		if (! $error) {
823
-			if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
824
-				// Define output language
825
-				$outputlangs = $langs;
826
-				$newlang = '';
827
-				if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09'))
828
-					$newlang = GETPOST('lang_id','aZ09');
829
-				if ($conf->global->MAIN_MULTILANGS && empty($newlang))
830
-					$newlang = $object->thirdparty->default_lang;
831
-				if (! empty($newlang)) {
832
-					$outputlangs = new Translate("", $conf);
833
-					$outputlangs->setDefaultLang($newlang);
834
-				}
835
-
836
-				$ret = $object->fetch($object->id); // Reload to get new records
837
-				$object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
838
-			}
839
-		}
840
-		else
841
-		{
842
-			header('Location: ' . $_SERVER['PHP_SELF'] . '?id=' . $object->id); // Pour reaffichage de la fiche en cours d'edition
843
-			exit();
844
-		}
845
-	}
846
-
847
-	else if ($action == 'updateline' && $user->rights->expedition->creer && GETPOST('cancel','alpha') == $langs->trans('Cancel')) {
848
-		header('Location: ' . $_SERVER['PHP_SELF'] . '?id=' . $object->id); // Pour reaffichage de la fiche en cours d'edition
849
-		exit();
850
-	}
851
-
852
-	include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
853
-
854
-	// Actions to send emails
855
-	if (empty($id)) $id=$facid;
856
-	$trigger_name='SHIPPING_SENTBYMAIL';
857
-	$paramname='id';
858
-	$mode='emailfromshipment';
859
-	$trackid='shi'.$object->id;
860
-	include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
617
+    else if ($action == 'updateline' && $user->rights->expedition->creer && GETPOST('save'))
618
+    {
619
+        // Clean parameters
620
+        $qty=0;
621
+        $entrepot_id = 0;
622
+        $batch_id = 0;
623
+
624
+        $lines = $object->lines;
625
+        $num_prod = count($lines);
626
+        for ($i = 0 ; $i < $num_prod ; $i++)
627
+        {
628
+            if ($lines[$i]->id == $line_id)		// we have found line to update
629
+            {
630
+                $line = new ExpeditionLigne($db);
631
+                // Extrafields Lines
632
+                $extrafieldsline = new ExtraFields($db);
633
+                $extralabelsline = $extrafieldsline->fetch_name_optionals_label($object->table_element_line);
634
+                $line->array_options = $extrafieldsline->getOptionalsFromPost($extralabelsline);
635
+                // Unset extrafield POST Data
636
+                if (is_array($extralabelsline)) {
637
+                    foreach ($extralabelsline as $key => $value) {
638
+                        unset($_POST["options_" . $key]);
639
+                    }
640
+                }
641
+                $line->fk_product = $lines[$i]->fk_product;
642
+                if (is_array($lines[$i]->detail_batch) && count($lines[$i]->detail_batch) > 0)
643
+                {
644
+                    // line with lot
645
+                    foreach ($lines[$i]->detail_batch as $detail_batch)
646
+                    {
647
+                        $lotStock = new Productbatch($db);
648
+                        $batch="batchl".$detail_batch->fk_expeditiondet."_".$detail_batch->fk_origin_stock;
649
+                        $qty = "qtyl".$detail_batch->fk_expeditiondet.'_'.$detail_batch->id;
650
+                        $batch_id = GETPOST($batch,'int');
651
+                        $batch_qty = GETPOST($qty, 'int');
652
+                        if (! empty($batch_id) && ($batch_id != $detail_batch->fk_origin_stock || $batch_qty != $detail_batch->qty))
653
+                        {
654
+                            if ($lotStock->fetch($batch_id) > 0 && $line->fetch($detail_batch->fk_expeditiondet) > 0)	// $line is ExpeditionLine
655
+                            {
656
+                                if ($lines[$i]->entrepot_id != 0)
657
+                                {
658
+                                    // allow update line entrepot_id if not multi warehouse shipping
659
+                                    $line->entrepot_id = $lotStock->warehouseid;
660
+                                }
661
+
662
+                                // detail_batch can be an object with keys, or an array of ExpeditionLineBatch
663
+                                if (empty($line->detail_batch)) $line->detail_batch=new stdClass();
664
+
665
+                                $line->detail_batch->fk_origin_stock = $batch_id;
666
+                                $line->detail_batch->batch = $lotStock->batch;
667
+                                $line->detail_batch->id = $detail_batch->id;
668
+                                $line->detail_batch->entrepot_id = $lotStock->warehouseid;
669
+                                $line->detail_batch->qty = $batch_qty;
670
+                                if ($line->update($user) < 0) {
671
+                                    setEventMessages($line->error, $line->errors, 'errors');
672
+                                    $error++;
673
+                                }
674
+                            }
675
+                            else
676
+                            {
677
+                                setEventMessages($lotStock->error, $lotStock->errors, 'errors');
678
+                                $error++;
679
+                            }
680
+                        }
681
+                        unset($_POST[$batch]);
682
+                        unset($_POST[$qty]);
683
+                    }
684
+                    // add new batch
685
+                    $lotStock = new Productbatch($db);
686
+                    $batch="batchl".$line_id."_0";
687
+                    $qty = "qtyl".$line_id."_0";
688
+                    $batch_id = GETPOST($batch,'int');
689
+                    $batch_qty = GETPOST($qty, 'int');
690
+                    $lineIdToAddLot = 0;
691
+                    if ($batch_qty > 0 && ! empty($batch_id))
692
+                    {
693
+                        if ($lotStock->fetch($batch_id) > 0)
694
+                        {
695
+                            // check if lotStock warehouse id is same as line warehouse id
696
+                            if ($lines[$i]->entrepot_id > 0)
697
+                            {
698
+                                // single warehouse shipment line
699
+                                if ($lines[i]->entrepot_id == $lotStock->warehouseid)
700
+                                {
701
+                                    $lineIdToAddLot = $line_id;
702
+                                }
703
+                            }
704
+                            else if (count($lines[$i]->details_entrepot) > 1)
705
+                            {
706
+                                // multi warehouse shipment lines
707
+                                foreach ($lines[$i]->details_entrepot as $detail_entrepot)
708
+                                {
709
+                                    if ($detail_entrepot->entrepot_id == $lotStock->warehouseid)
710
+                                    {
711
+                                        $lineIdToAddLot = $detail_entrepot->line_id;
712
+                                    }
713
+                                }
714
+                            }
715
+                            if ($lineIdToAddLot)
716
+                            {
717
+                                // add lot to existing line
718
+                                if ($line->fetch($lineIdToAddLot) > 0)
719
+                                {
720
+                                    $line->detail_batch->fk_origin_stock = $batch_id;
721
+                                    $line->detail_batch->batch = $lotStock->batch;
722
+                                    $line->detail_batch->entrepot_id = $lotStock->warehouseid;
723
+                                    $line->detail_batch->qty = $batch_qty;
724
+                                    if ($line->update($user) < 0) {
725
+                                        setEventMessages($line->error, $line->errors, 'errors');
726
+                                        $error++;
727
+                                    }
728
+                                }
729
+                                else
730
+                                {
731
+                                    setEventMessages($line->error, $line->errors, 'errors');
732
+                                    $error++;
733
+                                }
734
+                            }
735
+                            else
736
+                            {
737
+                                // create new line with new lot
738
+                                $line->origin_line_id = $lines[$i]->origin_line_id;
739
+                                $line->entrepot_id = $lotStock->warehouseid;
740
+                                $line->detail_batch[0] = new ExpeditionLineBatch($db);
741
+                                $line->detail_batch[0]->fk_origin_stock = $batch_id;
742
+                                $line->detail_batch[0]->batch = $lotStock->batch;
743
+                                $line->detail_batch[0]->entrepot_id = $lotStock->warehouseid;
744
+                                $line->detail_batch[0]->qty = $batch_qty;
745
+                                if ($object->create_line_batch($line, $line->array_options) < 0)
746
+                                {
747
+                                    setEventMessages($object->error, $object->errors, 'errors');
748
+                                    $error++;
749
+                                }
750
+                            }
751
+                        }
752
+                        else
753
+                        {
754
+                            setEventMessages($lotStock->error, $lotStock->errors, 'errors');
755
+                            $error++;
756
+                        }
757
+                    }
758
+                }
759
+                else
760
+                {
761
+                    if ($lines[$i]->fk_product > 0)
762
+                    {
763
+                        // line without lot
764
+                        if ($lines[$i]->entrepot_id > 0)
765
+                        {
766
+                            // single warehouse shipment line
767
+                            $stockLocation="entl".$line_id;
768
+                            $qty = "qtyl".$line_id;
769
+                            $line->id = $line_id;
770
+                            $line->entrepot_id = GETPOST($stockLocation,'int');
771
+                            $line->qty = GETPOST($qty, 'int');
772
+                            if ($line->update($user) < 0) {
773
+                                setEventMessages($line->error, $line->errors, 'errors');
774
+                                $error++;
775
+                            }
776
+                            unset($_POST[$stockLocation]);
777
+                            unset($_POST[$qty]);
778
+                        }
779
+                        else if (count($lines[$i]->details_entrepot) > 1)
780
+                        {
781
+                            // multi warehouse shipment lines
782
+                            foreach ($lines[$i]->details_entrepot as $detail_entrepot)
783
+                            {
784
+                                if (! $error) {
785
+                                    $stockLocation="entl".$detail_entrepot->line_id;
786
+                                    $qty = "qtyl".$detail_entrepot->line_id;
787
+                                    $warehouse = GETPOST($stockLocation,'int');
788
+                                    if (!empty ($warehouse))
789
+                                    {
790
+                                        $line->id = $detail_entrepot->line_id;
791
+                                        $line->entrepot_id = $warehouse;
792
+                                        $line->qty = GETPOST($qty, 'int');
793
+                                        if ($line->update($user) < 0) {
794
+                                            setEventMessages($line->error, $line->errors, 'errors');
795
+                                            $error++;
796
+                                        }
797
+                                    }
798
+                                    unset($_POST[$stockLocation]);
799
+                                    unset($_POST[$qty]);
800
+                                }
801
+                            }
802
+                        }
803
+                    }
804
+                    else	// Product no predefined
805
+                    {
806
+                        $qty = "qtyl".$line_id;
807
+                        $line->id = $line_id;
808
+                        $line->qty = GETPOST($qty, 'int');
809
+                        $line->entrepot_id = 0;
810
+                        if ($line->update($user) < 0) {
811
+                            setEventMessages($line->error, $line->errors, 'errors');
812
+                            $error++;
813
+                        }
814
+                        unset($_POST[$qty]);
815
+                    }
816
+                }
817
+            }
818
+        }
819
+
820
+        unset($_POST["lineid"]);
821
+
822
+        if (! $error) {
823
+            if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
824
+                // Define output language
825
+                $outputlangs = $langs;
826
+                $newlang = '';
827
+                if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09'))
828
+                    $newlang = GETPOST('lang_id','aZ09');
829
+                if ($conf->global->MAIN_MULTILANGS && empty($newlang))
830
+                    $newlang = $object->thirdparty->default_lang;
831
+                if (! empty($newlang)) {
832
+                    $outputlangs = new Translate("", $conf);
833
+                    $outputlangs->setDefaultLang($newlang);
834
+                }
835
+
836
+                $ret = $object->fetch($object->id); // Reload to get new records
837
+                $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
838
+            }
839
+        }
840
+        else
841
+        {
842
+            header('Location: ' . $_SERVER['PHP_SELF'] . '?id=' . $object->id); // Pour reaffichage de la fiche en cours d'edition
843
+            exit();
844
+        }
845
+    }
846
+
847
+    else if ($action == 'updateline' && $user->rights->expedition->creer && GETPOST('cancel','alpha') == $langs->trans('Cancel')) {
848
+        header('Location: ' . $_SERVER['PHP_SELF'] . '?id=' . $object->id); // Pour reaffichage de la fiche en cours d'edition
849
+        exit();
850
+    }
851
+
852
+    include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
853
+
854
+    // Actions to send emails
855
+    if (empty($id)) $id=$facid;
856
+    $trigger_name='SHIPPING_SENTBYMAIL';
857
+    $paramname='id';
858
+    $mode='emailfromshipment';
859
+    $trackid='shi'.$object->id;
860
+    include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
861 861
 }
862 862
 
863 863
 
@@ -990,7 +990,7 @@  discard block
 block discarded – undo
990 990
                 print '<tr><td>'.$langs->trans("NotePrivate").'</td>';
991 991
                 print '<td colspan="3">';
992 992
                 $doleditor = new DolEditor('note_private', $object->note_private, '', 60, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%');
993
-        		print $doleditor->Create(1);
993
+                print $doleditor->Create(1);
994 994
                 print "</td></tr>";
995 995
             }
996 996
 
@@ -1033,37 +1033,37 @@  discard block
 block discarded – undo
1033 1033
             $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$expe,$action);    // Note that $action and $object may have been modified by hook
1034 1034
             print $hookmanager->resPrint;
1035 1035
 
1036
-			if (empty($reshook)) {
1037
-				// copy from order
1038
-				$orderExtrafields = new Extrafields($db);
1039
-				$orderExtrafieldLabels = $orderExtrafields->fetch_name_optionals_label($object->table_element);
1040
-				if ($object->fetch_optionals() > 0) {
1041
-					$expe->array_options = array_merge($expe->array_options, $object->array_options);
1042
-				}
1043
-				print $expe->showOptionals($extrafields, 'edit');
1044
-			}
1036
+            if (empty($reshook)) {
1037
+                // copy from order
1038
+                $orderExtrafields = new Extrafields($db);
1039
+                $orderExtrafieldLabels = $orderExtrafields->fetch_name_optionals_label($object->table_element);
1040
+                if ($object->fetch_optionals() > 0) {
1041
+                    $expe->array_options = array_merge($expe->array_options, $object->array_options);
1042
+                }
1043
+                print $expe->showOptionals($extrafields, 'edit');
1044
+            }
1045 1045
 
1046 1046
 
1047 1047
             // Incoterms
1048
-			if (!empty($conf->incoterm->enabled))
1049
-			{
1050
-				print '<tr>';
1051
-				print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $object->libelle_incoterms, 1).'</label></td>';
1052
-		        print '<td colspan="3" class="maxwidthonsmartphone">';
1053
-		        print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''));
1054
-				print '</td></tr>';
1055
-			}
1048
+            if (!empty($conf->incoterm->enabled))
1049
+            {
1050
+                print '<tr>';
1051
+                print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $object->libelle_incoterms, 1).'</label></td>';
1052
+                print '<td colspan="3" class="maxwidthonsmartphone">';
1053
+                print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''));
1054
+                print '</td></tr>';
1055
+            }
1056 1056
 
1057 1057
             // Document model
1058
-			include_once DOL_DOCUMENT_ROOT . '/core/modules/expedition/modules_expedition.php';
1059
-			$liste = ModelePdfExpedition::liste_modeles($db);
1060
-			if (count($liste) > 1)
1061
-			{
1062
-    			print "<tr><td>".$langs->trans("DefaultModel")."</td>";
1058
+            include_once DOL_DOCUMENT_ROOT . '/core/modules/expedition/modules_expedition.php';
1059
+            $liste = ModelePdfExpedition::liste_modeles($db);
1060
+            if (count($liste) > 1)
1061
+            {
1062
+                print "<tr><td>".$langs->trans("DefaultModel")."</td>";
1063 1063
                 print '<td colspan="3">';
1064
-    			print $form->selectarray('model', $liste, $conf->global->EXPEDITION_ADDON_PDF);
1064
+                print $form->selectarray('model', $liste, $conf->global->EXPEDITION_ADDON_PDF);
1065 1065
                 print "</td></tr>\n";
1066
-			}
1066
+            }
1067 1067
 
1068 1068
             print "</table>";
1069 1069
 
@@ -1077,21 +1077,21 @@  discard block
 block discarded – undo
1077 1077
             print '<script type="text/javascript" language="javascript">
1078 1078
             jQuery(document).ready(function() {
1079 1079
 	            jQuery("#autofill").click(function() {';
1080
-    	    	$i=0;
1081
-    	    	while($i < $numAsked)
1082
-    	    	{
1083
-    	    		print 'jQuery("#qtyl'.$i.'").val(jQuery("#qtyasked'.$i.'").val() - jQuery("#qtydelivered'.$i.'").val());'."\n";
1084
-    	    		$i++;
1085
-    	    	}
1086
-        		print '});
1080
+                $i=0;
1081
+                while($i < $numAsked)
1082
+                {
1083
+                    print 'jQuery("#qtyl'.$i.'").val(jQuery("#qtyasked'.$i.'").val() - jQuery("#qtydelivered'.$i.'").val());'."\n";
1084
+                    $i++;
1085
+                }
1086
+                print '});
1087 1087
 	            jQuery("#autoreset").click(function() {';
1088
-    	    	$i=0;
1089
-    	    	while($i < $numAsked)
1090
-    	    	{
1091
-    	    		print 'jQuery("#qtyl'.$i.'").val(0);'."\n";
1092
-    	    		$i++;
1093
-    	    	}
1094
-        		print '});
1088
+                $i=0;
1089
+                while($i < $numAsked)
1090
+                {
1091
+                    print 'jQuery("#qtyl'.$i.'").val(0);'."\n";
1092
+                    $i++;
1093
+                }
1094
+                print '});
1095 1095
         	});
1096 1096
             </script>';
1097 1097
 
@@ -1112,22 +1112,22 @@  discard block
 block discarded – undo
1112 1112
                 print '<td align="center">'.$langs->trans("QtyOrdered").'</td>';
1113 1113
                 print '<td align="center">'.$langs->trans("QtyShipped").'</td>';
1114 1114
                 print '<td align="center">'.$langs->trans("QtyToShip");
1115
-				if (empty($conf->productbatch->enabled))
1116
-				{
1117
-	                print ' <br>(<a href="#" id="autofill">'.$langs->trans("Fill").'</a>';
1118
-	                print ' / <a href="#" id="autoreset">'.$langs->trans("Reset").'</a>)';
1119
-				}
1115
+                if (empty($conf->productbatch->enabled))
1116
+                {
1117
+                    print ' <br>(<a href="#" id="autofill">'.$langs->trans("Fill").'</a>';
1118
+                    print ' / <a href="#" id="autoreset">'.$langs->trans("Reset").'</a>)';
1119
+                }
1120 1120
                 print '</td>';
1121 1121
                 if (! empty($conf->stock->enabled))
1122 1122
                 {
1123
-					if (empty($conf->productbatch->enabled))
1124
-					{
1125
-                    	print '<td align="left">'.$langs->trans("Warehouse").' ('.$langs->trans("Stock").')</td>';
1126
-					}
1127
-					else
1128
-					{
1129
-						print '<td align="left">'.$langs->trans("Warehouse").' / '.$langs->trans("Batch").' ('.$langs->trans("Stock").')</td>';
1130
-					}
1123
+                    if (empty($conf->productbatch->enabled))
1124
+                    {
1125
+                        print '<td align="left">'.$langs->trans("Warehouse").' ('.$langs->trans("Stock").')</td>';
1126
+                    }
1127
+                    else
1128
+                    {
1129
+                        print '<td align="left">'.$langs->trans("Warehouse").' / '.$langs->trans("Batch").' ('.$langs->trans("Stock").')</td>';
1130
+                    }
1131 1131
                 }
1132 1132
                 print "</tr>\n";
1133 1133
             }
@@ -1182,16 +1182,16 @@  discard block
 block discarded – undo
1182 1182
                     print '</td>';
1183 1183
                 }
1184 1184
                 else
1185
-				{
1186
-				    print "<td>";
1185
+                {
1186
+                    print "<td>";
1187 1187
                     if ($type==1) $text = img_object($langs->trans('Service'),'service');
1188 1188
                     else $text = img_object($langs->trans('Product'),'product');
1189 1189
 
1190 1190
                     if (! empty($line->label)) {
1191
-                    	$text.= ' <strong>'.$line->label.'</strong>';
1192
-                    	print $form->textwithtooltip($text,$line->desc,3,'','',$i);
1191
+                        $text.= ' <strong>'.$line->label.'</strong>';
1192
+                        print $form->textwithtooltip($text,$line->desc,3,'','',$i);
1193 1193
                     } else {
1194
-                    	print $text.' '.nl2br($line->desc);
1194
+                        print $text.' '.nl2br($line->desc);
1195 1195
                     }
1196 1196
 
1197 1197
                     // Show range
@@ -1214,372 +1214,372 @@  discard block
 block discarded – undo
1214 1214
 
1215 1215
                 // Qty to ship
1216 1216
                 $quantityAsked = $line->qty;
1217
-				if ($line->product_type == 1 && empty($conf->global->STOCK_SUPPORTS_SERVICES))
1218
-				{
1219
-					$quantityToBeDelivered = 0;
1220
-				}
1221
-				else
1222
-				{
1223
-					$quantityToBeDelivered = $quantityAsked - $quantityDelivered;
1224
-				}
1217
+                if ($line->product_type == 1 && empty($conf->global->STOCK_SUPPORTS_SERVICES))
1218
+                {
1219
+                    $quantityToBeDelivered = 0;
1220
+                }
1221
+                else
1222
+                {
1223
+                    $quantityToBeDelivered = $quantityAsked - $quantityDelivered;
1224
+                }
1225 1225
                 $warehouse_id = GETPOST('entrepot_id','int');
1226 1226
 
1227
-				$warehouseObject = null;
1228
-				if ($warehouse_id > 0 || ! ($line->fk_product > 0) || empty($conf->stock->enabled))     // If warehouse was already selected or if product is not a predefined, we go into this part with no multiwarehouse selection
1229
-				{
1230
-				    print '<!-- Case warehouse already known or product not a predefined product -->';
1231
-					//ship from preselected location
1232
-					$stock = + $product->stock_warehouse[$warehouse_id]->real; // Convert to number
1233
-					$deliverableQty=min($quantityToBeDelivered, $stock);
1234
-					if ($deliverableQty < 0) $deliverableQty = 0;
1235
-					if (empty($conf->productbatch->enabled) || ! $product->hasbatch())
1236
-					{
1237
-						// Quantity to send
1238
-						print '<td align="center">';
1239
-						if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1240
-						{
1227
+                $warehouseObject = null;
1228
+                if ($warehouse_id > 0 || ! ($line->fk_product > 0) || empty($conf->stock->enabled))     // If warehouse was already selected or if product is not a predefined, we go into this part with no multiwarehouse selection
1229
+                {
1230
+                    print '<!-- Case warehouse already known or product not a predefined product -->';
1231
+                    //ship from preselected location
1232
+                    $stock = + $product->stock_warehouse[$warehouse_id]->real; // Convert to number
1233
+                    $deliverableQty=min($quantityToBeDelivered, $stock);
1234
+                    if ($deliverableQty < 0) $deliverableQty = 0;
1235
+                    if (empty($conf->productbatch->enabled) || ! $product->hasbatch())
1236
+                    {
1237
+                        // Quantity to send
1238
+                        print '<td align="center">';
1239
+                        if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1240
+                        {
1241 1241
                             if (GETPOST('qtyl'.$indiceAsked, 'int')) $deliverableQty=GETPOST('qtyl'.$indiceAsked, 'int');
1242 1242
                             print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1243
-							print '<input name="qtyl'.$indiceAsked.'" id="qtyl'.$indiceAsked.'" type="text" size="4" value="'.$deliverableQty.'">';
1244
-						}
1245
-						else print $langs->trans("NA");
1246
-						print '</td>';
1247
-
1248
-						// Stock
1249
-						if (! empty($conf->stock->enabled))
1250
-						{
1251
-							print '<td align="left">';
1252
-							if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))   // Type of product need stock change ?
1253
-							{
1254
-								// Show warehouse combo list
1255
-								$ent = "entl".$indiceAsked;
1256
-								$idl = "idl".$indiceAsked;
1257
-								$tmpentrepot_id = is_numeric(GETPOST($ent,'int'))?GETPOST($ent,'int'):$warehouse_id;
1258
-								if ($line->fk_product > 0)
1259
-								{
1260
-								    print '<!-- Show warehouse selection -->';
1261
-									print $formproduct->selectWarehouses($tmpentrepot_id, 'entl'.$indiceAsked, '', 1, 0, $line->fk_product, '', 1);
1262
-									if ($tmpentrepot_id > 0 && $tmpentrepot_id == $warehouse_id)
1263
-									{
1264
-										//print $stock.' '.$quantityToBeDelivered;
1265
-										if ($stock < $quantityToBeDelivered)
1266
-										{
1267
-											print ' '.img_warning($langs->trans("StockTooLow"));	// Stock too low for this $warehouse_id but you can change warehouse
1268
-										}
1269
-									}
1270
-								}
1271
-							}
1272
-							else
1273
-							{
1274
-								print $langs->trans("Service");
1275
-							}
1276
-							print '</td>';
1277
-						}
1278
-
1279
-						print "</tr>\n";
1280
-
1281
-						// Show subproducts of product
1282
-						if (! empty($conf->global->PRODUIT_SOUSPRODUITS) && $line->fk_product > 0)
1283
-						{
1284
-							$product->get_sousproduits_arbo();
1285
-							$prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
1286
-							if(count($prods_arbo) > 0)
1287
-							{
1288
-								foreach($prods_arbo as $key => $value)
1289
-								{
1290
-									//print $value[0];
1291
-									$img='';
1292
-									if ($value['stock'] < $value['stock_alert'])
1293
-									{
1294
-										$img=img_warning($langs->trans("StockTooLow"));
1295
-									}
1296
-									print "<tr class=\"oddeven\"><td>&nbsp; &nbsp; &nbsp; ->
1243
+                            print '<input name="qtyl'.$indiceAsked.'" id="qtyl'.$indiceAsked.'" type="text" size="4" value="'.$deliverableQty.'">';
1244
+                        }
1245
+                        else print $langs->trans("NA");
1246
+                        print '</td>';
1247
+
1248
+                        // Stock
1249
+                        if (! empty($conf->stock->enabled))
1250
+                        {
1251
+                            print '<td align="left">';
1252
+                            if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))   // Type of product need stock change ?
1253
+                            {
1254
+                                // Show warehouse combo list
1255
+                                $ent = "entl".$indiceAsked;
1256
+                                $idl = "idl".$indiceAsked;
1257
+                                $tmpentrepot_id = is_numeric(GETPOST($ent,'int'))?GETPOST($ent,'int'):$warehouse_id;
1258
+                                if ($line->fk_product > 0)
1259
+                                {
1260
+                                    print '<!-- Show warehouse selection -->';
1261
+                                    print $formproduct->selectWarehouses($tmpentrepot_id, 'entl'.$indiceAsked, '', 1, 0, $line->fk_product, '', 1);
1262
+                                    if ($tmpentrepot_id > 0 && $tmpentrepot_id == $warehouse_id)
1263
+                                    {
1264
+                                        //print $stock.' '.$quantityToBeDelivered;
1265
+                                        if ($stock < $quantityToBeDelivered)
1266
+                                        {
1267
+                                            print ' '.img_warning($langs->trans("StockTooLow"));	// Stock too low for this $warehouse_id but you can change warehouse
1268
+                                        }
1269
+                                    }
1270
+                                }
1271
+                            }
1272
+                            else
1273
+                            {
1274
+                                print $langs->trans("Service");
1275
+                            }
1276
+                            print '</td>';
1277
+                        }
1278
+
1279
+                        print "</tr>\n";
1280
+
1281
+                        // Show subproducts of product
1282
+                        if (! empty($conf->global->PRODUIT_SOUSPRODUITS) && $line->fk_product > 0)
1283
+                        {
1284
+                            $product->get_sousproduits_arbo();
1285
+                            $prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
1286
+                            if(count($prods_arbo) > 0)
1287
+                            {
1288
+                                foreach($prods_arbo as $key => $value)
1289
+                                {
1290
+                                    //print $value[0];
1291
+                                    $img='';
1292
+                                    if ($value['stock'] < $value['stock_alert'])
1293
+                                    {
1294
+                                        $img=img_warning($langs->trans("StockTooLow"));
1295
+                                    }
1296
+                                    print "<tr class=\"oddeven\"><td>&nbsp; &nbsp; &nbsp; ->
1297 1297
 										<a href=\"".DOL_URL_ROOT."/product/card.php?id=".$value['id']."\">".$value['fullpath']."
1298 1298
 										</a> (".$value['nb'].")</td><td align=\"center\"> ".$value['nb_total']."</td><td>&nbsp</td><td>&nbsp</td>
1299 1299
 										<td align=\"center\">".$value['stock']." ".$img."</td></tr>";
1300
-								}
1301
-							}
1302
-						}
1303
-					}
1304
-					else
1305
-					{
1306
-					    // Product need lot
1307
-						print '<td></td><td></td></tr>';	// end line and start a new one for lot/serial
1308
-						print '<!-- Case product need lot -->';
1309
-
1310
-						$staticwarehouse=new Entrepot($db);
1311
-						if ($warehouse_id > 0) $staticwarehouse->fetch($warehouse_id);
1312
-
1313
-						$subj=0;
1314
-						// Define nb of lines suggested for this order line
1315
-						$nbofsuggested=0;
1316
-						if (is_object($product->stock_warehouse[$warehouse_id]) && count($product->stock_warehouse[$warehouse_id]->detail_batch))
1317
-						{
1318
-							foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch)
1319
-						    {
1320
-   						        $nbofsuggested++;
1321
-    						}
1322
-						}
1323
-						print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1324
-						if (is_object($product->stock_warehouse[$warehouse_id]) && count($product->stock_warehouse[$warehouse_id]->detail_batch))
1325
-						{
1326
-							foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch)	// $dbatch is instance of Productbatch
1327
-							{
1328
-								//var_dump($dbatch);
1329
-								$batchStock = + $dbatch->qty;		// To get a numeric
1330
-								$deliverableQty = min($quantityToBeDelivered,$batchStock);
1331
-								print '<!-- subj='.$subj.'/'.$nbofsuggested.' --><tr '.((($subj + 1) == $nbofsuggested)?$bc[$var]:'').'>';
1332
-								print '<td colspan="3" ></td><td align="center">';
1333
-								print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="'.$deliverableQty.'">';
1334
-								print '</td>';
1335
-
1336
-								print '<!-- Show details of lot -->';
1337
-								print '<td align="left">';
1338
-
1339
-								print $staticwarehouse->getNomUrl(0).' / ';
1340
-
1341
-								print '<input name="batchl'.$indiceAsked.'_'.$subj.'" type="hidden" value="'.$dbatch->id.'">';
1342
-
1343
-								$detail='';
1344
-								$detail.= $langs->trans("Batch").': '.$dbatch->batch;
1345
-								$detail.= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby,"day");
1346
-								$detail.= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby,"day");
1347
-								$detail.= ' - '.$langs->trans("Qty").': '.$dbatch->qty;
1348
-								$detail.= '<br>';
1349
-								print $detail;
1350
-
1351
-								$quantityToBeDelivered -= $deliverableQty;
1352
-								if ($quantityToBeDelivered < 0)
1353
-								{
1354
-									$quantityToBeDelivered = 0;
1355
-								}
1356
-								$subj++;
1357
-								print '</td></tr>';
1358
-							}
1359
-						}
1360
-						else
1361
-						{
1362
-						    print '<!-- Case there is no details of lot at all -->';
1363
-						    print '<tr class="oddeven"><td colspan="3"></td><td align="center">';
1364
-							print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="0" disabled="disabled"> ';
1365
-							print '</td>';
1366
-
1367
-							print '<td align="left">';
1368
-							print img_warning().' '.$langs->trans("NoProductToShipFoundIntoStock", $staticwarehouse->libelle);
1369
-							print '</td></tr>';
1370
-						}
1371
-					}
1372
-				}
1373
-				else
1374
-				{
1375
-					// ship from multiple locations
1376
-					if (empty($conf->productbatch->enabled) || ! $product->hasbatch())
1377
-					{
1378
-					    print '<!-- Case warehouse not already known and product does not need lot -->';
1379
-					    print '<td></td><td></td></tr>'."\n";	// end line and start a new one for each warehouse
1380
-
1381
-						print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1382
-						$subj=0;
1383
-    					// Define nb of lines suggested for this order line
1384
-						$nbofsuggested=0;
1385
-						foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
1386
-						{
1387
-							if ($stock_warehouse->real > 0)
1388
-							{
1300
+                                }
1301
+                            }
1302
+                        }
1303
+                    }
1304
+                    else
1305
+                    {
1306
+                        // Product need lot
1307
+                        print '<td></td><td></td></tr>';	// end line and start a new one for lot/serial
1308
+                        print '<!-- Case product need lot -->';
1309
+
1310
+                        $staticwarehouse=new Entrepot($db);
1311
+                        if ($warehouse_id > 0) $staticwarehouse->fetch($warehouse_id);
1312
+
1313
+                        $subj=0;
1314
+                        // Define nb of lines suggested for this order line
1315
+                        $nbofsuggested=0;
1316
+                        if (is_object($product->stock_warehouse[$warehouse_id]) && count($product->stock_warehouse[$warehouse_id]->detail_batch))
1317
+                        {
1318
+                            foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch)
1319
+                            {
1320
+                                    $nbofsuggested++;
1321
+                            }
1322
+                        }
1323
+                        print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1324
+                        if (is_object($product->stock_warehouse[$warehouse_id]) && count($product->stock_warehouse[$warehouse_id]->detail_batch))
1325
+                        {
1326
+                            foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch)	// $dbatch is instance of Productbatch
1327
+                            {
1328
+                                //var_dump($dbatch);
1329
+                                $batchStock = + $dbatch->qty;		// To get a numeric
1330
+                                $deliverableQty = min($quantityToBeDelivered,$batchStock);
1331
+                                print '<!-- subj='.$subj.'/'.$nbofsuggested.' --><tr '.((($subj + 1) == $nbofsuggested)?$bc[$var]:'').'>';
1332
+                                print '<td colspan="3" ></td><td align="center">';
1333
+                                print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="'.$deliverableQty.'">';
1334
+                                print '</td>';
1335
+
1336
+                                print '<!-- Show details of lot -->';
1337
+                                print '<td align="left">';
1338
+
1339
+                                print $staticwarehouse->getNomUrl(0).' / ';
1340
+
1341
+                                print '<input name="batchl'.$indiceAsked.'_'.$subj.'" type="hidden" value="'.$dbatch->id.'">';
1342
+
1343
+                                $detail='';
1344
+                                $detail.= $langs->trans("Batch").': '.$dbatch->batch;
1345
+                                $detail.= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby,"day");
1346
+                                $detail.= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby,"day");
1347
+                                $detail.= ' - '.$langs->trans("Qty").': '.$dbatch->qty;
1348
+                                $detail.= '<br>';
1349
+                                print $detail;
1350
+
1351
+                                $quantityToBeDelivered -= $deliverableQty;
1352
+                                if ($quantityToBeDelivered < 0)
1353
+                                {
1354
+                                    $quantityToBeDelivered = 0;
1355
+                                }
1356
+                                $subj++;
1357
+                                print '</td></tr>';
1358
+                            }
1359
+                        }
1360
+                        else
1361
+                        {
1362
+                            print '<!-- Case there is no details of lot at all -->';
1363
+                            print '<tr class="oddeven"><td colspan="3"></td><td align="center">';
1364
+                            print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="0" disabled="disabled"> ';
1365
+                            print '</td>';
1366
+
1367
+                            print '<td align="left">';
1368
+                            print img_warning().' '.$langs->trans("NoProductToShipFoundIntoStock", $staticwarehouse->libelle);
1369
+                            print '</td></tr>';
1370
+                        }
1371
+                    }
1372
+                }
1373
+                else
1374
+                {
1375
+                    // ship from multiple locations
1376
+                    if (empty($conf->productbatch->enabled) || ! $product->hasbatch())
1377
+                    {
1378
+                        print '<!-- Case warehouse not already known and product does not need lot -->';
1379
+                        print '<td></td><td></td></tr>'."\n";	// end line and start a new one for each warehouse
1380
+
1381
+                        print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1382
+                        $subj=0;
1383
+                        // Define nb of lines suggested for this order line
1384
+                        $nbofsuggested=0;
1385
+                        foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
1386
+                        {
1387
+                            if ($stock_warehouse->real > 0)
1388
+                            {
1389 1389
                                 $nbofsuggested++;
1390
-						    }
1391
-						}
1392
-						$tmpwarehouseObject=new Entrepot($db);
1393
-						foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)    // $stock_warehouse is product_stock
1394
-						{
1395
-							$tmpwarehouseObject->fetch($warehouse_id);
1396
-							if ($stock_warehouse->real > 0)
1397
-							{
1398
-								$stock = + $stock_warehouse->real; // Convert it to number
1399
-								$deliverableQty = min($quantityToBeDelivered,$stock);
1400
-								$deliverableQty = max(0, $deliverableQty);
1401
-								// Quantity to send
1402
-								print '<!-- subj='.$subj.'/'.$nbofsuggested.' --><tr '.((($subj + 1) == $nbofsuggested)?$bc[$var]:'').'>';
1403
-								print '<td colspan="3" ></td><td align="center"><!-- qty to ship (no lot management for product line indiceAsked='.$indiceAsked.') -->';
1404
-								if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1405
-								{
1406
-									print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'" type="text" size="4" value="'.$deliverableQty.'">';
1407
-									print '<input name="ent1'.$indiceAsked.'_'.$subj.'" type="hidden" value="'.$warehouse_id.'">';
1408
-								}
1409
-								else print $langs->trans("NA");
1410
-								print '</td>';
1411
-
1412
-								// Stock
1413
-								if (! empty($conf->stock->enabled))
1414
-								{
1415
-									print '<td align="left">';
1416
-									if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1417
-									{
1418
-										print $tmpwarehouseObject->getNomUrl(0).' ';
1419
-
1420
-										print '<!-- Show details of stock -->';
1421
-										print '('.$stock.')';
1422
-									}
1423
-									else
1424
-									{
1425
-										print $langs->trans("Service");
1426
-									}
1427
-									print '</td>';
1428
-								}
1429
-								$quantityToBeDelivered -= $deliverableQty;
1430
-								if ($quantityToBeDelivered < 0)
1431
-								{
1432
-									$quantityToBeDelivered = 0;
1433
-								}
1434
-								$subj++;
1435
-								print "</tr>\n";
1436
-							}
1437
-						}
1438
-						// Show subproducts of product (not recommanded)
1439
-						if (! empty($conf->global->PRODUIT_SOUSPRODUITS) && $line->fk_product > 0)
1440
-						{
1441
-							$product->get_sousproduits_arbo();
1442
-							$prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
1443
-							if (count($prods_arbo) > 0)
1444
-							{
1445
-								foreach($prods_arbo as $key => $value)
1446
-								{
1447
-									//print $value[0];
1448
-									$img='';
1449
-									if ($value['stock'] < $value['stock_alert'])
1450
-									{
1451
-										$img=img_warning($langs->trans("StockTooLow"));
1452
-									}
1453
-									print '<tr class"oddeven"><td>';
1454
-									print "&nbsp; &nbsp; &nbsp; ->
1390
+                            }
1391
+                        }
1392
+                        $tmpwarehouseObject=new Entrepot($db);
1393
+                        foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)    // $stock_warehouse is product_stock
1394
+                        {
1395
+                            $tmpwarehouseObject->fetch($warehouse_id);
1396
+                            if ($stock_warehouse->real > 0)
1397
+                            {
1398
+                                $stock = + $stock_warehouse->real; // Convert it to number
1399
+                                $deliverableQty = min($quantityToBeDelivered,$stock);
1400
+                                $deliverableQty = max(0, $deliverableQty);
1401
+                                // Quantity to send
1402
+                                print '<!-- subj='.$subj.'/'.$nbofsuggested.' --><tr '.((($subj + 1) == $nbofsuggested)?$bc[$var]:'').'>';
1403
+                                print '<td colspan="3" ></td><td align="center"><!-- qty to ship (no lot management for product line indiceAsked='.$indiceAsked.') -->';
1404
+                                if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1405
+                                {
1406
+                                    print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'" type="text" size="4" value="'.$deliverableQty.'">';
1407
+                                    print '<input name="ent1'.$indiceAsked.'_'.$subj.'" type="hidden" value="'.$warehouse_id.'">';
1408
+                                }
1409
+                                else print $langs->trans("NA");
1410
+                                print '</td>';
1411
+
1412
+                                // Stock
1413
+                                if (! empty($conf->stock->enabled))
1414
+                                {
1415
+                                    print '<td align="left">';
1416
+                                    if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1417
+                                    {
1418
+                                        print $tmpwarehouseObject->getNomUrl(0).' ';
1419
+
1420
+                                        print '<!-- Show details of stock -->';
1421
+                                        print '('.$stock.')';
1422
+                                    }
1423
+                                    else
1424
+                                    {
1425
+                                        print $langs->trans("Service");
1426
+                                    }
1427
+                                    print '</td>';
1428
+                                }
1429
+                                $quantityToBeDelivered -= $deliverableQty;
1430
+                                if ($quantityToBeDelivered < 0)
1431
+                                {
1432
+                                    $quantityToBeDelivered = 0;
1433
+                                }
1434
+                                $subj++;
1435
+                                print "</tr>\n";
1436
+                            }
1437
+                        }
1438
+                        // Show subproducts of product (not recommanded)
1439
+                        if (! empty($conf->global->PRODUIT_SOUSPRODUITS) && $line->fk_product > 0)
1440
+                        {
1441
+                            $product->get_sousproduits_arbo();
1442
+                            $prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
1443
+                            if (count($prods_arbo) > 0)
1444
+                            {
1445
+                                foreach($prods_arbo as $key => $value)
1446
+                                {
1447
+                                    //print $value[0];
1448
+                                    $img='';
1449
+                                    if ($value['stock'] < $value['stock_alert'])
1450
+                                    {
1451
+                                        $img=img_warning($langs->trans("StockTooLow"));
1452
+                                    }
1453
+                                    print '<tr class"oddeven"><td>';
1454
+                                    print "&nbsp; &nbsp; &nbsp; ->
1455 1455
 									<a href=\"".DOL_URL_ROOT."/product/card.php?id=".$value['id']."\">".$value['fullpath']."
1456 1456
 									</a> (".$value['nb'].")</td><td align=\"center\"> ".$value['nb_total']."</td><td>&nbsp</td><td>&nbsp</td>
1457 1457
 									<td align=\"center\">".$value['stock']." ".$img."</td>";
1458
-									print "</tr>";
1459
-								}
1460
-							}
1461
-						}
1462
-					}
1463
-					else
1464
-					{
1465
-					    print '<!-- Case warehouse not already known and product need lot -->';
1466
-					    print '<td></td><td></td></tr>';	// end line and start a new one for lot/serial
1467
-
1468
-						$subj=0;
1469
-						print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1470
-
1471
-						$tmpwarehouseObject=new Entrepot($db);
1472
-						$productlotObject=new Productlot($db);
1473
-						// Define nb of lines suggested for this order line
1474
-						$nbofsuggested=0;
1475
-						foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
1476
-						{
1477
-						    if (($stock_warehouse->real > 0) && (count($stock_warehouse->detail_batch))) {
1478
-						        foreach ($stock_warehouse->detail_batch as $dbatch)
1479
-								{
1458
+                                    print "</tr>";
1459
+                                }
1460
+                            }
1461
+                        }
1462
+                    }
1463
+                    else
1464
+                    {
1465
+                        print '<!-- Case warehouse not already known and product need lot -->';
1466
+                        print '<td></td><td></td></tr>';	// end line and start a new one for lot/serial
1467
+
1468
+                        $subj=0;
1469
+                        print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1470
+
1471
+                        $tmpwarehouseObject=new Entrepot($db);
1472
+                        $productlotObject=new Productlot($db);
1473
+                        // Define nb of lines suggested for this order line
1474
+                        $nbofsuggested=0;
1475
+                        foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
1476
+                        {
1477
+                            if (($stock_warehouse->real > 0) && (count($stock_warehouse->detail_batch))) {
1478
+                                foreach ($stock_warehouse->detail_batch as $dbatch)
1479
+                                {
1480 1480
                                     $nbofsuggested++;
1481
-								}
1482
-						    }
1483
-						}
1484
-						foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
1485
-						{
1486
-							$tmpwarehouseObject->fetch($warehouse_id);
1487
-							if (($stock_warehouse->real > 0) && (count($stock_warehouse->detail_batch))) {
1488
-						        foreach ($stock_warehouse->detail_batch as $dbatch)
1489
-								{
1490
-									//var_dump($dbatch);
1491
-									$batchStock = + $dbatch->qty;		// To get a numeric
1492
-									$deliverableQty = min($quantityToBeDelivered,$batchStock);
1493
-									if ($deliverableQty < 0) $deliverableQty = 0;
1494
-									print '<!-- subj='.$subj.'/'.$nbofsuggested.' --><tr '.((($subj + 1) == $nbofsuggested)?$bc[$var]:'').'><td colspan="3"></td><td align="center">';
1495
-									print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="'.$deliverableQty.'">';
1496
-									print '</td>';
1497
-
1498
-									print '<td align="left">';
1499
-
1500
-									print $tmpwarehouseObject->getNomUrl(0).' / ';
1501
-
1502
-									print '<!-- Show details of lot -->';
1503
-									print '<input name="batchl'.$indiceAsked.'_'.$subj.'" type="hidden" value="'.$dbatch->id.'">';
1504
-
1505
-									//print '|'.$line->fk_product.'|'.$dbatch->batch.'|<br>';
1506
-									print $langs->trans("Batch").': ';
1507
-									$result = $productlotObject->fetch(0, $line->fk_product, $dbatch->batch);
1508
-									if ($result > 0) print $productlotObject->getNomUrl(1);
1509
-									else print 'TableLotIncompleteRunRepairWithParamStandardEqualConfirmed';
1510
-									print ' ('.$dbatch->qty.')';
1511
-									$quantityToBeDelivered -= $deliverableQty;
1512
-									if ($quantityToBeDelivered < 0)
1513
-									{
1514
-										$quantityToBeDelivered = 0;
1515
-									}
1516
-									//dol_syslog('deliverableQty = '.$deliverableQty.' batchStock = '.$batchStock);
1517
-									$subj++;
1518
-									print '</td></tr>';
1519
-								}
1520
-							}
1521
-						}
1522
-					}
1523
-					if ($subj == 0) // Line not shown yet, we show it
1524
-					{
1525
-					    print '<!-- line not shown yet, we show it -->';
1526
-						print '<tr class="oddeven"><td colspan="3" ></td><td align="center">';
1527
-						if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1528
-						{
1529
-						    $disabled='';
1530
-					        if (! empty($conf->productbatch->enabled) && $product->hasbatch())
1531
-					        {
1481
+                                }
1482
+                            }
1483
+                        }
1484
+                        foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
1485
+                        {
1486
+                            $tmpwarehouseObject->fetch($warehouse_id);
1487
+                            if (($stock_warehouse->real > 0) && (count($stock_warehouse->detail_batch))) {
1488
+                                foreach ($stock_warehouse->detail_batch as $dbatch)
1489
+                                {
1490
+                                    //var_dump($dbatch);
1491
+                                    $batchStock = + $dbatch->qty;		// To get a numeric
1492
+                                    $deliverableQty = min($quantityToBeDelivered,$batchStock);
1493
+                                    if ($deliverableQty < 0) $deliverableQty = 0;
1494
+                                    print '<!-- subj='.$subj.'/'.$nbofsuggested.' --><tr '.((($subj + 1) == $nbofsuggested)?$bc[$var]:'').'><td colspan="3"></td><td align="center">';
1495
+                                    print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="'.$deliverableQty.'">';
1496
+                                    print '</td>';
1497
+
1498
+                                    print '<td align="left">';
1499
+
1500
+                                    print $tmpwarehouseObject->getNomUrl(0).' / ';
1501
+
1502
+                                    print '<!-- Show details of lot -->';
1503
+                                    print '<input name="batchl'.$indiceAsked.'_'.$subj.'" type="hidden" value="'.$dbatch->id.'">';
1504
+
1505
+                                    //print '|'.$line->fk_product.'|'.$dbatch->batch.'|<br>';
1506
+                                    print $langs->trans("Batch").': ';
1507
+                                    $result = $productlotObject->fetch(0, $line->fk_product, $dbatch->batch);
1508
+                                    if ($result > 0) print $productlotObject->getNomUrl(1);
1509
+                                    else print 'TableLotIncompleteRunRepairWithParamStandardEqualConfirmed';
1510
+                                    print ' ('.$dbatch->qty.')';
1511
+                                    $quantityToBeDelivered -= $deliverableQty;
1512
+                                    if ($quantityToBeDelivered < 0)
1513
+                                    {
1514
+                                        $quantityToBeDelivered = 0;
1515
+                                    }
1516
+                                    //dol_syslog('deliverableQty = '.$deliverableQty.' batchStock = '.$batchStock);
1517
+                                    $subj++;
1518
+                                    print '</td></tr>';
1519
+                                }
1520
+                            }
1521
+                        }
1522
+                    }
1523
+                    if ($subj == 0) // Line not shown yet, we show it
1524
+                    {
1525
+                        print '<!-- line not shown yet, we show it -->';
1526
+                        print '<tr class="oddeven"><td colspan="3" ></td><td align="center">';
1527
+                        if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1528
+                        {
1529
+                            $disabled='';
1530
+                            if (! empty($conf->productbatch->enabled) && $product->hasbatch())
1531
+                            {
1532 1532
                                 $disabled='disabled="disabled"';
1533
-						    }
1534
-    						print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="0"'.($disabled?' '.$disabled:'').'> ';
1535
-						}
1536
-						else
1537
-						{
1538
-						    print $langs->trans("NA");
1539
-						}
1540
-						print '</td>';
1541
-
1542
-						print '<td align="left">';
1543
-						if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1544
-						{
1545
-							$warehouse_selected_id = GETPOST('entrepot_id','int');
1546
-    						if ($warehouse_selected_id > 0)
1547
-    						{
1548
-    							$warehouseObject=new Entrepot($db);
1549
-    							$warehouseObject->fetch($warehouse_selected_id);
1550
-    							print img_warning().' '.$langs->trans("NoProductToShipFoundIntoStock", $warehouseObject->libelle);
1551
-    						}
1552
-    						else
1553
-    						{
1554
-    						    if ($line->fk_product) print img_warning().' '.$langs->trans("StockTooLow");
1555
-    						    else print '';
1556
-    						}
1557
-						}
1558
-						else
1559
-						{
1560
-						    print $langs->trans("Service");
1561
-						}
1562
-						print '</td>';
1563
-						print '</tr>';
1564
-					}
1565
-				}
1566
-
1567
-
1568
-				//Display lines extrafields
1569
-				if (is_array($extralabelslines) && count($extralabelslines)>0)
1570
-				{
1571
-					$colspan=5;
1572
-					$orderLineExtrafields = new Extrafields($db);
1573
-					$orderLineExtrafieldLabels = $orderLineExtrafields->fetch_name_optionals_label($object->table_element_line);
1574
-					$srcLine = new OrderLine($db);
1575
-					$srcLine->fetch_optionals($line->id); // fetch extrafields also available in orderline
1576
-					$line = new ExpeditionLigne($db);
1577
-					//$line->fetch_optionals($line->id);
1578
-					$line->array_options = array_merge($line->array_options, $srcLine->array_options);
1579
-					print '<tr class="oddeven">';
1580
-					print $line->showOptionals($extrafieldsline, 'edit', array('style'=>$bc[$var], 'colspan'=>$colspan),$indiceAsked);
1581
-					print '</tr>';
1582
-				}
1533
+                            }
1534
+                            print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="0"'.($disabled?' '.$disabled:'').'> ';
1535
+                        }
1536
+                        else
1537
+                        {
1538
+                            print $langs->trans("NA");
1539
+                        }
1540
+                        print '</td>';
1541
+
1542
+                        print '<td align="left">';
1543
+                        if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1544
+                        {
1545
+                            $warehouse_selected_id = GETPOST('entrepot_id','int');
1546
+                            if ($warehouse_selected_id > 0)
1547
+                            {
1548
+                                $warehouseObject=new Entrepot($db);
1549
+                                $warehouseObject->fetch($warehouse_selected_id);
1550
+                                print img_warning().' '.$langs->trans("NoProductToShipFoundIntoStock", $warehouseObject->libelle);
1551
+                            }
1552
+                            else
1553
+                            {
1554
+                                if ($line->fk_product) print img_warning().' '.$langs->trans("StockTooLow");
1555
+                                else print '';
1556
+                            }
1557
+                        }
1558
+                        else
1559
+                        {
1560
+                            print $langs->trans("Service");
1561
+                        }
1562
+                        print '</td>';
1563
+                        print '</tr>';
1564
+                    }
1565
+                }
1566
+
1567
+
1568
+                //Display lines extrafields
1569
+                if (is_array($extralabelslines) && count($extralabelslines)>0)
1570
+                {
1571
+                    $colspan=5;
1572
+                    $orderLineExtrafields = new Extrafields($db);
1573
+                    $orderLineExtrafieldLabels = $orderLineExtrafields->fetch_name_optionals_label($object->table_element_line);
1574
+                    $srcLine = new OrderLine($db);
1575
+                    $srcLine->fetch_optionals($line->id); // fetch extrafields also available in orderline
1576
+                    $line = new ExpeditionLigne($db);
1577
+                    //$line->fetch_optionals($line->id);
1578
+                    $line->array_options = array_merge($line->array_options, $srcLine->array_options);
1579
+                    print '<tr class="oddeven">';
1580
+                    print $line->showOptionals($extrafieldsline, 'edit', array('style'=>$bc[$var], 'colspan'=>$colspan),$indiceAsked);
1581
+                    print '</tr>';
1582
+                }
1583 1583
 
1584 1584
                 $indiceAsked++;
1585 1585
             }
@@ -1599,7 +1599,7 @@  discard block
 block discarded – undo
1599 1599
             print '<br>';
1600 1600
         }
1601 1601
         else
1602
-		{
1602
+        {
1603 1603
             dol_print_error($db);
1604 1604
         }
1605 1605
     }
@@ -1611,102 +1611,102 @@  discard block
 block discarded – undo
1611 1611
 /*                                                                             */
1612 1612
 /* *************************************************************************** */
1613 1613
 {
1614
-	$lines = $object->lines;
1614
+    $lines = $object->lines;
1615 1615
 
1616
-	$num_prod = count($lines);
1616
+    $num_prod = count($lines);
1617 1617
 
1618
-	if ($object->id > 0)
1619
-	{
1620
-		if (!empty($object->origin) && $object->origin_id > 0)
1621
-		{
1622
-			$typeobject = $object->origin;
1623
-			$origin = $object->origin;
1624
-			$origin_id = $object->origin_id;
1625
-			$object->fetch_origin();         // Load property $object->commande, $object->propal, ...
1626
-		}
1627
-
1628
-		$soc = new Societe($db);
1629
-		$soc->fetch($object->socid);
1630
-
1631
-		$res = $object->fetch_optionals();
1632
-
1633
-		$head=shipping_prepare_head($object);
1634
-		dol_fiche_head($head, 'shipping', $langs->trans("Shipment"), -1, 'sending');
1635
-
1636
-		$formconfirm='';
1637
-
1638
-		// Confirm deleteion
1639
-		if ($action == 'delete')
1640
-		{
1641
-			$formconfirm=$form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('DeleteSending'),$langs->trans("ConfirmDeleteSending",$object->ref),'confirm_delete','',0,1);
1642
-		}
1643
-
1644
-		// Confirmation validation
1645
-		if ($action == 'valid')
1646
-		{
1647
-			$objectref = substr($object->ref, 1, 4);
1648
-			if ($objectref == 'PROV')
1649
-			{
1650
-				$numref = $object->getNextNumRef($soc);
1651
-			}
1652
-			else
1653
-			{
1654
-				$numref = $object->ref;
1655
-			}
1656
-
1657
-			$text = $langs->trans("ConfirmValidateSending",$numref);
1658
-
1659
-			if (! empty($conf->notification->enabled))
1660
-			{
1661
-				require_once DOL_DOCUMENT_ROOT .'/core/class/notify.class.php';
1662
-				$notify=new Notify($db);
1663
-				$text.='<br>';
1664
-				$text.=$notify->confirmMessage('SHIPPING_VALIDATE',$object->socid, $object);
1665
-			}
1666
-
1667
-			$formconfirm=$form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('ValidateSending'),$text,'confirm_valid','',0,1);
1668
-		}
1669
-		// Confirm cancelation
1670
-		if ($action == 'annuler')
1671
-		{
1672
-			$formconfirm=$form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('CancelSending'),$langs->trans("ConfirmCancelSending",$object->ref),'confirm_cancel','',0,1);
1673
-		}
1674
-
1675
-		// Call Hook formConfirm
1676
-		$parameters = array();
1677
-		$reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1678
-		if (empty($reshook)) $formconfirm.=$hookmanager->resPrint;
1679
-		elseif ($reshook > 0) $formconfirm=$hookmanager->resPrint;
1680
-
1681
-		// Print form confirm
1682
-		print $formconfirm;
1683
-
1684
-
1685
-		// Calculate totalWeight and totalVolume for all products
1686
-		// by adding weight and volume of each product line.
1687
-		$tmparray=$object->getTotalWeightVolume();
1688
-		$totalWeight=$tmparray['weight'];
1689
-		$totalVolume=$tmparray['volume'];
1690
-
1691
-
1692
-		if ($typeobject == 'commande' && $object->$typeobject->id && ! empty($conf->commande->enabled))
1693
-		{
1694
-		    $objectsrc=new Commande($db);
1695
-		    $objectsrc->fetch($object->$typeobject->id);
1696
-		}
1697
-		if ($typeobject == 'propal' && $object->$typeobject->id && ! empty($conf->propal->enabled))
1698
-		{
1699
-		    $objectsrc=new Propal($db);
1700
-		    $objectsrc->fetch($object->$typeobject->id);
1701
-		}
1702
-
1703
-		// Shipment card
1704
-		$linkback = '<a href="'.DOL_URL_ROOT.'/expedition/list.php?restore_lastsearch_values=1' . (! empty($socid) ? '&socid=' . $socid : '') . '">'.$langs->trans("BackToList").'</a>';
1705
-		$morehtmlref='<div class="refidno">';
1706
-		// Ref customer shipment
1707
-		$morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->rights->expedition->creer, 'string', '', 0, 1);
1708
-		$morehtmlref.=$form->editfieldval("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->rights->expedition->creer, 'string', '', null, null, '', 1);
1709
-		// Thirdparty
1618
+    if ($object->id > 0)
1619
+    {
1620
+        if (!empty($object->origin) && $object->origin_id > 0)
1621
+        {
1622
+            $typeobject = $object->origin;
1623
+            $origin = $object->origin;
1624
+            $origin_id = $object->origin_id;
1625
+            $object->fetch_origin();         // Load property $object->commande, $object->propal, ...
1626
+        }
1627
+
1628
+        $soc = new Societe($db);
1629
+        $soc->fetch($object->socid);
1630
+
1631
+        $res = $object->fetch_optionals();
1632
+
1633
+        $head=shipping_prepare_head($object);
1634
+        dol_fiche_head($head, 'shipping', $langs->trans("Shipment"), -1, 'sending');
1635
+
1636
+        $formconfirm='';
1637
+
1638
+        // Confirm deleteion
1639
+        if ($action == 'delete')
1640
+        {
1641
+            $formconfirm=$form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('DeleteSending'),$langs->trans("ConfirmDeleteSending",$object->ref),'confirm_delete','',0,1);
1642
+        }
1643
+
1644
+        // Confirmation validation
1645
+        if ($action == 'valid')
1646
+        {
1647
+            $objectref = substr($object->ref, 1, 4);
1648
+            if ($objectref == 'PROV')
1649
+            {
1650
+                $numref = $object->getNextNumRef($soc);
1651
+            }
1652
+            else
1653
+            {
1654
+                $numref = $object->ref;
1655
+            }
1656
+
1657
+            $text = $langs->trans("ConfirmValidateSending",$numref);
1658
+
1659
+            if (! empty($conf->notification->enabled))
1660
+            {
1661
+                require_once DOL_DOCUMENT_ROOT .'/core/class/notify.class.php';
1662
+                $notify=new Notify($db);
1663
+                $text.='<br>';
1664
+                $text.=$notify->confirmMessage('SHIPPING_VALIDATE',$object->socid, $object);
1665
+            }
1666
+
1667
+            $formconfirm=$form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('ValidateSending'),$text,'confirm_valid','',0,1);
1668
+        }
1669
+        // Confirm cancelation
1670
+        if ($action == 'annuler')
1671
+        {
1672
+            $formconfirm=$form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('CancelSending'),$langs->trans("ConfirmCancelSending",$object->ref),'confirm_cancel','',0,1);
1673
+        }
1674
+
1675
+        // Call Hook formConfirm
1676
+        $parameters = array();
1677
+        $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1678
+        if (empty($reshook)) $formconfirm.=$hookmanager->resPrint;
1679
+        elseif ($reshook > 0) $formconfirm=$hookmanager->resPrint;
1680
+
1681
+        // Print form confirm
1682
+        print $formconfirm;
1683
+
1684
+
1685
+        // Calculate totalWeight and totalVolume for all products
1686
+        // by adding weight and volume of each product line.
1687
+        $tmparray=$object->getTotalWeightVolume();
1688
+        $totalWeight=$tmparray['weight'];
1689
+        $totalVolume=$tmparray['volume'];
1690
+
1691
+
1692
+        if ($typeobject == 'commande' && $object->$typeobject->id && ! empty($conf->commande->enabled))
1693
+        {
1694
+            $objectsrc=new Commande($db);
1695
+            $objectsrc->fetch($object->$typeobject->id);
1696
+        }
1697
+        if ($typeobject == 'propal' && $object->$typeobject->id && ! empty($conf->propal->enabled))
1698
+        {
1699
+            $objectsrc=new Propal($db);
1700
+            $objectsrc->fetch($object->$typeobject->id);
1701
+        }
1702
+
1703
+        // Shipment card
1704
+        $linkback = '<a href="'.DOL_URL_ROOT.'/expedition/list.php?restore_lastsearch_values=1' . (! empty($socid) ? '&socid=' . $socid : '') . '">'.$langs->trans("BackToList").'</a>';
1705
+        $morehtmlref='<div class="refidno">';
1706
+        // Ref customer shipment
1707
+        $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->rights->expedition->creer, 'string', '', 0, 1);
1708
+        $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->rights->expedition->creer, 'string', '', null, null, '', 1);
1709
+        // Thirdparty
1710 1710
         $morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1);
1711 1711
         // Project
1712 1712
         if (! empty($conf->projet->enabled)) {
@@ -1742,849 +1742,849 @@  discard block
 block discarded – undo
1742 1742
                 }
1743 1743
             }
1744 1744
         }
1745
-		$morehtmlref.='</div>';
1745
+        $morehtmlref.='</div>';
1746 1746
 
1747 1747
 
1748
-    	dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
1748
+        dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
1749 1749
 
1750 1750
 
1751
-    	print '<div class="fichecenter">';
1752
-    	print '<div class="fichehalfleft">';
1753
-    	print '<div class="underbanner clearboth"></div>';
1751
+        print '<div class="fichecenter">';
1752
+        print '<div class="fichehalfleft">';
1753
+        print '<div class="underbanner clearboth"></div>';
1754 1754
 
1755 1755
         print '<table class="border" width="100%">';
1756 1756
 
1757
-		// Linked documents
1758
-		if ($typeobject == 'commande' && $object->$typeobject->id && ! empty($conf->commande->enabled))
1759
-		{
1760
-			print '<tr><td>';
1761
-			print $langs->trans("RefOrder").'</td>';
1762
-			print '<td colspan="3">';
1763
-			print $objectsrc->getNomUrl(1,'commande');
1764
-			print "</td>\n";
1765
-			print '</tr>';
1766
-		}
1767
-		if ($typeobject == 'propal' && $object->$typeobject->id && ! empty($conf->propal->enabled))
1768
-		{
1769
-			print '<tr><td>';
1770
-			print $langs->trans("RefProposal").'</td>';
1771
-			print '<td colspan="3">';
1772
-			print $objectsrc->getNomUrl(1,'expedition');
1773
-			print "</td>\n";
1774
-			print '</tr>';
1775
-		}
1776
-
1777
-		// Date creation
1778
-		print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
1779
-		print '<td colspan="3">'.dol_print_date($object->date_creation,"dayhour")."</td>\n";
1780
-		print '</tr>';
1781
-
1782
-		// Delivery date planned
1783
-		print '<tr><td height="10">';
1784
-		print '<table class="nobordernopadding" width="100%"><tr><td>';
1785
-		print $langs->trans('DateDeliveryPlanned');
1786
-		print '</td>';
1787
-
1788
-		if ($action != 'editdate_livraison') print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editdate_livraison&amp;id='.$object->id.'">'.img_edit($langs->trans('SetDeliveryDate'),1).'</a></td>';
1789
-		print '</tr></table>';
1790
-		print '</td><td colspan="2">';
1791
-		if ($action == 'editdate_livraison')
1792
-		{
1793
-			print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1794
-			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1795
-			print '<input type="hidden" name="action" value="setdate_livraison">';
1796
-			print $form->selectDate($object->date_delivery?$object->date_delivery:-1, 'liv_', 1, 1, '', "setdate_livraison", 1, 0);
1797
-			print '<input type="submit" class="button" value="'.$langs->trans('Modify').'">';
1798
-			print '</form>';
1799
-		}
1800
-		else
1801
-		{
1802
-			print $object->date_delivery ? dol_print_date($object->date_delivery,'dayhour') : '&nbsp;';
1803
-		}
1804
-		print '</td>';
1805
-		print '</tr>';
1806
-
1807
-		// Weight
1808
-		print '<tr><td>';
1809
-		print $form->editfieldkey("Weight",'trueWeight',$object->trueWeight,$object,$user->rights->expedition->creer);
1810
-		print '</td><td colspan="3">';
1811
-
1812
-		if ($action=='edittrueWeight')
1813
-		{
1814
-			print '<form name="settrueweight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1815
-			print '<input name="action" value="settrueWeight" type="hidden">';
1816
-			print '<input name="id" value="'.$object->id.'" type="hidden">';
1817
-			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1818
-			print '<input id="trueWeight" name="trueWeight" value="'.$object->trueWeight.'" type="text">';
1819
-			print $formproduct->select_measuring_units("weight_units","weight",$object->weight_units);
1820
-			print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1821
-			print ' <input class="button" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1822
-			print '</form>';
1823
-		}
1824
-		else
1825
-		{
1826
-			print $object->trueWeight;
1827
-			print ($object->trueWeight && $object->weight_units!='')?' '.measuring_units_string($object->weight_units,"weight"):'';
1828
-		}
1757
+        // Linked documents
1758
+        if ($typeobject == 'commande' && $object->$typeobject->id && ! empty($conf->commande->enabled))
1759
+        {
1760
+            print '<tr><td>';
1761
+            print $langs->trans("RefOrder").'</td>';
1762
+            print '<td colspan="3">';
1763
+            print $objectsrc->getNomUrl(1,'commande');
1764
+            print "</td>\n";
1765
+            print '</tr>';
1766
+        }
1767
+        if ($typeobject == 'propal' && $object->$typeobject->id && ! empty($conf->propal->enabled))
1768
+        {
1769
+            print '<tr><td>';
1770
+            print $langs->trans("RefProposal").'</td>';
1771
+            print '<td colspan="3">';
1772
+            print $objectsrc->getNomUrl(1,'expedition');
1773
+            print "</td>\n";
1774
+            print '</tr>';
1775
+        }
1776
+
1777
+        // Date creation
1778
+        print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
1779
+        print '<td colspan="3">'.dol_print_date($object->date_creation,"dayhour")."</td>\n";
1780
+        print '</tr>';
1781
+
1782
+        // Delivery date planned
1783
+        print '<tr><td height="10">';
1784
+        print '<table class="nobordernopadding" width="100%"><tr><td>';
1785
+        print $langs->trans('DateDeliveryPlanned');
1786
+        print '</td>';
1787
+
1788
+        if ($action != 'editdate_livraison') print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editdate_livraison&amp;id='.$object->id.'">'.img_edit($langs->trans('SetDeliveryDate'),1).'</a></td>';
1789
+        print '</tr></table>';
1790
+        print '</td><td colspan="2">';
1791
+        if ($action == 'editdate_livraison')
1792
+        {
1793
+            print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1794
+            print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1795
+            print '<input type="hidden" name="action" value="setdate_livraison">';
1796
+            print $form->selectDate($object->date_delivery?$object->date_delivery:-1, 'liv_', 1, 1, '', "setdate_livraison", 1, 0);
1797
+            print '<input type="submit" class="button" value="'.$langs->trans('Modify').'">';
1798
+            print '</form>';
1799
+        }
1800
+        else
1801
+        {
1802
+            print $object->date_delivery ? dol_print_date($object->date_delivery,'dayhour') : '&nbsp;';
1803
+        }
1804
+        print '</td>';
1805
+        print '</tr>';
1806
+
1807
+        // Weight
1808
+        print '<tr><td>';
1809
+        print $form->editfieldkey("Weight",'trueWeight',$object->trueWeight,$object,$user->rights->expedition->creer);
1810
+        print '</td><td colspan="3">';
1811
+
1812
+        if ($action=='edittrueWeight')
1813
+        {
1814
+            print '<form name="settrueweight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1815
+            print '<input name="action" value="settrueWeight" type="hidden">';
1816
+            print '<input name="id" value="'.$object->id.'" type="hidden">';
1817
+            print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1818
+            print '<input id="trueWeight" name="trueWeight" value="'.$object->trueWeight.'" type="text">';
1819
+            print $formproduct->select_measuring_units("weight_units","weight",$object->weight_units);
1820
+            print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1821
+            print ' <input class="button" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1822
+            print '</form>';
1823
+        }
1824
+        else
1825
+        {
1826
+            print $object->trueWeight;
1827
+            print ($object->trueWeight && $object->weight_units!='')?' '.measuring_units_string($object->weight_units,"weight"):'';
1828
+        }
1829 1829
 
1830 1830
         // Calculated
1831
-		if ($totalWeight > 0)
1832
-		{
1833
-			if (!empty($object->trueWeight)) print ' ('.$langs->trans("SumOfProductWeights").': ';
1834
-			//print $totalWeight.' '.measuring_units_string(0,"weight");
1835
-			print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND)?$conf->global->MAIN_WEIGHT_DEFAULT_ROUND:-1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT)?$conf->global->MAIN_WEIGHT_DEFAULT_UNIT:'no');
1836
-			//if (empty($object->trueWeight)) print ' ('.$langs->trans("Calculated").')';
1837
-			if (!empty($object->trueWeight)) print ')';
1838
-		}
1839
-		print '</td></tr>';
1840
-
1841
-		// Width
1842
-		print '<tr><td>'.$form->editfieldkey("Width",'trueWidth',$object->trueWidth,$object,$user->rights->expedition->creer).'</td><td colspan="3">';
1843
-		print $form->editfieldval("Width",'trueWidth',$object->trueWidth,$object,$user->rights->expedition->creer);
1844
-		print ($object->trueWidth && $object->width_units!='')?' '.measuring_units_string($object->width_units,"size"):'';
1845
-		print '</td></tr>';
1846
-
1847
-		// Height
1848
-		print '<tr><td>'.$form->editfieldkey("Height",'trueHeight',$object->trueHeight,$object,$user->rights->expedition->creer).'</td><td colspan="3">';
1849
-		if($action=='edittrueHeight')
1850
-		{
1851
-			print '<form name="settrueHeight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1852
-			print '<input name="action" value="settrueHeight" type="hidden">';
1853
-			print '<input name="id" value="'.$object->id.'" type="hidden">';
1854
-			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1855
-			print '<input id="trueHeight" name="trueHeight" value="'.$object->trueHeight.'" type="text">';
1856
-			print $formproduct->select_measuring_units("size_units","size",$object->size_units);
1857
-			print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1858
-			print ' <input class="button" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1859
-			print '</form>';
1860
-		}
1861
-		else
1862
-		{
1863
-			print $object->trueHeight;
1864
-			print ($object->trueHeight && $object->height_units!='')?' '.measuring_units_string($object->height_units,"size"):'';
1865
-		}
1866
-
1867
-		print '</td></tr>';
1868
-
1869
-		// Depth
1870
-		print '<tr><td>'.$form->editfieldkey("Depth",'trueDepth',$object->trueDepth,$object,$user->rights->expedition->creer).'</td><td colspan="3">';
1871
-		print $form->editfieldval("Depth",'trueDepth',$object->trueDepth,$object,$user->rights->expedition->creer);
1872
-		print ($object->trueDepth && $object->depth_units!='')?' '.measuring_units_string($object->depth_units,"size"):'';
1873
-		print '</td></tr>';
1874
-
1875
-		// Volume
1876
-		print '<tr><td>';
1877
-		print $langs->trans("Volume");
1878
-		print '</td>';
1879
-		print '<td colspan="3">';
1880
-		$calculatedVolume=0;
1881
-		$volumeUnit=0;
1882
-		if ($object->trueWidth && $object->trueHeight && $object->trueDepth)
1883
-		{
1884
-		    $calculatedVolume=($object->trueWidth * $object->trueHeight * $object->trueDepth);
1885
-		    $volumeUnit=$object->size_units * 3;
1886
-		}
1887
-		// If sending volume not defined we use sum of products
1888
-		if ($calculatedVolume > 0)
1889
-		{
1890
-			if ($volumeUnit < 50)
1891
-			{
1892
-			    //print $calculatedVolume.' '.measuring_units_string($volumeUnit,"volume");
1893
-			    print showDimensionInBestUnit($calculatedVolume, $volumeUnit, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND)?$conf->global->MAIN_VOLUME_DEFAULT_ROUND:-1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT)?$conf->global->MAIN_VOLUME_DEFAULT_UNIT:'no');
1894
-			}
1895
-			else print $calculatedVolume.' '.measuring_units_string($volumeUnit,"volume");
1896
-		}
1897
-		if ($totalVolume > 0)
1898
-		{
1899
-			if ($calculatedVolume) print ' ('.$langs->trans("SumOfProductVolumes").': ';
1900
-			//print $totalVolume.' '.measuring_units_string(0,"volume");
1901
-			print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND)?$conf->global->MAIN_VOLUME_DEFAULT_ROUND:-1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT)?$conf->global->MAIN_VOLUME_DEFAULT_UNIT:'no');
1902
-			//if (empty($calculatedVolume)) print ' ('.$langs->trans("Calculated").')';
1903
-			if ($calculatedVolume) print ')';
1904
-		}
1905
-		print "</td>\n";
1906
-		print '</tr>';
1907
-
1908
-		// Other attributes
1909
-		$cols = 2;
1910
-		include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
1911
-
1912
-		print '</table>';
1913
-
1914
-		print '</div>';
1915
-		print '<div class="fichehalfright">';
1916
-		print '<div class="ficheaddleft">';
1917
-		print '<div class="underbanner clearboth"></div>';
1918
-
1919
-		print '<table class="border centpercent">';
1920
-
1921
-		// Sending method
1922
-		print '<tr><td height="10">';
1923
-		print '<table class="nobordernopadding" width="100%"><tr><td>';
1924
-		print $langs->trans('SendingMethod');
1925
-		print '</td>';
1926
-
1927
-		if ($action != 'editshipping_method_id') print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editshipping_method_id&amp;id='.$object->id.'">'.img_edit($langs->trans('SetSendingMethod'),1).'</a></td>';
1928
-		print '</tr></table>';
1929
-		print '</td><td colspan="2">';
1930
-		if ($action == 'editshipping_method_id')
1931
-		{
1932
-			print '<form name="setshipping_method_id" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1933
-			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1934
-			print '<input type="hidden" name="action" value="setshipping_method_id">';
1935
-			$object->fetch_delivery_methods();
1936
-			print $form->selectarray("shipping_method_id",$object->meths,$object->shipping_method_id,1,0,0,"",1);
1937
-			if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
1938
-			print '<input type="submit" class="button" value="'.$langs->trans('Modify').'">';
1939
-			print '</form>';
1940
-		}
1941
-		else
1942
-		{
1943
-			if ($object->shipping_method_id > 0)
1944
-			{
1945
-				// Get code using getLabelFromKey
1946
-				$code=$langs->getLabelFromKey($db,$object->shipping_method_id,'c_shipment_mode','rowid','code');
1947
-				print $langs->trans("SendingMethod".strtoupper($code));
1948
-			}
1949
-		}
1950
-		print '</td>';
1951
-		print '</tr>';
1952
-
1953
-		// Tracking Number
1954
-		print '<tr><td class="titlefield">'.$form->editfieldkey("TrackingNumber",'tracking_number',$object->tracking_number,$object,$user->rights->expedition->creer).'</td><td colspan="3">';
1955
-		print $form->editfieldval("TrackingNumber",'tracking_number',$object->tracking_url,$object,$user->rights->expedition->creer,'string',$object->tracking_number);
1956
-		print '</td></tr>';
1957
-
1958
-		// Incoterms
1959
-		if (!empty($conf->incoterm->enabled))
1960
-		{
1961
-			print '<tr><td>';
1962
-	        print '<table width="100%" class="nobordernopadding"><tr><td>';
1963
-	        print $langs->trans('IncotermLabel');
1964
-	        print '<td><td align="right">';
1965
-	        if ($user->rights->expedition->creer) print '<a href="'.DOL_URL_ROOT.'/expedition/card.php?id='.$object->id.'&action=editincoterm">'.img_edit().'</a>';
1966
-	        else print '&nbsp;';
1967
-	        print '</td></tr></table>';
1968
-	        print '</td>';
1969
-	        print '<td colspan="3">';
1970
-			if ($action != 'editincoterm')
1971
-			{
1972
-				print $form->textwithpicto($object->display_incoterms(), $object->libelle_incoterms, 1);
1973
-			}
1974
-			else
1975
-			{
1976
-				print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''), $_SERVER['PHP_SELF'].'?id='.$object->id);
1977
-			}
1978
-	        print '</td></tr>';
1979
-		}
1980
-
1981
-		print "</table>";
1982
-
1983
-		print '</div>';
1984
-		print '</div>';
1985
-		print '</div>';
1986
-
1987
-		print '<div class="clearboth"></div>';
1988
-
1989
-
1990
-		// Lines of products
1991
-
1992
-		if ($action == 'editline')
1993
-		{
1994
-			print '	<form name="updateline" id="updateline" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;lineid=' . $line_id . '" method="POST">
1831
+        if ($totalWeight > 0)
1832
+        {
1833
+            if (!empty($object->trueWeight)) print ' ('.$langs->trans("SumOfProductWeights").': ';
1834
+            //print $totalWeight.' '.measuring_units_string(0,"weight");
1835
+            print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND)?$conf->global->MAIN_WEIGHT_DEFAULT_ROUND:-1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT)?$conf->global->MAIN_WEIGHT_DEFAULT_UNIT:'no');
1836
+            //if (empty($object->trueWeight)) print ' ('.$langs->trans("Calculated").')';
1837
+            if (!empty($object->trueWeight)) print ')';
1838
+        }
1839
+        print '</td></tr>';
1840
+
1841
+        // Width
1842
+        print '<tr><td>'.$form->editfieldkey("Width",'trueWidth',$object->trueWidth,$object,$user->rights->expedition->creer).'</td><td colspan="3">';
1843
+        print $form->editfieldval("Width",'trueWidth',$object->trueWidth,$object,$user->rights->expedition->creer);
1844
+        print ($object->trueWidth && $object->width_units!='')?' '.measuring_units_string($object->width_units,"size"):'';
1845
+        print '</td></tr>';
1846
+
1847
+        // Height
1848
+        print '<tr><td>'.$form->editfieldkey("Height",'trueHeight',$object->trueHeight,$object,$user->rights->expedition->creer).'</td><td colspan="3">';
1849
+        if($action=='edittrueHeight')
1850
+        {
1851
+            print '<form name="settrueHeight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1852
+            print '<input name="action" value="settrueHeight" type="hidden">';
1853
+            print '<input name="id" value="'.$object->id.'" type="hidden">';
1854
+            print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1855
+            print '<input id="trueHeight" name="trueHeight" value="'.$object->trueHeight.'" type="text">';
1856
+            print $formproduct->select_measuring_units("size_units","size",$object->size_units);
1857
+            print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1858
+            print ' <input class="button" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1859
+            print '</form>';
1860
+        }
1861
+        else
1862
+        {
1863
+            print $object->trueHeight;
1864
+            print ($object->trueHeight && $object->height_units!='')?' '.measuring_units_string($object->height_units,"size"):'';
1865
+        }
1866
+
1867
+        print '</td></tr>';
1868
+
1869
+        // Depth
1870
+        print '<tr><td>'.$form->editfieldkey("Depth",'trueDepth',$object->trueDepth,$object,$user->rights->expedition->creer).'</td><td colspan="3">';
1871
+        print $form->editfieldval("Depth",'trueDepth',$object->trueDepth,$object,$user->rights->expedition->creer);
1872
+        print ($object->trueDepth && $object->depth_units!='')?' '.measuring_units_string($object->depth_units,"size"):'';
1873
+        print '</td></tr>';
1874
+
1875
+        // Volume
1876
+        print '<tr><td>';
1877
+        print $langs->trans("Volume");
1878
+        print '</td>';
1879
+        print '<td colspan="3">';
1880
+        $calculatedVolume=0;
1881
+        $volumeUnit=0;
1882
+        if ($object->trueWidth && $object->trueHeight && $object->trueDepth)
1883
+        {
1884
+            $calculatedVolume=($object->trueWidth * $object->trueHeight * $object->trueDepth);
1885
+            $volumeUnit=$object->size_units * 3;
1886
+        }
1887
+        // If sending volume not defined we use sum of products
1888
+        if ($calculatedVolume > 0)
1889
+        {
1890
+            if ($volumeUnit < 50)
1891
+            {
1892
+                //print $calculatedVolume.' '.measuring_units_string($volumeUnit,"volume");
1893
+                print showDimensionInBestUnit($calculatedVolume, $volumeUnit, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND)?$conf->global->MAIN_VOLUME_DEFAULT_ROUND:-1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT)?$conf->global->MAIN_VOLUME_DEFAULT_UNIT:'no');
1894
+            }
1895
+            else print $calculatedVolume.' '.measuring_units_string($volumeUnit,"volume");
1896
+        }
1897
+        if ($totalVolume > 0)
1898
+        {
1899
+            if ($calculatedVolume) print ' ('.$langs->trans("SumOfProductVolumes").': ';
1900
+            //print $totalVolume.' '.measuring_units_string(0,"volume");
1901
+            print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND)?$conf->global->MAIN_VOLUME_DEFAULT_ROUND:-1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT)?$conf->global->MAIN_VOLUME_DEFAULT_UNIT:'no');
1902
+            //if (empty($calculatedVolume)) print ' ('.$langs->trans("Calculated").')';
1903
+            if ($calculatedVolume) print ')';
1904
+        }
1905
+        print "</td>\n";
1906
+        print '</tr>';
1907
+
1908
+        // Other attributes
1909
+        $cols = 2;
1910
+        include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
1911
+
1912
+        print '</table>';
1913
+
1914
+        print '</div>';
1915
+        print '<div class="fichehalfright">';
1916
+        print '<div class="ficheaddleft">';
1917
+        print '<div class="underbanner clearboth"></div>';
1918
+
1919
+        print '<table class="border centpercent">';
1920
+
1921
+        // Sending method
1922
+        print '<tr><td height="10">';
1923
+        print '<table class="nobordernopadding" width="100%"><tr><td>';
1924
+        print $langs->trans('SendingMethod');
1925
+        print '</td>';
1926
+
1927
+        if ($action != 'editshipping_method_id') print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editshipping_method_id&amp;id='.$object->id.'">'.img_edit($langs->trans('SetSendingMethod'),1).'</a></td>';
1928
+        print '</tr></table>';
1929
+        print '</td><td colspan="2">';
1930
+        if ($action == 'editshipping_method_id')
1931
+        {
1932
+            print '<form name="setshipping_method_id" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1933
+            print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1934
+            print '<input type="hidden" name="action" value="setshipping_method_id">';
1935
+            $object->fetch_delivery_methods();
1936
+            print $form->selectarray("shipping_method_id",$object->meths,$object->shipping_method_id,1,0,0,"",1);
1937
+            if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
1938
+            print '<input type="submit" class="button" value="'.$langs->trans('Modify').'">';
1939
+            print '</form>';
1940
+        }
1941
+        else
1942
+        {
1943
+            if ($object->shipping_method_id > 0)
1944
+            {
1945
+                // Get code using getLabelFromKey
1946
+                $code=$langs->getLabelFromKey($db,$object->shipping_method_id,'c_shipment_mode','rowid','code');
1947
+                print $langs->trans("SendingMethod".strtoupper($code));
1948
+            }
1949
+        }
1950
+        print '</td>';
1951
+        print '</tr>';
1952
+
1953
+        // Tracking Number
1954
+        print '<tr><td class="titlefield">'.$form->editfieldkey("TrackingNumber",'tracking_number',$object->tracking_number,$object,$user->rights->expedition->creer).'</td><td colspan="3">';
1955
+        print $form->editfieldval("TrackingNumber",'tracking_number',$object->tracking_url,$object,$user->rights->expedition->creer,'string',$object->tracking_number);
1956
+        print '</td></tr>';
1957
+
1958
+        // Incoterms
1959
+        if (!empty($conf->incoterm->enabled))
1960
+        {
1961
+            print '<tr><td>';
1962
+            print '<table width="100%" class="nobordernopadding"><tr><td>';
1963
+            print $langs->trans('IncotermLabel');
1964
+            print '<td><td align="right">';
1965
+            if ($user->rights->expedition->creer) print '<a href="'.DOL_URL_ROOT.'/expedition/card.php?id='.$object->id.'&action=editincoterm">'.img_edit().'</a>';
1966
+            else print '&nbsp;';
1967
+            print '</td></tr></table>';
1968
+            print '</td>';
1969
+            print '<td colspan="3">';
1970
+            if ($action != 'editincoterm')
1971
+            {
1972
+                print $form->textwithpicto($object->display_incoterms(), $object->libelle_incoterms, 1);
1973
+            }
1974
+            else
1975
+            {
1976
+                print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''), $_SERVER['PHP_SELF'].'?id='.$object->id);
1977
+            }
1978
+            print '</td></tr>';
1979
+        }
1980
+
1981
+        print "</table>";
1982
+
1983
+        print '</div>';
1984
+        print '</div>';
1985
+        print '</div>';
1986
+
1987
+        print '<div class="clearboth"></div>';
1988
+
1989
+
1990
+        // Lines of products
1991
+
1992
+        if ($action == 'editline')
1993
+        {
1994
+            print '	<form name="updateline" id="updateline" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;lineid=' . $line_id . '" method="POST">
1995 1995
 			<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">
1996 1996
 			<input type="hidden" name="action" value="updateline">
1997 1997
 			<input type="hidden" name="mode" value="">
1998 1998
 			<input type="hidden" name="id" value="' . $object->id . '">
1999 1999
 			';
2000
-		}
2001
-		print '<br>';
2000
+        }
2001
+        print '<br>';
2002 2002
 
2003 2003
         print '<div class="div-table-responsive-no-min">';
2004
-		print '<table class="noborder" width="100%">';
2005
-		print '<tr class="liste_titre">';
2006
-		// Adds a line numbering column
2007
-		if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER))
2008
-		{
2009
-			print '<td width="5" align="center">&nbsp;</td>';
2010
-		}
2011
-		// Product/Service
2012
-		print '<td>'.$langs->trans("Products").'</td>';
2013
-		// Qty
2014
-		print '<td align="center">'.$langs->trans("QtyOrdered").'</td>';
2015
-		if ($origin && $origin_id > 0)
2016
-		{
2017
-			print '<td align="center">'.$langs->trans("QtyInOtherShipments").'</td>';
2018
-		}
2019
-		if ($action == 'editline')
2020
-		{
2021
-			$editColspan = 3;
2022
-			if (empty($conf->stock->enabled)) $editColspan--;
2023
-			if (empty($conf->productbatch->enabled)) $editColspan--;
2024
-			print '<td align="center" colspan="'. $editColspan . '">';
2025
-			if ($object->statut <= 1)
2026
-			{
2027
-				print $langs->trans("QtyToShip").' - ';
2028
-			}
2029
-			else
2030
-			{
2031
-				print $langs->trans("QtyShipped").' - ';
2032
-			}
2033
-			if (! empty($conf->stock->enabled))
2034
-			{
2035
-				print $langs->trans("WarehouseSource").' - ';
2036
-			}
2037
-			if (! empty($conf->productbatch->enabled))
2038
-			{
2039
-				print $langs->trans("Batch");
2040
-			}
2041
-			print '</td>';
2042
-		}
2043
-		else
2044
-		{
2045
-			if ($object->statut <= 1)
2046
-			{
2047
-				print '<td align="center">'.$langs->trans("QtyToShip").'</td>';
2048
-			}
2049
-			else
2050
-			{
2051
-				print '<td align="center">'.$langs->trans("QtyShipped").'</td>';
2052
-			}
2053
-			if (! empty($conf->stock->enabled))
2054
-			{
2055
-				print '<td align="left">'.$langs->trans("WarehouseSource").'</td>';
2056
-			}
2057
-
2058
-			if (! empty($conf->productbatch->enabled))
2059
-			{
2060
-				print '<td align="left">'.$langs->trans("Batch").'</td>';
2061
-			}
2062
-		}
2063
-		print '<td align="center">'.$langs->trans("CalculatedWeight").'</td>';
2064
-		print '<td align="center">'.$langs->trans("CalculatedVolume").'</td>';
2065
-		//print '<td align="center">'.$langs->trans("Size").'</td>';
2066
-		if ($object->statut == 0)
2067
-		{
2068
-			print '<td class="linecoledit"></td>';
2069
-			print '<td class="linecoldelete" width="10"></td>';
2070
-		}
2071
-		print "</tr>\n";
2072
-
2073
-		$var=false;
2074
-
2075
-		if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
2076
-		{
2077
-			$object->fetch_thirdparty();
2078
-			$outputlangs = $langs;
2079
-			$newlang='';
2080
-			if (empty($newlang) && GETPOST('lang_id','aZ09')) $newlang=GETPOST('lang_id','aZ09');
2081
-			if (empty($newlang)) $newlang=$object->thirdparty->default_lang;
2082
-			if (! empty($newlang))
2083
-			{
2084
-				$outputlangs = new Translate("",$conf);
2085
-				$outputlangs->setDefaultLang($newlang);
2086
-			}
2087
-		}
2088
-
2089
-		// Get list of products already sent for same source object into $alreadysent
2090
-		$alreadysent = array();
2091
-		if ($origin && $origin_id > 0)
2092
-		{
2093
-    		$sql = "SELECT obj.rowid, obj.fk_product, obj.label, obj.description, obj.product_type as fk_product_type, obj.qty as qty_asked, obj.date_start, obj.date_end";
2094
-    		$sql.= ", ed.rowid as shipmentline_id, ed.qty as qty_shipped, ed.fk_expedition as expedition_id, ed.fk_origin_line, ed.fk_entrepot";
2095
-    		$sql.= ", e.rowid as shipment_id, e.ref as shipment_ref, e.date_creation, e.date_valid, e.date_delivery, e.date_expedition";
2096
-    		//if ($conf->livraison_bon->enabled) $sql .= ", l.rowid as livraison_id, l.ref as livraison_ref, l.date_delivery, ld.qty as qty_received";
2097
-    		$sql.= ', p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.tobatch as product_tobatch';
2098
-    		$sql.= ', p.description as product_desc';
2099
-    		$sql.= " FROM ".MAIN_DB_PREFIX."expeditiondet as ed";
2100
-    		$sql.= ", ".MAIN_DB_PREFIX."expedition as e";
2101
-    		$sql.= ", ".MAIN_DB_PREFIX.$origin."det as obj";
2102
-    		//if ($conf->livraison_bon->enabled) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."livraison as l ON l.fk_expedition = e.rowid LEFT JOIN ".MAIN_DB_PREFIX."livraisondet as ld ON ld.fk_livraison = l.rowid  AND obj.rowid = ld.fk_origin_line";
2103
-    		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON obj.fk_product = p.rowid";
2104
-    		$sql.= " WHERE e.entity IN (".getEntity('expedition').")";
2105
-    		$sql.= " AND obj.fk_".$origin." = ".$origin_id;
2106
-    		$sql.= " AND obj.rowid = ed.fk_origin_line";
2107
-    		$sql.= " AND ed.fk_expedition = e.rowid";
2108
-    		//if ($filter) $sql.= $filter;
2109
-    		$sql.= " ORDER BY obj.fk_product";
2110
-
2111
-    		dol_syslog("get list of shipment lines", LOG_DEBUG);
2112
-    		$resql = $db->query($sql);
2113
-    		if ($resql)
2114
-    		{
2115
-    		    $num = $db->num_rows($resql);
2116
-    		    $i = 0;
2117
-
2118
-    		    while($i < $num)
2119
-    		    {
2120
-        		    $obj = $db->fetch_object($resql);
2121
-        		    if ($obj)
2122
-        		    {
2123
-        		        // $obj->rowid is rowid in $origin."det" table
2124
-        		        $alreadysent[$obj->rowid][$obj->shipmentline_id]=array('shipment_ref'=>$obj->shipment_ref, 'shipment_id'=>$obj->shipment_id, 'warehouse'=>$obj->fk_entrepot, 'qty_shipped'=>$obj->qty_shipped, 'date_valid'=>$obj->date_valid, 'date_delivery'=>$obj->date_delivery);
2125
-        		    }
2126
-        		    $i++;
2127
-    		    }
2128
-    		}
2129
-    		//var_dump($alreadysent);
2130
-		}
2131
-
2132
-		// Loop on each product to send/sent
2133
-		for ($i = 0 ; $i < $num_prod ; $i++)
2134
-		{
2135
-		    print '<!-- origin line id = '.$lines[$i]->origin_line_id.' -->'; // id of order line
2136
-			print '<tr class="oddeven">';
2137
-
2138
-			// Adds a line numbering column
2139
-			if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER))
2140
-			{
2141
-				print '<td align="center">'.($i+1).'</td>';
2142
-			}
2143
-
2144
-			// Predefined product or service
2145
-			if ($lines[$i]->fk_product > 0)
2146
-			{
2147
-				// Define output language
2148
-				if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
2149
-				{
2150
-					$prod = new Product($db);
2151
-					$prod->fetch($lines[$i]->fk_product);
2152
-					$label = ( ! empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product_label;
2153
-				}
2154
-				else
2155
-					$label = (! empty($lines[$i]->label)?$lines[$i]->label:$lines[$i]->product_label);
2156
-
2157
-				print '<td>';
2158
-
2159
-				// Show product and description
2160
-				$product_static->type=$lines[$i]->fk_product_type;
2161
-				$product_static->id=$lines[$i]->fk_product;
2162
-				$product_static->ref=$lines[$i]->ref;
2163
-				$product_static->status_batch=$lines[$i]->product_tobatch;
2164
-				$text=$product_static->getNomUrl(1);
2165
-				$text.= ' - '.$label;
2166
-				$description=(! empty($conf->global->PRODUIT_DESC_IN_FORM)?'':dol_htmlentitiesbr($lines[$i]->description));
2167
-				print $form->textwithtooltip($text,$description,3,'','',$i);
2168
-				print_date_range($lines[$i]->date_start,$lines[$i]->date_end);
2169
-				if (! empty($conf->global->PRODUIT_DESC_IN_FORM))
2170
-				{
2171
-					print (! empty($lines[$i]->description) && $lines[$i]->description!=$lines[$i]->product)?'<br>'.dol_htmlentitiesbr($lines[$i]->description):'';
2172
-				}
2173
-				print "</td>\n";
2174
-			}
2175
-			else
2176
-			{
2177
-				print "<td>";
2178
-				if ($lines[$i]->product_type == Product::TYPE_SERVICE) $text = img_object($langs->trans('Service'),'service');
2179
-				else $text = img_object($langs->trans('Product'),'product');
2180
-
2181
-				if (! empty($lines[$i]->label)) {
2182
-					$text.= ' <strong>'.$lines[$i]->label.'</strong>';
2183
-					print $form->textwithtooltip($text,$lines[$i]->description,3,'','',$i);
2184
-				} else {
2185
-					print $text.' '.nl2br($lines[$i]->description);
2186
-				}
2187
-
2188
-				print_date_range($lines[$i]->date_start,$lines[$i]->date_end);
2189
-				print "</td>\n";
2190
-			}
2191
-
2192
-			// Qty ordered
2193
-			print '<td align="center">'.$lines[$i]->qty_asked.'</td>';
2194
-
2195
-			// Qty in other shipments (with shipment and warehouse used)
2196
-    		if ($origin && $origin_id > 0)
2197
-    		{
2198
-    			print '<td align="center" class="nowrap">';
2199
-    			foreach ($alreadysent as $key => $val)
2200
-    			{
2201
-    			    if ($lines[$i]->fk_origin_line == $key)
2202
-    			    {
2203
-    			        $j = 0;
2204
-    			        foreach($val as $shipmentline_id=> $shipmentline_var)
2205
-    			        {
2206
-    			            if ($shipmentline_var['shipment_id'] == $lines[$i]->fk_expedition) continue; // We want to show only "other shipments"
2207
-
2208
-    			            $j++;
2209
-    			            if ($j > 1) print '<br>';
2210
-    			            $shipment_static->fetch($shipmentline_var['shipment_id']);
2211
-    			            print $shipment_static->getNomUrl(1);
2212
-    			            print ' - '.$shipmentline_var['qty_shipped'];
2213
-    			            $htmltext=$langs->trans("DateValidation").' : '.(empty($shipmentline_var['date_valid'])?$langs->trans("Draft"):dol_print_date($shipmentline_var['date_valid'], 'dayhour'));
2214
-    			            if (! empty($conf->stock->enabled) && $shipmentline_var['warehouse'] > 0)
2215
-    			            {
2216
-    			                $warehousestatic->fetch($shipmentline_var['warehouse']);
2217
-    			                $htmltext .= '<br>'.$langs->trans("From").' : '.$warehousestatic->getNomUrl(1);
2218
-    			            }
2219
-    			            print ' '.$form->textwithpicto('', $htmltext, 1);
2220
-    			        }
2221
-    			    }
2222
-    			}
2223
-    		}
2224
-			print '</td>';
2225
-
2226
-			if ($action == 'editline' && $lines[$i]->id == $line_id)
2227
-			{
2228
-				// edit mode
2229
-				print '<td colspan="'.$editColspan.'" align="center"><table class="nobordernopadding">';
2230
-				if (is_array($lines[$i]->detail_batch) && count($lines[$i]->detail_batch) > 0)
2231
-				{
2232
-					print '<!-- case edit 1 -->';
2233
-					$line = new ExpeditionLigne($db);
2234
-					foreach ($lines[$i]->detail_batch as $detail_batch)
2235
-					{
2236
-						print '<tr>';
2237
-						// Qty to ship or shipped
2238
-						print '<td>' . '<input name="qtyl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->id.'" id="qtyl'.$line_id.'_'.$detail_batch->id.'" type="text" size="4" value="'.$detail_batch->qty.'">' . '</td>';
2239
-						// Batch number managment
2240
-						if ($lines[$i]->entrepot_id == 0)
2241
-						{
2242
-							// only show lot numbers from src warehouse when shipping from multiple warehouses
2243
-							$line->fetch($detail_batch->fk_expeditiondet);
2244
-						}
2245
-						print '<td>' . $formproduct->selectLotStock($detail_batch->fk_origin_stock, 'batchl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->fk_origin_stock, '', 1, 0, $lines[$i]->fk_product, $line->entrepot_id). '</td>';
2246
-						print '</tr>';
2247
-					}
2248
-					// add a 0 qty lot row to be able to add a lot
2249
-					print '<tr>';
2250
-					// Qty to ship or shipped
2251
-					print '<td>' . '<input name="qtyl'.$line_id.'_0" id="qtyl'.$line_id.'_0" type="text" size="4" value="0">' . '</td>';
2252
-					// Batch number managment
2253
-					print '<td>' . $formproduct->selectLotStock('', 'batchl'.$line_id.'_0', '', 1, 0, $lines[$i]->fk_product). '</td>';
2254
-					print '</tr>';
2255
-				}
2256
-				else if (! empty($conf->stock->enabled))
2257
-				{
2258
-					if ($lines[$i]->fk_product > 0)
2259
-					{
2260
-						if ($lines[$i]->entrepot_id > 0)
2261
-						{
2262
-							print '<!-- case edit 2 -->';
2263
-							print '<tr>';
2264
-							// Qty to ship or shipped
2265
-							print '<td>' . '<input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty_shipped.'">' . '</td>';
2266
-							// Warehouse source
2267
-							print '<td>' . $formproduct->selectWarehouses($lines[$i]->entrepot_id, 'entl'.$line_id, '', 1, 0, $lines[$i]->fk_product, '', 1). '</td>';
2268
-							// Batch number managment
2269
-							print '<td> - ' . $langs->trans("NA") . '</td>';
2270
-							print '</tr>';
2271
-						}
2272
-						else if (count($lines[$i]->details_entrepot) > 1)
2273
-						{
2274
-							print '<!-- case edit 3 -->';
2275
-							foreach ($lines[$i]->details_entrepot as $detail_entrepot)
2276
-							{
2277
-								print '<tr>';
2278
-								// Qty to ship or shipped
2279
-								print '<td>' . '<input name="qtyl'.$detail_entrepot->line_id.'" id="qtyl'.$detail_entrepot->line_id.'" type="text" size="4" value="'.$detail_entrepot->qty_shipped.'">' . '</td>';
2280
-								// Warehouse source
2281
-								print '<td>' . $formproduct->selectWarehouses($detail_entrepot->entrepot_id, 'entl'.$detail_entrepot->line_id, '', 1, 0, $lines[$i]->fk_product, '', 1) . '</td>';
2282
-								// Batch number managment
2283
-								print '<td> - ' . $langs->trans("NA") . '</td>';
2284
-								print '</tr>';
2285
-							}
2286
-						}
2287
-						else
2288
-						{
2289
-							print '<!-- case edit 4 -->';
2290
-							print '<tr><td colspan="3">'.$langs->trans("NotEnoughStock").'</td></tr>';
2291
-						}
2292
-					}
2293
-					else
2294
-					{
2295
-						print '<!-- case edit 5 -->';
2296
-						print '<tr>';
2297
-						// Qty to ship or shipped
2298
-						print '<td>' . '<input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty_shipped.'">' . '</td>';
2299
-						// Warehouse source
2300
-						print '<td>' . '</td>';
2301
-						// Batch number managment
2302
-						print '<td>' . '</td>';
2303
-						print '</tr>';
2304
-					}
2305
-				}
2306
-				print '</table></td>';
2307
-			}
2308
-			else
2309
-			{
2310
-				// Qty to ship or shipped
2311
-				print '<td align="center">'.$lines[$i]->qty_shipped.'</td>';
2312
-
2313
-				// Warehouse source
2314
-				if (! empty($conf->stock->enabled))
2315
-				{
2316
-					print '<td align="left">';
2317
-					if ($lines[$i]->entrepot_id > 0)
2318
-					{
2319
-						$entrepot = new Entrepot($db);
2320
-						$entrepot->fetch($lines[$i]->entrepot_id);
2321
-						print $entrepot->getNomUrl(1);
2322
-					}
2323
-					else if (count($lines[$i]->details_entrepot) > 1)
2324
-					{
2325
-						$detail = '';
2326
-						foreach ($lines[$i]->details_entrepot as $detail_entrepot)
2327
-						{
2328
-							if ($detail_entrepot->entrepot_id > 0)
2329
-							{
2330
-								$entrepot = new Entrepot($db);
2331
-								$entrepot->fetch($detail_entrepot->entrepot_id);
2332
-								$detail.= $langs->trans("DetailWarehouseFormat",$entrepot->libelle,$detail_entrepot->qty_shipped).'<br/>';
2333
-							}
2334
-						}
2335
-						print $form->textwithtooltip(img_picto('', 'object_stock').' '.$langs->trans("DetailWarehouseNumber"),$detail);
2336
-					}
2337
-					print '</td>';
2338
-				}
2339
-
2340
-				// Batch number managment
2341
-				if (! empty($conf->productbatch->enabled))
2342
-				{
2343
-					if (isset($lines[$i]->detail_batch))
2344
-					{
2345
-						print '<!-- Detail of lot -->';
2346
-						print '<td>';
2347
-						if ($lines[$i]->product_tobatch)
2348
-						{
2349
-							$detail = '';
2350
-							foreach ($lines[$i]->detail_batch as $dbatch)	// $dbatch is instance of ExpeditionLineBatch
2351
-							{
2352
-								$detail.= $langs->trans("Batch").': '.$dbatch->batch;
2353
-								$detail.= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby,"day");
2354
-								$detail.= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby,"day");
2355
-								$detail.= ' - '.$langs->trans("Qty").': '.$dbatch->qty;
2356
-								$detail.= '<br>';
2357
-							}
2358
-							print $form->textwithtooltip(img_picto('', 'object_barcode').' '.$langs->trans("DetailBatchNumber"),$detail);
2359
-						}
2360
-						else
2361
-						{
2362
-							print $langs->trans("NA");
2363
-						}
2364
-						print '</td>';
2365
-					} else {
2366
-						print '<td></td>';
2367
-					}
2368
-				}
2369
-			}
2370
-
2371
-			// Weight
2372
-			print '<td align="center">';
2373
-			if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) print $lines[$i]->weight*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->weight_units,"weight");
2374
-			else print '&nbsp;';
2375
-			print '</td>';
2376
-
2377
-			// Volume
2378
-			print '<td align="center">';
2379
-			if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) print $lines[$i]->volume*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->volume_units,"volume");
2380
-			else print '&nbsp;';
2381
-			print '</td>';
2382
-
2383
-			// Size
2384
-			//print '<td align="center">'.$lines[$i]->volume*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->volume_units,"volume").'</td>';
2385
-
2386
-			if ($action == 'editline' && $lines[$i]->id == $line_id)
2387
-			{
2388
-				print '<td align="center" colspan="2" valign="middle">';
2389
-				print '<input type="submit" class="button" id="savelinebutton" name="save" value="' . $langs->trans("Save") . '"><br>';
2390
-				print '<input type="submit" class="button" id="cancellinebutton" name="cancel" value="' . $langs->trans("Cancel") . '"><br>';
2391
-			}
2392
-			else if ($object->statut == 0)
2393
-			{
2394
-				// edit-delete buttons
2395
-				print '<td class="linecoledit" align="center">';
2396
-				print '<a href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=editline&amp;lineid=' . $lines[$i]->id . '">' . img_edit() . '</a>';
2397
-				print '</td>';
2398
-				print '<td class="linecoldelete" width="10">';
2399
-				print '<a href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=deleteline&amp;lineid=' . $lines[$i]->id . '">' . img_delete() . '</a>';
2400
-				print '</td>';
2401
-
2402
-				// Display lines extrafields
2403
-				if (! empty($rowExtrafieldsStart))
2404
-				{
2405
-					print $rowExtrafieldsStart;
2406
-					print $rowExtrafieldsView;
2407
-					print $rowEnd;
2408
-				}
2409
-			}
2410
-			print "</tr>";
2411
-
2412
-			// Display lines extrafields
2413
-			if (is_array($extralabelslines) && count($extralabelslines)>0) {
2414
-				$colspan= empty($conf->productbatch->enabled) ? 5 : 6;
2415
-				$line = new ExpeditionLigne($db);
2416
-				$line->fetch_optionals($lines[$i]->id);
2417
-				print '<tr class="oddeven">';
2418
-				if ($action == 'editline' && $lines[$i]->id == $line_id)
2419
-				{
2420
-					print $line->showOptionals($extrafieldsline, 'edit', array('style'=>$bc[$var], 'colspan'=>$colspan),$indiceAsked);
2421
-				}
2422
-				else
2423
-				{
2424
-					print $line->showOptionals($extrafieldsline, 'view', array('style'=>$bc[$var], 'colspan'=>$colspan),$indiceAsked);
2425
-				}
2426
-				print '</tr>';
2427
-			}
2428
-		}
2429
-
2430
-		// TODO Show also lines ordered but not delivered
2431
-
2432
-		print "</table>\n";
2433
-		print '</div>';
2434
-	}
2435
-
2436
-
2437
-	dol_fiche_end();
2438
-
2439
-
2440
-	$object->fetchObjectLinked($object->id,$object->element);
2441
-
2442
-
2443
-	/*
2004
+        print '<table class="noborder" width="100%">';
2005
+        print '<tr class="liste_titre">';
2006
+        // Adds a line numbering column
2007
+        if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER))
2008
+        {
2009
+            print '<td width="5" align="center">&nbsp;</td>';
2010
+        }
2011
+        // Product/Service
2012
+        print '<td>'.$langs->trans("Products").'</td>';
2013
+        // Qty
2014
+        print '<td align="center">'.$langs->trans("QtyOrdered").'</td>';
2015
+        if ($origin && $origin_id > 0)
2016
+        {
2017
+            print '<td align="center">'.$langs->trans("QtyInOtherShipments").'</td>';
2018
+        }
2019
+        if ($action == 'editline')
2020
+        {
2021
+            $editColspan = 3;
2022
+            if (empty($conf->stock->enabled)) $editColspan--;
2023
+            if (empty($conf->productbatch->enabled)) $editColspan--;
2024
+            print '<td align="center" colspan="'. $editColspan . '">';
2025
+            if ($object->statut <= 1)
2026
+            {
2027
+                print $langs->trans("QtyToShip").' - ';
2028
+            }
2029
+            else
2030
+            {
2031
+                print $langs->trans("QtyShipped").' - ';
2032
+            }
2033
+            if (! empty($conf->stock->enabled))
2034
+            {
2035
+                print $langs->trans("WarehouseSource").' - ';
2036
+            }
2037
+            if (! empty($conf->productbatch->enabled))
2038
+            {
2039
+                print $langs->trans("Batch");
2040
+            }
2041
+            print '</td>';
2042
+        }
2043
+        else
2044
+        {
2045
+            if ($object->statut <= 1)
2046
+            {
2047
+                print '<td align="center">'.$langs->trans("QtyToShip").'</td>';
2048
+            }
2049
+            else
2050
+            {
2051
+                print '<td align="center">'.$langs->trans("QtyShipped").'</td>';
2052
+            }
2053
+            if (! empty($conf->stock->enabled))
2054
+            {
2055
+                print '<td align="left">'.$langs->trans("WarehouseSource").'</td>';
2056
+            }
2057
+
2058
+            if (! empty($conf->productbatch->enabled))
2059
+            {
2060
+                print '<td align="left">'.$langs->trans("Batch").'</td>';
2061
+            }
2062
+        }
2063
+        print '<td align="center">'.$langs->trans("CalculatedWeight").'</td>';
2064
+        print '<td align="center">'.$langs->trans("CalculatedVolume").'</td>';
2065
+        //print '<td align="center">'.$langs->trans("Size").'</td>';
2066
+        if ($object->statut == 0)
2067
+        {
2068
+            print '<td class="linecoledit"></td>';
2069
+            print '<td class="linecoldelete" width="10"></td>';
2070
+        }
2071
+        print "</tr>\n";
2072
+
2073
+        $var=false;
2074
+
2075
+        if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
2076
+        {
2077
+            $object->fetch_thirdparty();
2078
+            $outputlangs = $langs;
2079
+            $newlang='';
2080
+            if (empty($newlang) && GETPOST('lang_id','aZ09')) $newlang=GETPOST('lang_id','aZ09');
2081
+            if (empty($newlang)) $newlang=$object->thirdparty->default_lang;
2082
+            if (! empty($newlang))
2083
+            {
2084
+                $outputlangs = new Translate("",$conf);
2085
+                $outputlangs->setDefaultLang($newlang);
2086
+            }
2087
+        }
2088
+
2089
+        // Get list of products already sent for same source object into $alreadysent
2090
+        $alreadysent = array();
2091
+        if ($origin && $origin_id > 0)
2092
+        {
2093
+            $sql = "SELECT obj.rowid, obj.fk_product, obj.label, obj.description, obj.product_type as fk_product_type, obj.qty as qty_asked, obj.date_start, obj.date_end";
2094
+            $sql.= ", ed.rowid as shipmentline_id, ed.qty as qty_shipped, ed.fk_expedition as expedition_id, ed.fk_origin_line, ed.fk_entrepot";
2095
+            $sql.= ", e.rowid as shipment_id, e.ref as shipment_ref, e.date_creation, e.date_valid, e.date_delivery, e.date_expedition";
2096
+            //if ($conf->livraison_bon->enabled) $sql .= ", l.rowid as livraison_id, l.ref as livraison_ref, l.date_delivery, ld.qty as qty_received";
2097
+            $sql.= ', p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.tobatch as product_tobatch';
2098
+            $sql.= ', p.description as product_desc';
2099
+            $sql.= " FROM ".MAIN_DB_PREFIX."expeditiondet as ed";
2100
+            $sql.= ", ".MAIN_DB_PREFIX."expedition as e";
2101
+            $sql.= ", ".MAIN_DB_PREFIX.$origin."det as obj";
2102
+            //if ($conf->livraison_bon->enabled) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."livraison as l ON l.fk_expedition = e.rowid LEFT JOIN ".MAIN_DB_PREFIX."livraisondet as ld ON ld.fk_livraison = l.rowid  AND obj.rowid = ld.fk_origin_line";
2103
+            $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON obj.fk_product = p.rowid";
2104
+            $sql.= " WHERE e.entity IN (".getEntity('expedition').")";
2105
+            $sql.= " AND obj.fk_".$origin." = ".$origin_id;
2106
+            $sql.= " AND obj.rowid = ed.fk_origin_line";
2107
+            $sql.= " AND ed.fk_expedition = e.rowid";
2108
+            //if ($filter) $sql.= $filter;
2109
+            $sql.= " ORDER BY obj.fk_product";
2110
+
2111
+            dol_syslog("get list of shipment lines", LOG_DEBUG);
2112
+            $resql = $db->query($sql);
2113
+            if ($resql)
2114
+            {
2115
+                $num = $db->num_rows($resql);
2116
+                $i = 0;
2117
+
2118
+                while($i < $num)
2119
+                {
2120
+                    $obj = $db->fetch_object($resql);
2121
+                    if ($obj)
2122
+                    {
2123
+                        // $obj->rowid is rowid in $origin."det" table
2124
+                        $alreadysent[$obj->rowid][$obj->shipmentline_id]=array('shipment_ref'=>$obj->shipment_ref, 'shipment_id'=>$obj->shipment_id, 'warehouse'=>$obj->fk_entrepot, 'qty_shipped'=>$obj->qty_shipped, 'date_valid'=>$obj->date_valid, 'date_delivery'=>$obj->date_delivery);
2125
+                    }
2126
+                    $i++;
2127
+                }
2128
+            }
2129
+            //var_dump($alreadysent);
2130
+        }
2131
+
2132
+        // Loop on each product to send/sent
2133
+        for ($i = 0 ; $i < $num_prod ; $i++)
2134
+        {
2135
+            print '<!-- origin line id = '.$lines[$i]->origin_line_id.' -->'; // id of order line
2136
+            print '<tr class="oddeven">';
2137
+
2138
+            // Adds a line numbering column
2139
+            if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER))
2140
+            {
2141
+                print '<td align="center">'.($i+1).'</td>';
2142
+            }
2143
+
2144
+            // Predefined product or service
2145
+            if ($lines[$i]->fk_product > 0)
2146
+            {
2147
+                // Define output language
2148
+                if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
2149
+                {
2150
+                    $prod = new Product($db);
2151
+                    $prod->fetch($lines[$i]->fk_product);
2152
+                    $label = ( ! empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product_label;
2153
+                }
2154
+                else
2155
+                    $label = (! empty($lines[$i]->label)?$lines[$i]->label:$lines[$i]->product_label);
2156
+
2157
+                print '<td>';
2158
+
2159
+                // Show product and description
2160
+                $product_static->type=$lines[$i]->fk_product_type;
2161
+                $product_static->id=$lines[$i]->fk_product;
2162
+                $product_static->ref=$lines[$i]->ref;
2163
+                $product_static->status_batch=$lines[$i]->product_tobatch;
2164
+                $text=$product_static->getNomUrl(1);
2165
+                $text.= ' - '.$label;
2166
+                $description=(! empty($conf->global->PRODUIT_DESC_IN_FORM)?'':dol_htmlentitiesbr($lines[$i]->description));
2167
+                print $form->textwithtooltip($text,$description,3,'','',$i);
2168
+                print_date_range($lines[$i]->date_start,$lines[$i]->date_end);
2169
+                if (! empty($conf->global->PRODUIT_DESC_IN_FORM))
2170
+                {
2171
+                    print (! empty($lines[$i]->description) && $lines[$i]->description!=$lines[$i]->product)?'<br>'.dol_htmlentitiesbr($lines[$i]->description):'';
2172
+                }
2173
+                print "</td>\n";
2174
+            }
2175
+            else
2176
+            {
2177
+                print "<td>";
2178
+                if ($lines[$i]->product_type == Product::TYPE_SERVICE) $text = img_object($langs->trans('Service'),'service');
2179
+                else $text = img_object($langs->trans('Product'),'product');
2180
+
2181
+                if (! empty($lines[$i]->label)) {
2182
+                    $text.= ' <strong>'.$lines[$i]->label.'</strong>';
2183
+                    print $form->textwithtooltip($text,$lines[$i]->description,3,'','',$i);
2184
+                } else {
2185
+                    print $text.' '.nl2br($lines[$i]->description);
2186
+                }
2187
+
2188
+                print_date_range($lines[$i]->date_start,$lines[$i]->date_end);
2189
+                print "</td>\n";
2190
+            }
2191
+
2192
+            // Qty ordered
2193
+            print '<td align="center">'.$lines[$i]->qty_asked.'</td>';
2194
+
2195
+            // Qty in other shipments (with shipment and warehouse used)
2196
+            if ($origin && $origin_id > 0)
2197
+            {
2198
+                print '<td align="center" class="nowrap">';
2199
+                foreach ($alreadysent as $key => $val)
2200
+                {
2201
+                    if ($lines[$i]->fk_origin_line == $key)
2202
+                    {
2203
+                        $j = 0;
2204
+                        foreach($val as $shipmentline_id=> $shipmentline_var)
2205
+                        {
2206
+                            if ($shipmentline_var['shipment_id'] == $lines[$i]->fk_expedition) continue; // We want to show only "other shipments"
2207
+
2208
+                            $j++;
2209
+                            if ($j > 1) print '<br>';
2210
+                            $shipment_static->fetch($shipmentline_var['shipment_id']);
2211
+                            print $shipment_static->getNomUrl(1);
2212
+                            print ' - '.$shipmentline_var['qty_shipped'];
2213
+                            $htmltext=$langs->trans("DateValidation").' : '.(empty($shipmentline_var['date_valid'])?$langs->trans("Draft"):dol_print_date($shipmentline_var['date_valid'], 'dayhour'));
2214
+                            if (! empty($conf->stock->enabled) && $shipmentline_var['warehouse'] > 0)
2215
+                            {
2216
+                                $warehousestatic->fetch($shipmentline_var['warehouse']);
2217
+                                $htmltext .= '<br>'.$langs->trans("From").' : '.$warehousestatic->getNomUrl(1);
2218
+                            }
2219
+                            print ' '.$form->textwithpicto('', $htmltext, 1);
2220
+                        }
2221
+                    }
2222
+                }
2223
+            }
2224
+            print '</td>';
2225
+
2226
+            if ($action == 'editline' && $lines[$i]->id == $line_id)
2227
+            {
2228
+                // edit mode
2229
+                print '<td colspan="'.$editColspan.'" align="center"><table class="nobordernopadding">';
2230
+                if (is_array($lines[$i]->detail_batch) && count($lines[$i]->detail_batch) > 0)
2231
+                {
2232
+                    print '<!-- case edit 1 -->';
2233
+                    $line = new ExpeditionLigne($db);
2234
+                    foreach ($lines[$i]->detail_batch as $detail_batch)
2235
+                    {
2236
+                        print '<tr>';
2237
+                        // Qty to ship or shipped
2238
+                        print '<td>' . '<input name="qtyl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->id.'" id="qtyl'.$line_id.'_'.$detail_batch->id.'" type="text" size="4" value="'.$detail_batch->qty.'">' . '</td>';
2239
+                        // Batch number managment
2240
+                        if ($lines[$i]->entrepot_id == 0)
2241
+                        {
2242
+                            // only show lot numbers from src warehouse when shipping from multiple warehouses
2243
+                            $line->fetch($detail_batch->fk_expeditiondet);
2244
+                        }
2245
+                        print '<td>' . $formproduct->selectLotStock($detail_batch->fk_origin_stock, 'batchl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->fk_origin_stock, '', 1, 0, $lines[$i]->fk_product, $line->entrepot_id). '</td>';
2246
+                        print '</tr>';
2247
+                    }
2248
+                    // add a 0 qty lot row to be able to add a lot
2249
+                    print '<tr>';
2250
+                    // Qty to ship or shipped
2251
+                    print '<td>' . '<input name="qtyl'.$line_id.'_0" id="qtyl'.$line_id.'_0" type="text" size="4" value="0">' . '</td>';
2252
+                    // Batch number managment
2253
+                    print '<td>' . $formproduct->selectLotStock('', 'batchl'.$line_id.'_0', '', 1, 0, $lines[$i]->fk_product). '</td>';
2254
+                    print '</tr>';
2255
+                }
2256
+                else if (! empty($conf->stock->enabled))
2257
+                {
2258
+                    if ($lines[$i]->fk_product > 0)
2259
+                    {
2260
+                        if ($lines[$i]->entrepot_id > 0)
2261
+                        {
2262
+                            print '<!-- case edit 2 -->';
2263
+                            print '<tr>';
2264
+                            // Qty to ship or shipped
2265
+                            print '<td>' . '<input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty_shipped.'">' . '</td>';
2266
+                            // Warehouse source
2267
+                            print '<td>' . $formproduct->selectWarehouses($lines[$i]->entrepot_id, 'entl'.$line_id, '', 1, 0, $lines[$i]->fk_product, '', 1). '</td>';
2268
+                            // Batch number managment
2269
+                            print '<td> - ' . $langs->trans("NA") . '</td>';
2270
+                            print '</tr>';
2271
+                        }
2272
+                        else if (count($lines[$i]->details_entrepot) > 1)
2273
+                        {
2274
+                            print '<!-- case edit 3 -->';
2275
+                            foreach ($lines[$i]->details_entrepot as $detail_entrepot)
2276
+                            {
2277
+                                print '<tr>';
2278
+                                // Qty to ship or shipped
2279
+                                print '<td>' . '<input name="qtyl'.$detail_entrepot->line_id.'" id="qtyl'.$detail_entrepot->line_id.'" type="text" size="4" value="'.$detail_entrepot->qty_shipped.'">' . '</td>';
2280
+                                // Warehouse source
2281
+                                print '<td>' . $formproduct->selectWarehouses($detail_entrepot->entrepot_id, 'entl'.$detail_entrepot->line_id, '', 1, 0, $lines[$i]->fk_product, '', 1) . '</td>';
2282
+                                // Batch number managment
2283
+                                print '<td> - ' . $langs->trans("NA") . '</td>';
2284
+                                print '</tr>';
2285
+                            }
2286
+                        }
2287
+                        else
2288
+                        {
2289
+                            print '<!-- case edit 4 -->';
2290
+                            print '<tr><td colspan="3">'.$langs->trans("NotEnoughStock").'</td></tr>';
2291
+                        }
2292
+                    }
2293
+                    else
2294
+                    {
2295
+                        print '<!-- case edit 5 -->';
2296
+                        print '<tr>';
2297
+                        // Qty to ship or shipped
2298
+                        print '<td>' . '<input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty_shipped.'">' . '</td>';
2299
+                        // Warehouse source
2300
+                        print '<td>' . '</td>';
2301
+                        // Batch number managment
2302
+                        print '<td>' . '</td>';
2303
+                        print '</tr>';
2304
+                    }
2305
+                }
2306
+                print '</table></td>';
2307
+            }
2308
+            else
2309
+            {
2310
+                // Qty to ship or shipped
2311
+                print '<td align="center">'.$lines[$i]->qty_shipped.'</td>';
2312
+
2313
+                // Warehouse source
2314
+                if (! empty($conf->stock->enabled))
2315
+                {
2316
+                    print '<td align="left">';
2317
+                    if ($lines[$i]->entrepot_id > 0)
2318
+                    {
2319
+                        $entrepot = new Entrepot($db);
2320
+                        $entrepot->fetch($lines[$i]->entrepot_id);
2321
+                        print $entrepot->getNomUrl(1);
2322
+                    }
2323
+                    else if (count($lines[$i]->details_entrepot) > 1)
2324
+                    {
2325
+                        $detail = '';
2326
+                        foreach ($lines[$i]->details_entrepot as $detail_entrepot)
2327
+                        {
2328
+                            if ($detail_entrepot->entrepot_id > 0)
2329
+                            {
2330
+                                $entrepot = new Entrepot($db);
2331
+                                $entrepot->fetch($detail_entrepot->entrepot_id);
2332
+                                $detail.= $langs->trans("DetailWarehouseFormat",$entrepot->libelle,$detail_entrepot->qty_shipped).'<br/>';
2333
+                            }
2334
+                        }
2335
+                        print $form->textwithtooltip(img_picto('', 'object_stock').' '.$langs->trans("DetailWarehouseNumber"),$detail);
2336
+                    }
2337
+                    print '</td>';
2338
+                }
2339
+
2340
+                // Batch number managment
2341
+                if (! empty($conf->productbatch->enabled))
2342
+                {
2343
+                    if (isset($lines[$i]->detail_batch))
2344
+                    {
2345
+                        print '<!-- Detail of lot -->';
2346
+                        print '<td>';
2347
+                        if ($lines[$i]->product_tobatch)
2348
+                        {
2349
+                            $detail = '';
2350
+                            foreach ($lines[$i]->detail_batch as $dbatch)	// $dbatch is instance of ExpeditionLineBatch
2351
+                            {
2352
+                                $detail.= $langs->trans("Batch").': '.$dbatch->batch;
2353
+                                $detail.= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby,"day");
2354
+                                $detail.= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby,"day");
2355
+                                $detail.= ' - '.$langs->trans("Qty").': '.$dbatch->qty;
2356
+                                $detail.= '<br>';
2357
+                            }
2358
+                            print $form->textwithtooltip(img_picto('', 'object_barcode').' '.$langs->trans("DetailBatchNumber"),$detail);
2359
+                        }
2360
+                        else
2361
+                        {
2362
+                            print $langs->trans("NA");
2363
+                        }
2364
+                        print '</td>';
2365
+                    } else {
2366
+                        print '<td></td>';
2367
+                    }
2368
+                }
2369
+            }
2370
+
2371
+            // Weight
2372
+            print '<td align="center">';
2373
+            if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) print $lines[$i]->weight*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->weight_units,"weight");
2374
+            else print '&nbsp;';
2375
+            print '</td>';
2376
+
2377
+            // Volume
2378
+            print '<td align="center">';
2379
+            if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) print $lines[$i]->volume*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->volume_units,"volume");
2380
+            else print '&nbsp;';
2381
+            print '</td>';
2382
+
2383
+            // Size
2384
+            //print '<td align="center">'.$lines[$i]->volume*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->volume_units,"volume").'</td>';
2385
+
2386
+            if ($action == 'editline' && $lines[$i]->id == $line_id)
2387
+            {
2388
+                print '<td align="center" colspan="2" valign="middle">';
2389
+                print '<input type="submit" class="button" id="savelinebutton" name="save" value="' . $langs->trans("Save") . '"><br>';
2390
+                print '<input type="submit" class="button" id="cancellinebutton" name="cancel" value="' . $langs->trans("Cancel") . '"><br>';
2391
+            }
2392
+            else if ($object->statut == 0)
2393
+            {
2394
+                // edit-delete buttons
2395
+                print '<td class="linecoledit" align="center">';
2396
+                print '<a href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=editline&amp;lineid=' . $lines[$i]->id . '">' . img_edit() . '</a>';
2397
+                print '</td>';
2398
+                print '<td class="linecoldelete" width="10">';
2399
+                print '<a href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=deleteline&amp;lineid=' . $lines[$i]->id . '">' . img_delete() . '</a>';
2400
+                print '</td>';
2401
+
2402
+                // Display lines extrafields
2403
+                if (! empty($rowExtrafieldsStart))
2404
+                {
2405
+                    print $rowExtrafieldsStart;
2406
+                    print $rowExtrafieldsView;
2407
+                    print $rowEnd;
2408
+                }
2409
+            }
2410
+            print "</tr>";
2411
+
2412
+            // Display lines extrafields
2413
+            if (is_array($extralabelslines) && count($extralabelslines)>0) {
2414
+                $colspan= empty($conf->productbatch->enabled) ? 5 : 6;
2415
+                $line = new ExpeditionLigne($db);
2416
+                $line->fetch_optionals($lines[$i]->id);
2417
+                print '<tr class="oddeven">';
2418
+                if ($action == 'editline' && $lines[$i]->id == $line_id)
2419
+                {
2420
+                    print $line->showOptionals($extrafieldsline, 'edit', array('style'=>$bc[$var], 'colspan'=>$colspan),$indiceAsked);
2421
+                }
2422
+                else
2423
+                {
2424
+                    print $line->showOptionals($extrafieldsline, 'view', array('style'=>$bc[$var], 'colspan'=>$colspan),$indiceAsked);
2425
+                }
2426
+                print '</tr>';
2427
+            }
2428
+        }
2429
+
2430
+        // TODO Show also lines ordered but not delivered
2431
+
2432
+        print "</table>\n";
2433
+        print '</div>';
2434
+    }
2435
+
2436
+
2437
+    dol_fiche_end();
2438
+
2439
+
2440
+    $object->fetchObjectLinked($object->id,$object->element);
2441
+
2442
+
2443
+    /*
2444 2444
 	 *    Boutons actions
2445 2445
 	 */
2446 2446
 
2447
-	if (($user->societe_id == 0) && ($action!='presend'))
2448
-	{
2449
-		print '<div class="tabsAction">';
2450
-
2451
-		$parameters = array();
2452
-		$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
2453
-		                                                                                               // modified by hook
2454
-		if (empty($reshook))
2455
-		{
2456
-
2457
-			if ($object->statut == Expedition::STATUS_DRAFT && $num_prod > 0)
2458
-			{
2459
-				if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->creer))
2460
-	  		     || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->shipping_advance->validate)))
2461
-				{
2462
-					print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=valid">'.$langs->trans("Validate").'</a>';
2463
-				}
2464
-				else
2465
-				{
2466
-					print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("Validate").'</a>';
2467
-				}
2468
-			}
2469
-
2470
-			// TODO add alternative status
2471
-			// 0=draft, 1=validated, 2=billed, we miss a status "delivered" (only available on order)
2472
-			if ($object->statut == Expedition::STATUS_CLOSED && $user->rights->expedition->creer)
2473
-			{
2474
-				if (! empty($conf->facture->enabled) && ! empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))  // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
2475
-				{
2476
-					print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=reopen">'.$langs->trans("ClassifyUnbilled").'</a>';
2477
-				}
2478
-				else
2479
-				{
2480
-			    	print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=reopen">'.$langs->trans("ReOpen").'</a>';
2481
-				}
2482
-			}
2483
-
2484
-			// Send
2485
-			if ($object->statut > 0)
2486
-			{
2487
-				if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->expedition->shipping_advance->send)
2488
-				{
2489
-					print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&mode=init#formmailbeforetitle">'.$langs->trans('SendMail').'</a>';
2490
-				}
2491
-				else print '<a class="butActionRefused classfortooltip" href="#">'.$langs->trans('SendMail').'</a>';
2492
-			}
2493
-
2494
-			// Create bill
2495
-			if (! empty($conf->facture->enabled) && ($object->statut == Expedition::STATUS_VALIDATED || $object->statut == Expedition::STATUS_CLOSED))
2496
-			{
2497
-				if ($user->rights->facture->creer)
2498
-				{
2499
-					// TODO show button only   if (! empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))
2500
-					// If we do that, we must also make this option official.
2501
-					print '<a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid.'">'.$langs->trans("CreateBill").'</a>';
2502
-				}
2503
-			}
2504
-
2505
-			// This is just to generate a delivery receipt
2506
-			//var_dump($object->linkedObjectsIds['delivery']);
2507
-			if ($conf->livraison_bon->enabled && ($object->statut == Expedition::STATUS_VALIDATED || $object->statut == Expedition::STATUS_CLOSED) && $user->rights->expedition->livraison->creer && count($object->linkedObjectsIds['delivery']) == 0)
2508
-			{
2509
-				print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=create_delivery">'.$langs->trans("CreateDeliveryOrder").'</a>';
2510
-			}
2511
-			// Close
2512
-			if ($object->statut == Expedition::STATUS_VALIDATED)
2513
-			{
2514
-				if ($user->rights->expedition->creer && $object->statut > 0 && ! $object->billed)
2515
-				{
2516
-					$label="Close"; $paramaction='classifyclosed';       // = Transferred/Received
2517
-					// Label here should be "Close" or "ClassifyBilled" if we decided to make bill on shipments instead of orders
2518
-					if (! empty($conf->facture->enabled) && ! empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))  // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
2519
-					{
2520
-					    $label="ClassifyBilled";
2521
-					    $paramaction='classifybilled';
2522
-					}
2523
-					print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action='.$paramaction.'">'.$langs->trans($label).'</a>';
2524
-				}
2525
-			}
2526
-
2527
-			if ($user->rights->expedition->supprimer)
2528
-			{
2529
-				print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=delete">'.$langs->trans("Delete").'</a>';
2530
-			}
2531
-		}
2532
-
2533
-		print '</div>';
2534
-	}
2535
-
2536
-
2537
-	/*
2447
+    if (($user->societe_id == 0) && ($action!='presend'))
2448
+    {
2449
+        print '<div class="tabsAction">';
2450
+
2451
+        $parameters = array();
2452
+        $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
2453
+                                                                                                        // modified by hook
2454
+        if (empty($reshook))
2455
+        {
2456
+
2457
+            if ($object->statut == Expedition::STATUS_DRAFT && $num_prod > 0)
2458
+            {
2459
+                if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->creer))
2460
+                   || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->shipping_advance->validate)))
2461
+                {
2462
+                    print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=valid">'.$langs->trans("Validate").'</a>';
2463
+                }
2464
+                else
2465
+                {
2466
+                    print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("Validate").'</a>';
2467
+                }
2468
+            }
2469
+
2470
+            // TODO add alternative status
2471
+            // 0=draft, 1=validated, 2=billed, we miss a status "delivered" (only available on order)
2472
+            if ($object->statut == Expedition::STATUS_CLOSED && $user->rights->expedition->creer)
2473
+            {
2474
+                if (! empty($conf->facture->enabled) && ! empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))  // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
2475
+                {
2476
+                    print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=reopen">'.$langs->trans("ClassifyUnbilled").'</a>';
2477
+                }
2478
+                else
2479
+                {
2480
+                    print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=reopen">'.$langs->trans("ReOpen").'</a>';
2481
+                }
2482
+            }
2483
+
2484
+            // Send
2485
+            if ($object->statut > 0)
2486
+            {
2487
+                if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->expedition->shipping_advance->send)
2488
+                {
2489
+                    print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&mode=init#formmailbeforetitle">'.$langs->trans('SendMail').'</a>';
2490
+                }
2491
+                else print '<a class="butActionRefused classfortooltip" href="#">'.$langs->trans('SendMail').'</a>';
2492
+            }
2493
+
2494
+            // Create bill
2495
+            if (! empty($conf->facture->enabled) && ($object->statut == Expedition::STATUS_VALIDATED || $object->statut == Expedition::STATUS_CLOSED))
2496
+            {
2497
+                if ($user->rights->facture->creer)
2498
+                {
2499
+                    // TODO show button only   if (! empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))
2500
+                    // If we do that, we must also make this option official.
2501
+                    print '<a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid.'">'.$langs->trans("CreateBill").'</a>';
2502
+                }
2503
+            }
2504
+
2505
+            // This is just to generate a delivery receipt
2506
+            //var_dump($object->linkedObjectsIds['delivery']);
2507
+            if ($conf->livraison_bon->enabled && ($object->statut == Expedition::STATUS_VALIDATED || $object->statut == Expedition::STATUS_CLOSED) && $user->rights->expedition->livraison->creer && count($object->linkedObjectsIds['delivery']) == 0)
2508
+            {
2509
+                print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=create_delivery">'.$langs->trans("CreateDeliveryOrder").'</a>';
2510
+            }
2511
+            // Close
2512
+            if ($object->statut == Expedition::STATUS_VALIDATED)
2513
+            {
2514
+                if ($user->rights->expedition->creer && $object->statut > 0 && ! $object->billed)
2515
+                {
2516
+                    $label="Close"; $paramaction='classifyclosed';       // = Transferred/Received
2517
+                    // Label here should be "Close" or "ClassifyBilled" if we decided to make bill on shipments instead of orders
2518
+                    if (! empty($conf->facture->enabled) && ! empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))  // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
2519
+                    {
2520
+                        $label="ClassifyBilled";
2521
+                        $paramaction='classifybilled';
2522
+                    }
2523
+                    print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action='.$paramaction.'">'.$langs->trans($label).'</a>';
2524
+                }
2525
+            }
2526
+
2527
+            if ($user->rights->expedition->supprimer)
2528
+            {
2529
+                print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=delete">'.$langs->trans("Delete").'</a>';
2530
+            }
2531
+        }
2532
+
2533
+        print '</div>';
2534
+    }
2535
+
2536
+
2537
+    /*
2538 2538
 	 * Documents generated
2539 2539
 	 */
2540 2540
 
2541
-	if ($action != 'presend' && $action != 'editline')
2542
-	{
2541
+    if ($action != 'presend' && $action != 'editline')
2542
+    {
2543 2543
         print '<div class="fichecenter"><div class="fichehalfleft">';
2544 2544
 
2545 2545
         $objectref = dol_sanitizeFileName($object->ref);
2546
-		$filedir = $conf->expedition->dir_output . "/sending/" .$objectref;
2546
+        $filedir = $conf->expedition->dir_output . "/sending/" .$objectref;
2547 2547
 
2548
-		$urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
2548
+        $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
2549 2549
 
2550
-		$genallowed=$user->rights->expedition->lire;
2551
-		$delallowed=$user->rights->expedition->creer;
2550
+        $genallowed=$user->rights->expedition->lire;
2551
+        $delallowed=$user->rights->expedition->creer;
2552 2552
 
2553
-		print $formfile->showdocuments('expedition',$objectref,$filedir,$urlsource,$genallowed,$delallowed,$object->modelpdf,1,0,0,28,0,'','','',$soc->default_lang);
2553
+        print $formfile->showdocuments('expedition',$objectref,$filedir,$urlsource,$genallowed,$delallowed,$object->modelpdf,1,0,0,28,0,'','','',$soc->default_lang);
2554 2554
 
2555 2555
 
2556
-		// Show links to link elements
2557
-		//$linktoelem = $form->showLinkToObjectBlock($object, null, array('order'));
2558
-		$somethingshown = $form->showLinkedObjectBlock($object, '');
2556
+        // Show links to link elements
2557
+        //$linktoelem = $form->showLinkToObjectBlock($object, null, array('order'));
2558
+        $somethingshown = $form->showLinkedObjectBlock($object, '');
2559 2559
 
2560 2560
 
2561
-		print '</div><div class="fichehalfright"><div class="ficheaddleft">';
2561
+        print '</div><div class="fichehalfright"><div class="ficheaddleft">';
2562 2562
 
2563
-		// List of actions on element
2564
-		include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
2565
-		$formactions=new FormActions($db);
2566
-		$somethingshown = $formactions->showactions($object,'shipping',$socid,1);
2563
+        // List of actions on element
2564
+        include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
2565
+        $formactions=new FormActions($db);
2566
+        $somethingshown = $formactions->showactions($object,'shipping',$socid,1);
2567 2567
 
2568
-		print '</div></div></div>';
2569
-	}
2568
+        print '</div></div></div>';
2569
+    }
2570 2570
 
2571 2571
 
2572
-	/*
2572
+    /*
2573 2573
 	 * Action presend
2574 2574
 	 */
2575 2575
 
2576
-	//Select mail models is same action as presend
2577
-	if (GETPOST('modelselected')) {
2578
-		$action = 'presend';
2579
-	}
2576
+    //Select mail models is same action as presend
2577
+    if (GETPOST('modelselected')) {
2578
+        $action = 'presend';
2579
+    }
2580 2580
 
2581
-	// Presend form
2582
-	$modelmail='shipping_send';
2583
-	$defaulttopic='SendShippingRef';
2584
-	$diroutput = $conf->expedition->dir_output. '/sending';
2585
-	$trackid = 'shi'.$object->id;
2581
+    // Presend form
2582
+    $modelmail='shipping_send';
2583
+    $defaulttopic='SendShippingRef';
2584
+    $diroutput = $conf->expedition->dir_output. '/sending';
2585
+    $trackid = 'shi'.$object->id;
2586 2586
 
2587
-	include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
2587
+    include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
2588 2588
 }
2589 2589
 
2590 2590
 // End of page
Please login to merge, or discard this patch.
dolibarr/htdocs/expedition/tpl/linkedobjectblock.tpl.php 1 patch
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -19,8 +19,8 @@  discard block
 block discarded – undo
19 19
 // Protection to avoid direct call of template
20 20
 if (empty($conf) || ! is_object($conf))
21 21
 {
22
-	print "Error, template page can't be called as URL";
23
-	exit;
22
+    print "Error, template page can't be called as URL";
23
+    exit;
24 24
 }
25 25
 
26 26
 ?>
@@ -51,20 +51,20 @@  discard block
 block discarded – undo
51 51
         <td></td>
52 52
     	<td align="center"><?php echo dol_print_date($objectlink->date_delivery,'day'); ?></td>
53 53
     	<td align="right"><?php
54
-    		if ($user->rights->expedition->lire) {
55
-    			$total = $total + $objectlink->total_ht;
56
-    			echo price($objectlink->total_ht);
57
-    		} ?></td>
54
+            if ($user->rights->expedition->lire) {
55
+                $total = $total + $objectlink->total_ht;
56
+                echo price($objectlink->total_ht);
57
+            } ?></td>
58 58
     	<td align="right"><?php echo $objectlink->getLibStatut(3); ?></td>
59 59
     	<td align="right">
60 60
     		<?php
61
-    		// For now, shipments must stay linked to order, so link is not deletable
62
-    		if($object->element != 'commande') {
63
-    			?>
61
+            // For now, shipments must stay linked to order, so link is not deletable
62
+            if($object->element != 'commande') {
63
+                ?>
64 64
     			<a href="<?php echo $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=dellink&dellinkid='.$key; ?>"><?php echo img_picto($langs->transnoentitiesnoconv("RemoveLink"), 'unlink'); ?></a></td>
65 65
     			<?php
66
-    		}
67
-    		?>
66
+            }
67
+            ?>
68 68
     </tr>
69 69
 <?php
70 70
 }
Please login to merge, or discard this patch.
dolibarr/htdocs/expedition/shipment.php 1 patch
Indentation   +597 added lines, -597 removed lines patch added patch discarded remove patch
@@ -34,8 +34,8 @@  discard block
 block discarded – undo
34 34
 require_once DOL_DOCUMENT_ROOT.'/core/lib/sendings.lib.php';
35 35
 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
36 36
 if (! empty($conf->projet->enabled)) {
37
-	require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
38
-	require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
37
+    require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
38
+    require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
39 39
 }
40 40
 if (! empty($conf->stock->enabled))  require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
41 41
 if (! empty($conf->propal->enabled)) require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
@@ -78,16 +78,16 @@  discard block
 block discarded – undo
78 78
     // Categorisation dans projet
79 79
     if ($action == 'classin')
80 80
     {
81
-    	$object = new Commande($db);
82
-    	$object->fetch($id);
83
-    	$object->setProject(GETPOST('projectid','int'));
81
+        $object = new Commande($db);
82
+        $object->fetch($id);
83
+        $object->setProject(GETPOST('projectid','int'));
84 84
     }
85 85
 
86 86
     if ($action == 'confirm_cloture' && GETPOST('confirm','alpha') == 'yes')
87 87
     {
88
-    	$object = new Commande($db);
89
-    	$object->fetch($id);
90
-    	$result = $object->cloture($user);
88
+        $object = new Commande($db);
89
+        $object->fetch($id);
90
+        $result = $object->cloture($user);
91 91
     }
92 92
 
93 93
     // Positionne ref commande client
@@ -101,14 +101,14 @@  discard block
 block discarded – undo
101 101
 
102 102
     if ($action == 'setdatedelivery' && $user->rights->commande->creer)
103 103
     {
104
-    	//print "x ".$_POST['liv_month'].", ".$_POST['liv_day'].", ".$_POST['liv_year'];
105
-    	$datelivraison=dol_mktime(0, 0, 0, GETPOST('liv_month','int'), GETPOST('liv_day','int'),GETPOST('liv_year','int'));
104
+        //print "x ".$_POST['liv_month'].", ".$_POST['liv_day'].", ".$_POST['liv_year'];
105
+        $datelivraison=dol_mktime(0, 0, 0, GETPOST('liv_month','int'), GETPOST('liv_day','int'),GETPOST('liv_year','int'));
106 106
 
107
-    	$object = new Commande($db);
108
-    	$object->fetch($id);
109
-    	$result=$object->set_date_livraison($user,$datelivraison);
110
-    	if ($result < 0)
111
-    		setEventMessages($object->error, $object->errors, 'errors');
107
+        $object = new Commande($db);
108
+        $object->fetch($id);
109
+        $result=$object->set_date_livraison($user,$datelivraison);
110
+        if ($result < 0)
111
+            setEventMessages($object->error, $object->errors, 'errors');
112 112
     }
113 113
     /*
114 114
     if ($action == 'setdeliveryaddress' && $user->rights->commande->creer)
@@ -122,11 +122,11 @@  discard block
 block discarded – undo
122 122
     */
123 123
     if ($action == 'setmode' && $user->rights->commande->creer)
124 124
     {
125
-    	$object = new Commande($db);
126
-    	$object->fetch($id);
127
-    	$result = $object->setPaymentMethods(GETPOST('mode_reglement_id','int'));
128
-    	if ($result < 0)
129
-    		setEventMessages($object->error, $object->errors, 'errors');
125
+        $object = new Commande($db);
126
+        $object->fetch($id);
127
+        $result = $object->setPaymentMethods(GETPOST('mode_reglement_id','int'));
128
+        if ($result < 0)
129
+            setEventMessages($object->error, $object->errors, 'errors');
130 130
     }
131 131
 
132 132
     if ($action == 'setavailability' && $user->rights->commande->creer) {
@@ -147,20 +147,20 @@  discard block
 block discarded – undo
147 147
 
148 148
     if ($action == 'setconditions' && $user->rights->commande->creer)
149 149
     {
150
-    	$object = new Commande($db);
151
-    	$object->fetch($id);
152
-    	$result=$object->setPaymentTerms(GETPOST('cond_reglement_id','int'));
153
-    	if ($result < 0)
154
-    		setEventMessages($object->error, $object->errors, 'errors');
150
+        $object = new Commande($db);
151
+        $object->fetch($id);
152
+        $result=$object->setPaymentTerms(GETPOST('cond_reglement_id','int'));
153
+        if ($result < 0)
154
+            setEventMessages($object->error, $object->errors, 'errors');
155 155
     }
156 156
 
157 157
     // Set incoterm
158 158
     elseif ($action == 'set_incoterms' && !empty($conf->incoterm->enabled))
159 159
     {
160
-    	$result = $object->setIncoterms(GETPOST('incoterm_id', 'int'), GETPOST('location_incoterms', 'alpha'));
161
-    	if ($result < 0) {
162
-    		setEventMessages($object->error, $object->errors, 'errors');
163
-    	}
160
+        $result = $object->setIncoterms(GETPOST('incoterm_id', 'int'), GETPOST('location_incoterms', 'alpha'));
161
+        if ($result < 0) {
162
+            setEventMessages($object->error, $object->errors, 'errors');
163
+        }
164 164
     }
165 165
 
166 166
     // shipping method
@@ -168,8 +168,8 @@  discard block
 block discarded – undo
168 168
         $object = new Commande($db);
169 169
         $object->fetch($id);
170 170
         $result=$object->setShippingMethod(GETPOST('shipping_method_id', 'int'));
171
-    	if ($result < 0)
172
-    		setEventMessages($object->error, $object->errors, 'errors');
171
+        if ($result < 0)
172
+            setEventMessages($object->error, $object->errors, 'errors');
173 173
     }
174 174
 
175 175
     // warehouse
@@ -183,9 +183,9 @@  discard block
 block discarded – undo
183 183
 
184 184
     if ($action == 'update_extras')
185 185
     {
186
-    	$object->oldcopy = dol_clone($object);
186
+        $object->oldcopy = dol_clone($object);
187 187
 
188
-    	// Fill array 'array_options' with data from update form
188
+        // Fill array 'array_options' with data from update form
189 189
         $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
190 190
         $ret = $extrafields->setOptionalsFromPost($extralabels, $object, GETPOST('attribute', 'none'));
191 191
         if ($ret < 0) $error++;
@@ -194,11 +194,11 @@  discard block
 block discarded – undo
194 194
         {
195 195
             // Actions on extra fields
196 196
             $result = $object->insertExtraFields('SHIPMENT_MODIFY');
197
-			if ($result < 0)
198
-			{
199
-				setEventMessages($object->error, $object->errors, 'errors');
200
-				$error++;
201
-			}
197
+            if ($result < 0)
198
+            {
199
+                setEventMessages($object->error, $object->errors, 'errors');
200
+                $error++;
201
+            }
202 202
         }
203 203
 
204 204
         if ($error)
@@ -231,162 +231,162 @@  discard block
 block discarded – undo
231 231
 
232 232
 if ($id > 0 || ! empty($ref))
233 233
 {
234
-	$object = new Commande($db);
235
-	if ( $object->fetch($id,$ref) > 0)
236
-	{
237
-		$object->loadExpeditions(1);
234
+    $object = new Commande($db);
235
+    if ( $object->fetch($id,$ref) > 0)
236
+    {
237
+        $object->loadExpeditions(1);
238 238
 
239
-		$product_static=new Product($db);
239
+        $product_static=new Product($db);
240 240
 
241
-		$soc = new Societe($db);
242
-		$soc->fetch($object->socid);
241
+        $soc = new Societe($db);
242
+        $soc->fetch($object->socid);
243 243
 
244
-		$author = new User($db);
245
-		$author->fetch($object->user_author_id);
244
+        $author = new User($db);
245
+        $author->fetch($object->user_author_id);
246 246
 
247
-		$res = $object->fetch_optionals();
247
+        $res = $object->fetch_optionals();
248 248
 
249
-		$head = commande_prepare_head($object);
250
-		dol_fiche_head($head, 'shipping', $langs->trans("CustomerOrder"), -1, 'order');
249
+        $head = commande_prepare_head($object);
250
+        dol_fiche_head($head, 'shipping', $langs->trans("CustomerOrder"), -1, 'order');
251 251
 
252 252
 
253
-		$formconfirm = '';
253
+        $formconfirm = '';
254 254
 
255
-		// Confirm validation
256
-		if ($action == 'cloture')
257
-		{
258
-			$formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$id,$langs->trans("CloseShipment"),$langs->trans("ConfirmCloseShipment"),"confirm_cloture");
259
-		}
255
+        // Confirm validation
256
+        if ($action == 'cloture')
257
+        {
258
+            $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$id,$langs->trans("CloseShipment"),$langs->trans("ConfirmCloseShipment"),"confirm_cloture");
259
+        }
260 260
 
261
-		// Call Hook formConfirm
262
-		$parameters = array();
263
-		$reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
264
-		if (empty($reshook)) $formconfirm.=$hookmanager->resPrint;
265
-		elseif ($reshook > 0) $formconfirm=$hookmanager->resPrint;
266
-
267
-		// Print form confirm
268
-		print $formconfirm;
269
-
270
-
271
-		// Order card
272
-
273
-		$linkback = '<a href="' . DOL_URL_ROOT . '/commande/list.php?restore_lastsearch_values=1' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
274
-
275
-
276
-		$morehtmlref='<div class="refidno">';
277
-		// Ref customer
278
-		$morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->commande->creer, 'string', '', 0, 1);
279
-		$morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->commande->creer, 'string', '', null, null, '', 1);
280
-	    // Thirdparty
281
-	    $morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1);
282
-	    // Project
283
-	    if (! empty($conf->projet->enabled))
284
-	    {
285
-	        $langs->load("projects");
286
-	        $morehtmlref.='<br>'.$langs->trans('Project') . ' ';
287
-	        if ($user->rights->commande->creer)
288
-	        {
289
-	            if ($action != 'classify')
290
-	                $morehtmlref.='<a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
291
-	                if ($action == 'classify') {
292
-	                    //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
293
-	                    $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
294
-	                    $morehtmlref.='<input type="hidden" name="action" value="classin">';
295
-	                    $morehtmlref.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
296
-	                    $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
297
-	                    $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
298
-	                    $morehtmlref.='</form>';
299
-	                } else {
300
-	                    $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
301
-	                }
302
-	        } else {
303
-	            if (! empty($object->fk_project)) {
304
-	                $proj = new Project($db);
305
-	                $proj->fetch($object->fk_project);
306
-	                $morehtmlref.='<a href="'.DOL_URL_ROOT.'/projet/card.php?id=' . $object->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
307
-	                $morehtmlref.=$proj->ref;
308
-	                $morehtmlref.='</a>';
309
-	            } else {
310
-	                $morehtmlref.='';
311
-	            }
312
-	        }
313
-	    }
314
-	    $morehtmlref.='</div>';
315
-
316
-
317
-	    dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
318
-
319
-
320
-	    print '<div class="fichecenter">';
321
-	    print '<div class="fichehalfleft">';
322
-	    print '<div class="underbanner clearboth"></div>';
323
-
324
-	    print '<table class="border" width="100%">';
325
-
326
-		// Discounts for third party
327
-	    if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
328
-	    	$filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
329
-	    	$filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
330
-	    } else {
331
-	    	$filterabsolutediscount = "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')";
332
-	    	$filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')";
333
-	    }
334
-
335
-		print '<tr><td class="titlefield">'.$langs->trans('Discounts').'</td><td colspan="3">';
336
-
337
-		$absolute_discount=$soc->getAvailableDiscounts('',$filterabsolutediscount);
338
-		$absolute_creditnote=$soc->getAvailableDiscounts('',$filtercreditnote);
339
-		$absolute_discount=price2num($absolute_discount,'MT');
340
-		$absolute_creditnote=price2num($absolute_creditnote,'MT');
341
-
342
-		$thirdparty = $soc;
343
-		$discount_type = 0;
344
-		$backtopage = urlencode($_SERVER["PHP_SELF"] . '?id=' . $object->id);
345
-		$cannotApplyDiscount = 1;
346
-		include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
347
-		print '</td></tr>';
261
+        // Call Hook formConfirm
262
+        $parameters = array();
263
+        $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
264
+        if (empty($reshook)) $formconfirm.=$hookmanager->resPrint;
265
+        elseif ($reshook > 0) $formconfirm=$hookmanager->resPrint;
348 266
 
349
-		// Date
350
-		print '<tr><td>'.$langs->trans('Date').'</td>';
351
-		print '<td colspan="2">';
352
-		print dol_print_date($object->date,'daytext');
353
-		if ($object->hasDelay() && empty($object->date_livraison)) {
354
-		    print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
355
-		}
356
-		print '</td>';
357
-		print '</tr>';
267
+        // Print form confirm
268
+        print $formconfirm;
358 269
 
359
-		// Delivery date planned
360
-		print '<tr><td height="10">';
361
-		print '<table class="nobordernopadding" width="100%"><tr><td>';
362
-		print $langs->trans('DateDeliveryPlanned');
363
-		print '</td>';
364 270
 
365
-		if ($action != 'editdate_livraison') print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editdate_livraison&amp;id='.$object->id.'">'.img_edit($langs->trans('SetDeliveryDate'),1).'</a></td>';
366
-		print '</tr></table>';
367
-		print '</td><td colspan="2">';
368
-		if ($action == 'editdate_livraison')
369
-		{
370
-			print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
371
-			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
372
-			print '<input type="hidden" name="action" value="setdatedelivery">';
373
-			print $form->selectDate($object->date_livraison>0?$object->date_livraison:-1, 'liv_', '', '', '', "setdatedelivery");
374
-			print '<input type="submit" class="button" value="'.$langs->trans('Modify').'">';
375
-			print '</form>';
376
-		}
377
-		else
378
-		{
379
-			print dol_print_date($object->date_livraison,'daytext');
380
-			if ($object->hasDelay() && ! empty($object->date_livraison)) {
381
-			    print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
382
-			}
383
-		}
384
-		print '</td>';
385
-		// Note on several rows
386
-		//print '<td rowspan="'.$nbrow.'" valign="top">'.$langs->trans('NotePublic').' :<br>';
387
-		//print nl2br($object->note_public);
388
-		//print '</td>';
389
-		print '</tr>';
271
+        // Order card
272
+
273
+        $linkback = '<a href="' . DOL_URL_ROOT . '/commande/list.php?restore_lastsearch_values=1' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
274
+
275
+
276
+        $morehtmlref='<div class="refidno">';
277
+        // Ref customer
278
+        $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->commande->creer, 'string', '', 0, 1);
279
+        $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->commande->creer, 'string', '', null, null, '', 1);
280
+        // Thirdparty
281
+        $morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1);
282
+        // Project
283
+        if (! empty($conf->projet->enabled))
284
+        {
285
+            $langs->load("projects");
286
+            $morehtmlref.='<br>'.$langs->trans('Project') . ' ';
287
+            if ($user->rights->commande->creer)
288
+            {
289
+                if ($action != 'classify')
290
+                    $morehtmlref.='<a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
291
+                    if ($action == 'classify') {
292
+                        //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
293
+                        $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
294
+                        $morehtmlref.='<input type="hidden" name="action" value="classin">';
295
+                        $morehtmlref.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
296
+                        $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
297
+                        $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
298
+                        $morehtmlref.='</form>';
299
+                    } else {
300
+                        $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
301
+                    }
302
+            } else {
303
+                if (! empty($object->fk_project)) {
304
+                    $proj = new Project($db);
305
+                    $proj->fetch($object->fk_project);
306
+                    $morehtmlref.='<a href="'.DOL_URL_ROOT.'/projet/card.php?id=' . $object->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
307
+                    $morehtmlref.=$proj->ref;
308
+                    $morehtmlref.='</a>';
309
+                } else {
310
+                    $morehtmlref.='';
311
+                }
312
+            }
313
+        }
314
+        $morehtmlref.='</div>';
315
+
316
+
317
+        dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
318
+
319
+
320
+        print '<div class="fichecenter">';
321
+        print '<div class="fichehalfleft">';
322
+        print '<div class="underbanner clearboth"></div>';
323
+
324
+        print '<table class="border" width="100%">';
325
+
326
+        // Discounts for third party
327
+        if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
328
+            $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
329
+            $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
330
+        } else {
331
+            $filterabsolutediscount = "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')";
332
+            $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')";
333
+        }
334
+
335
+        print '<tr><td class="titlefield">'.$langs->trans('Discounts').'</td><td colspan="3">';
336
+
337
+        $absolute_discount=$soc->getAvailableDiscounts('',$filterabsolutediscount);
338
+        $absolute_creditnote=$soc->getAvailableDiscounts('',$filtercreditnote);
339
+        $absolute_discount=price2num($absolute_discount,'MT');
340
+        $absolute_creditnote=price2num($absolute_creditnote,'MT');
341
+
342
+        $thirdparty = $soc;
343
+        $discount_type = 0;
344
+        $backtopage = urlencode($_SERVER["PHP_SELF"] . '?id=' . $object->id);
345
+        $cannotApplyDiscount = 1;
346
+        include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
347
+        print '</td></tr>';
348
+
349
+        // Date
350
+        print '<tr><td>'.$langs->trans('Date').'</td>';
351
+        print '<td colspan="2">';
352
+        print dol_print_date($object->date,'daytext');
353
+        if ($object->hasDelay() && empty($object->date_livraison)) {
354
+            print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
355
+        }
356
+        print '</td>';
357
+        print '</tr>';
358
+
359
+        // Delivery date planned
360
+        print '<tr><td height="10">';
361
+        print '<table class="nobordernopadding" width="100%"><tr><td>';
362
+        print $langs->trans('DateDeliveryPlanned');
363
+        print '</td>';
364
+
365
+        if ($action != 'editdate_livraison') print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editdate_livraison&amp;id='.$object->id.'">'.img_edit($langs->trans('SetDeliveryDate'),1).'</a></td>';
366
+        print '</tr></table>';
367
+        print '</td><td colspan="2">';
368
+        if ($action == 'editdate_livraison')
369
+        {
370
+            print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
371
+            print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
372
+            print '<input type="hidden" name="action" value="setdatedelivery">';
373
+            print $form->selectDate($object->date_livraison>0?$object->date_livraison:-1, 'liv_', '', '', '', "setdatedelivery");
374
+            print '<input type="submit" class="button" value="'.$langs->trans('Modify').'">';
375
+            print '</form>';
376
+        }
377
+        else
378
+        {
379
+            print dol_print_date($object->date_livraison,'daytext');
380
+            if ($object->hasDelay() && ! empty($object->date_livraison)) {
381
+                print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
382
+            }
383
+        }
384
+        print '</td>';
385
+        // Note on several rows
386
+        //print '<td rowspan="'.$nbrow.'" valign="top">'.$langs->trans('NotePublic').' :<br>';
387
+        //print nl2br($object->note_public);
388
+        //print '</td>';
389
+        print '</tr>';
390 390
 
391 391
         // Shipping Method
392 392
         print '<tr><td>';
@@ -426,8 +426,8 @@  discard block
 block discarded – undo
426 426
             print '</tr>';
427 427
         }
428 428
 
429
-		// Terms of payment
430
-		/*
429
+        // Terms of payment
430
+        /*
431 431
 		print '<tr><td height="10">';
432 432
 		print '<table class="nobordernopadding" width="100%"><tr><td>';
433 433
 		print $langs->trans('PaymentConditionsShort');
@@ -464,392 +464,392 @@  discard block
 block discarded – undo
464 464
 		}
465 465
 		print '</td></tr>';*/
466 466
 
467
-		// Availability
468
-		print '<tr><td height="10">';
469
-		print '<table class="nobordernopadding" width="100%"><tr><td>';
470
-		print $langs->trans('AvailabilityPeriod');
471
-		print '</td>';
472
-		if ($action != 'editavailability')
473
-			print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editavailability&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetAvailability'), 1) . '</a></td>';
474
-		print '</tr></table>';
475
-		print '</td><td colspan="3">';
476
-		if ($action == 'editavailability') {
477
-			$form->form_availability($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->availability_id, 'availability_id', 1);
478
-		} else {
479
-			$form->form_availability($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->availability_id, 'none', 1);
480
-		}
481
-		print '</td></tr>';
467
+        // Availability
468
+        print '<tr><td height="10">';
469
+        print '<table class="nobordernopadding" width="100%"><tr><td>';
470
+        print $langs->trans('AvailabilityPeriod');
471
+        print '</td>';
472
+        if ($action != 'editavailability')
473
+            print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editavailability&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetAvailability'), 1) . '</a></td>';
474
+        print '</tr></table>';
475
+        print '</td><td colspan="3">';
476
+        if ($action == 'editavailability') {
477
+            $form->form_availability($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->availability_id, 'availability_id', 1);
478
+        } else {
479
+            $form->form_availability($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->availability_id, 'none', 1);
480
+        }
481
+        print '</td></tr>';
482 482
 
483
-		// Source
484
-		print '<tr><td height="10">';
485
-		print '<table class="nobordernopadding" width="100%"><tr><td>';
486
-		print $langs->trans('Source');
487
-		print '</td>';
488
-		if ($action != 'editdemandreason')
489
-			print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editdemandreason&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetDemandReason'), 1) . '</a></td>';
490
-		print '</tr></table>';
491
-		print '</td><td colspan="3">';
492
-		if ($action == 'editdemandreason') {
493
-			$form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->demand_reason_id, 'demand_reason_id', 1);
494
-		} else {
495
-			$form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->demand_reason_id, 'none');
496
-		}
483
+        // Source
484
+        print '<tr><td height="10">';
485
+        print '<table class="nobordernopadding" width="100%"><tr><td>';
486
+        print $langs->trans('Source');
487
+        print '</td>';
488
+        if ($action != 'editdemandreason')
489
+            print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editdemandreason&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetDemandReason'), 1) . '</a></td>';
490
+        print '</tr></table>';
491
+        print '</td><td colspan="3">';
492
+        if ($action == 'editdemandreason') {
493
+            $form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->demand_reason_id, 'demand_reason_id', 1);
494
+        } else {
495
+            $form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->demand_reason_id, 'none');
496
+        }
497 497
 
498
-		$tmparray=$object->getTotalWeightVolume();
499
-		$totalWeight=$tmparray['weight'];
500
-		$totalVolume=$tmparray['volume'];
501
-		if ($totalWeight || $totalVolume)
502
-		{
503
-		    print '<tr><td>'.$langs->trans("CalculatedWeight").'</td>';
504
-		    print '<td>';
505
-		    print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND)?$conf->global->MAIN_WEIGHT_DEFAULT_ROUND:-1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT)?$conf->global->MAIN_WEIGHT_DEFAULT_UNIT:'no');
506
-		    print '</td></tr>';
507
-		    print '<tr><td>'.$langs->trans("CalculatedVolume").'</td>';
508
-		    print '<td>';
509
-		    print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND)?$conf->global->MAIN_VOLUME_DEFAULT_ROUND:-1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT)?$conf->global->MAIN_VOLUME_DEFAULT_UNIT:'no');
510
-		    print '</td></tr>';
511
-		}
498
+        $tmparray=$object->getTotalWeightVolume();
499
+        $totalWeight=$tmparray['weight'];
500
+        $totalVolume=$tmparray['volume'];
501
+        if ($totalWeight || $totalVolume)
502
+        {
503
+            print '<tr><td>'.$langs->trans("CalculatedWeight").'</td>';
504
+            print '<td>';
505
+            print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND)?$conf->global->MAIN_WEIGHT_DEFAULT_ROUND:-1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT)?$conf->global->MAIN_WEIGHT_DEFAULT_UNIT:'no');
506
+            print '</td></tr>';
507
+            print '<tr><td>'.$langs->trans("CalculatedVolume").'</td>';
508
+            print '<td>';
509
+            print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND)?$conf->global->MAIN_VOLUME_DEFAULT_ROUND:-1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT)?$conf->global->MAIN_VOLUME_DEFAULT_UNIT:'no');
510
+            print '</td></tr>';
511
+        }
512 512
 
513
-		// TODO How record was recorded OrderMode (llx_c_input_method)
513
+        // TODO How record was recorded OrderMode (llx_c_input_method)
514 514
 
515
-		// Incoterms
516
-		if (!empty($conf->incoterm->enabled))
517
-		{
518
-		    print '<tr><td>';
519
-		    print '<table width="100%" class="nobordernopadding"><tr><td>';
520
-		    print $langs->trans('IncotermLabel');
521
-		    print '<td><td align="right">';
522
-		    if ($user->rights->commande->creer) print '<a href="'.$_SERVER['PHP_SELF'].'/expedition/shipment.php?id='.$object->id.'&action=editincoterm">'.img_edit().'</a>';
523
-		    else print '&nbsp;';
524
-		    print '</td></tr></table>';
525
-		    print '</td>';
526
-		    print '<td colspan="3">';
527
-		    if ($action != 'editincoterm')
528
-		    {
529
-		        print $form->textwithpicto($object->display_incoterms(), $object->libelle_incoterms, 1);
530
-		    }
531
-		    else
532
-		    {
533
-		        print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''), $_SERVER['PHP_SELF'].'?id='.$object->id);
534
-		    }
535
-		    print '</td></tr>';
536
-		}
515
+        // Incoterms
516
+        if (!empty($conf->incoterm->enabled))
517
+        {
518
+            print '<tr><td>';
519
+            print '<table width="100%" class="nobordernopadding"><tr><td>';
520
+            print $langs->trans('IncotermLabel');
521
+            print '<td><td align="right">';
522
+            if ($user->rights->commande->creer) print '<a href="'.$_SERVER['PHP_SELF'].'/expedition/shipment.php?id='.$object->id.'&action=editincoterm">'.img_edit().'</a>';
523
+            else print '&nbsp;';
524
+            print '</td></tr></table>';
525
+            print '</td>';
526
+            print '<td colspan="3">';
527
+            if ($action != 'editincoterm')
528
+            {
529
+                print $form->textwithpicto($object->display_incoterms(), $object->libelle_incoterms, 1);
530
+            }
531
+            else
532
+            {
533
+                print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''), $_SERVER['PHP_SELF'].'?id='.$object->id);
534
+            }
535
+            print '</td></tr>';
536
+        }
537 537
 
538
-		// Other attributes
539
-		$cols = 2;
540
-		include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
538
+        // Other attributes
539
+        $cols = 2;
540
+        include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
541 541
 
542
-		print '</table>';
542
+        print '</table>';
543 543
 
544
-		print '</div>';
545
-		print '<div class="fichehalfright">';
546
-		print '<div class="ficheaddleft">';
547
-		print '<div class="underbanner clearboth"></div>';
544
+        print '</div>';
545
+        print '<div class="fichehalfright">';
546
+        print '<div class="ficheaddleft">';
547
+        print '<div class="underbanner clearboth"></div>';
548 548
 
549
-		print '<table class="border centpercent">';
549
+        print '<table class="border centpercent">';
550 550
 
551
-		if (!empty($conf->multicurrency->enabled) && ($object->multicurrency_code != $conf->currency))
552
-		{
553
-		    // Multicurrency Amount HT
554
-		    print '<tr><td class="titlefieldmiddle">' . $form->editfieldkey('MulticurrencyAmountHT', 'multicurrency_total_ht', '', $object, 0) . '</td>';
555
-		    print '<td class="nowrap">' . price($object->multicurrency_total_ht, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
556
-		    print '</tr>';
557
-
558
-		    // Multicurrency Amount VAT
559
-		    print '<tr><td>' . $form->editfieldkey('MulticurrencyAmountVAT', 'multicurrency_total_tva', '', $object, 0) . '</td>';
560
-		    print '<td class="nowrap">' . price($object->multicurrency_total_tva, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
561
-		    print '</tr>';
562
-
563
-		    // Multicurrency Amount TTC
564
-		    print '<tr><td>' . $form->editfieldkey('MulticurrencyAmountTTC', 'multicurrency_total_ttc', '', $object, 0) . '</td>';
565
-		    print '<td class="nowrap">' . price($object->multicurrency_total_ttc, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
566
-		    print '</tr>';
567
-		}
551
+        if (!empty($conf->multicurrency->enabled) && ($object->multicurrency_code != $conf->currency))
552
+        {
553
+            // Multicurrency Amount HT
554
+            print '<tr><td class="titlefieldmiddle">' . $form->editfieldkey('MulticurrencyAmountHT', 'multicurrency_total_ht', '', $object, 0) . '</td>';
555
+            print '<td class="nowrap">' . price($object->multicurrency_total_ht, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
556
+            print '</tr>';
568 557
 
569
-		// Total HT
570
-		print '<tr><td class="titlefieldmiddle">'.$langs->trans('AmountHT').'</td>';
571
-		print '<td>'.price($object->total_ht, 0, '', 1, -1, -1, $conf->currency).'</td>';
572
-		print '</tr>';
558
+            // Multicurrency Amount VAT
559
+            print '<tr><td>' . $form->editfieldkey('MulticurrencyAmountVAT', 'multicurrency_total_tva', '', $object, 0) . '</td>';
560
+            print '<td class="nowrap">' . price($object->multicurrency_total_tva, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
561
+            print '</tr>';
573 562
 
574
-		// Total VAT
575
-		print '<tr><td>'.$langs->trans('AmountVAT').'</td><td>'.price($object->total_tva, 0, '', 1, -1, -1, $conf->currency).'</td>';
576
-		print '</tr>';
563
+            // Multicurrency Amount TTC
564
+            print '<tr><td>' . $form->editfieldkey('MulticurrencyAmountTTC', 'multicurrency_total_ttc', '', $object, 0) . '</td>';
565
+            print '<td class="nowrap">' . price($object->multicurrency_total_ttc, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
566
+            print '</tr>';
567
+        }
577 568
 
578
-		// Amount Local Taxes
579
-		if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) 		// Localtax1
580
-		{
581
-		    print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
582
-		    print '<td>' . price($object->total_localtax1, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
583
-		}
584
-		if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) 		// Localtax2 IRPF
585
-		{
586
-		    print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
587
-		    print '<td>' . price($object->total_localtax2, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
588
-		}
569
+        // Total HT
570
+        print '<tr><td class="titlefieldmiddle">'.$langs->trans('AmountHT').'</td>';
571
+        print '<td>'.price($object->total_ht, 0, '', 1, -1, -1, $conf->currency).'</td>';
572
+        print '</tr>';
589 573
 
590
-		// Total TTC
591
-		print '<tr><td>'.$langs->trans('AmountTTC').'</td><td>'.price($object->total_ttc, 0, '', 1, -1, -1, $conf->currency).'</td>';
592
-		print '</tr>';
574
+        // Total VAT
575
+        print '<tr><td>'.$langs->trans('AmountVAT').'</td><td>'.price($object->total_tva, 0, '', 1, -1, -1, $conf->currency).'</td>';
576
+        print '</tr>';
593 577
 
594
-		print '</table>';
578
+        // Amount Local Taxes
579
+        if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) 		// Localtax1
580
+        {
581
+            print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
582
+            print '<td>' . price($object->total_localtax1, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
583
+        }
584
+        if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) 		// Localtax2 IRPF
585
+        {
586
+            print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
587
+            print '<td>' . price($object->total_localtax2, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
588
+        }
589
+
590
+        // Total TTC
591
+        print '<tr><td>'.$langs->trans('AmountTTC').'</td><td>'.price($object->total_ttc, 0, '', 1, -1, -1, $conf->currency).'</td>';
592
+        print '</tr>';
595 593
 
596
-		print '</div>';
597
-		print '</div>';
598
-		print '</div>';
594
+        print '</table>';
599 595
 
600
-		print '<div class="clearboth"></div><br>';
596
+        print '</div>';
597
+        print '</div>';
598
+        print '</div>';
601 599
 
600
+        print '<div class="clearboth"></div><br>';
602 601
 
603 602
 
604
-		/**
605
-		 *  Lines or orders with quantity shipped and remain to ship
606
-		 *  Note: Qty shipped are already available into $object->expeditions[fk_product]
607
-		 */
608
-		print '<table class="noborder noshadow" width="100%">';
609
-
610
-		$sql = "SELECT cd.rowid, cd.fk_product, cd.product_type as type, cd.label, cd.description,";
611
-		$sql.= " cd.price, cd.tva_tx, cd.subprice,";
612
-		$sql.= " cd.qty,";
613
-		$sql.= ' cd.date_start,';
614
-		$sql.= ' cd.date_end,';
615
-		$sql.= ' p.rowid as prodid, p.label as product_label, p.entity, p.ref, p.fk_product_type as product_type, p.description as product_desc';
616
-		$sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd";
617
-		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid";
618
-		$sql.= " WHERE cd.fk_commande = ".$object->id;
619
-		$sql.= " ORDER BY cd.rang, cd.rowid";
620
-
621
-		//print $sql;
622
-		dol_syslog("shipment.php", LOG_DEBUG);
623
-		$resql = $db->query($sql);
624
-		if ($resql)
625
-		{
626
-			$num = $db->num_rows($resql);
627
-			$i = 0;
628
-
629
-			print '<tr class="liste_titre">';
630
-			print '<td>'.$langs->trans("Description").'</td>';
631
-			print '<td align="center">'.$langs->trans("QtyOrdered").'</td>';
632
-			print '<td align="center">'.$langs->trans("QtyShipped").'</td>';
633
-			print '<td align="center">'.$langs->trans("KeepToShip").'</td>';
634
-			if (! empty($conf->stock->enabled))
635
-			{
636
-				print '<td align="center">'.$langs->trans("RealStock").'</td>';
637
-			}
638
-			else
639
-			{
640
-				print '<td>&nbsp;</td>';
641
-			}
642
-			print "</tr>\n";
643
-
644
-			$toBeShipped=array();
645
-			$toBeShippedTotal=0;
646
-			while ($i < $num)
647
-			{
648
-				$objp = $db->fetch_object($resql);
649
-
650
-
651
-				// Show product and description
652
-				$type=isset($objp->type)?$objp->type:$objp->product_type;
653
-
654
-				// Try to enhance type detection using date_start and date_end for free lines where type
655
-				// was not saved.
656
-				if (! empty($objp->date_start)) $type=1;
657
-				if (! empty($objp->date_end)) $type=1;
658
-
659
-				print '<tr class="oddeven">';
660
-
661
-				// Product label
662
-				if ($objp->fk_product > 0)
663
-				{
664
-					// Define output language
665
-					if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
666
-					{
667
-						$object->fetch_thirdparty();
668
-
669
-						$prod = new Product($db);
603
+
604
+        /**
605
+         *  Lines or orders with quantity shipped and remain to ship
606
+         *  Note: Qty shipped are already available into $object->expeditions[fk_product]
607
+         */
608
+        print '<table class="noborder noshadow" width="100%">';
609
+
610
+        $sql = "SELECT cd.rowid, cd.fk_product, cd.product_type as type, cd.label, cd.description,";
611
+        $sql.= " cd.price, cd.tva_tx, cd.subprice,";
612
+        $sql.= " cd.qty,";
613
+        $sql.= ' cd.date_start,';
614
+        $sql.= ' cd.date_end,';
615
+        $sql.= ' p.rowid as prodid, p.label as product_label, p.entity, p.ref, p.fk_product_type as product_type, p.description as product_desc';
616
+        $sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd";
617
+        $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid";
618
+        $sql.= " WHERE cd.fk_commande = ".$object->id;
619
+        $sql.= " ORDER BY cd.rang, cd.rowid";
620
+
621
+        //print $sql;
622
+        dol_syslog("shipment.php", LOG_DEBUG);
623
+        $resql = $db->query($sql);
624
+        if ($resql)
625
+        {
626
+            $num = $db->num_rows($resql);
627
+            $i = 0;
628
+
629
+            print '<tr class="liste_titre">';
630
+            print '<td>'.$langs->trans("Description").'</td>';
631
+            print '<td align="center">'.$langs->trans("QtyOrdered").'</td>';
632
+            print '<td align="center">'.$langs->trans("QtyShipped").'</td>';
633
+            print '<td align="center">'.$langs->trans("KeepToShip").'</td>';
634
+            if (! empty($conf->stock->enabled))
635
+            {
636
+                print '<td align="center">'.$langs->trans("RealStock").'</td>';
637
+            }
638
+            else
639
+            {
640
+                print '<td>&nbsp;</td>';
641
+            }
642
+            print "</tr>\n";
643
+
644
+            $toBeShipped=array();
645
+            $toBeShippedTotal=0;
646
+            while ($i < $num)
647
+            {
648
+                $objp = $db->fetch_object($resql);
649
+
650
+
651
+                // Show product and description
652
+                $type=isset($objp->type)?$objp->type:$objp->product_type;
653
+
654
+                // Try to enhance type detection using date_start and date_end for free lines where type
655
+                // was not saved.
656
+                if (! empty($objp->date_start)) $type=1;
657
+                if (! empty($objp->date_end)) $type=1;
658
+
659
+                print '<tr class="oddeven">';
660
+
661
+                // Product label
662
+                if ($objp->fk_product > 0)
663
+                {
664
+                    // Define output language
665
+                    if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
666
+                    {
667
+                        $object->fetch_thirdparty();
668
+
669
+                        $prod = new Product($db);
670 670
                         $prod->id = $objp->fk_product;
671 671
                         $prod->entity = $objp->entity;
672
-						$prod->getMultiLangs();
673
-
674
-						$outputlangs = $langs;
675
-						$newlang='';
676
-						if (empty($newlang) && ! empty($_REQUEST['lang_id'])) $newlang=$_REQUEST['lang_id'];
677
-						if (empty($newlang)) $newlang=$object->thirdparty->default_lang;
678
-						if (! empty($newlang))
679
-						{
680
-							$outputlangs = new Translate("",$conf);
681
-							$outputlangs->setDefaultLang($newlang);
682
-						}
683
-
684
-						$label = (! empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $objp->product_label;
685
-					}
686
-					else
687
-						$label = (! empty($objp->label)?$objp->label:$objp->product_label);
688
-
689
-					print '<td>';
690
-					print '<a name="'.$objp->rowid.'"></a>'; // ancre pour retourner sur la ligne
691
-
692
-					// Show product and description
693
-					$product_static->type=$type;
694
-					$product_static->id=$objp->fk_product;
695
-					$product_static->ref=$objp->ref;
672
+                        $prod->getMultiLangs();
673
+
674
+                        $outputlangs = $langs;
675
+                        $newlang='';
676
+                        if (empty($newlang) && ! empty($_REQUEST['lang_id'])) $newlang=$_REQUEST['lang_id'];
677
+                        if (empty($newlang)) $newlang=$object->thirdparty->default_lang;
678
+                        if (! empty($newlang))
679
+                        {
680
+                            $outputlangs = new Translate("",$conf);
681
+                            $outputlangs->setDefaultLang($newlang);
682
+                        }
683
+
684
+                        $label = (! empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $objp->product_label;
685
+                    }
686
+                    else
687
+                        $label = (! empty($objp->label)?$objp->label:$objp->product_label);
688
+
689
+                    print '<td>';
690
+                    print '<a name="'.$objp->rowid.'"></a>'; // ancre pour retourner sur la ligne
691
+
692
+                    // Show product and description
693
+                    $product_static->type=$type;
694
+                    $product_static->id=$objp->fk_product;
695
+                    $product_static->ref=$objp->ref;
696 696
                     $product_static->entity = $objp->entity;
697
-					$text=$product_static->getNomUrl(1);
698
-					$text.= ' - '.$label;
699
-					$description=($conf->global->PRODUIT_DESC_IN_FORM?'':dol_htmlentitiesbr($objp->description)).'<br>';
697
+                    $text=$product_static->getNomUrl(1);
698
+                    $text.= ' - '.$label;
699
+                    $description=($conf->global->PRODUIT_DESC_IN_FORM?'':dol_htmlentitiesbr($objp->description)).'<br>';
700 700
                     $description.= $product_static->show_photos('product', $conf->product->multidir_output[$product_static->entity], 1, 1, 0, 0, 0, 80);
701
-					print $form->textwithtooltip($text,$description,3,'','',$i);
702
-
703
-					// Show range
704
-					print_date_range($db->jdate($objp->date_start),$db->jdate($objp->date_end));
705
-
706
-					// Add description in form
707
-					if (! empty($conf->global->PRODUIT_DESC_IN_FORM))
708
-					{
709
-						print ($objp->description && $objp->description!=$objp->product_label)?'<br>'.dol_htmlentitiesbr($objp->description):'';
710
-					}
711
-
712
-					print '</td>';
713
-				}
714
-				else
715
-				{
716
-					print "<td>";
717
-					if ($type==1) $text = img_object($langs->trans('Service'),'service');
718
-					else $text = img_object($langs->trans('Product'),'product');
719
-
720
-					if (! empty($objp->label)) {
721
-						$text.= ' <strong>'.$objp->label.'</strong>';
722
-						print $form->textwithtooltip($text,$objp->description,3,'','',$i);
723
-					} else {
724
-						print $text.' '.nl2br($objp->description);
725
-					}
726
-
727
-					// Show range
728
-					print_date_range($db->jdate($objp->date_start),$db->jdate($objp->date_end));
729
-					print "</td>\n";
730
-				}
731
-
732
-				// Qty ordered
733
-				print '<td align="center">' . $objp->qty . '</td>';
734
-
735
-				// Qty already shipped
736
-				$qtyProdCom=$objp->qty;
737
-				print '<td align="center">';
738
-				// Nb of sending products for this line of order
739
-				$qtyAlreadyShipped = (! empty($object->expeditions[$objp->rowid])?$object->expeditions[$objp->rowid]:0);
740
-				print $qtyAlreadyShipped;
741
-				print '</td>';
742
-
743
-				// Qty remains to ship
744
-				print '<td align="center">';
745
-				if ($type == 0 || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
746
-				{
747
-					$toBeShipped[$objp->fk_product] = $objp->qty - $qtyAlreadyShipped;
748
-					$toBeShippedTotal += $toBeShipped[$objp->fk_product];
749
-					print $toBeShipped[$objp->fk_product];
750
-				}
751
-				else
752
-				{
753
-					print '0 ('.$langs->trans("Service").')';
754
-				}
755
-				print '</td>';
756
-
757
-				if ($objp->fk_product > 0)
758
-				{
759
-					$product = new Product($db);
760
-					$product->fetch($objp->fk_product);
761
-					$product->load_stock('warehouseopen');
762
-				}
763
-
764
-				if ($objp->fk_product > 0 && ($type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) && ! empty($conf->stock->enabled))
765
-				{
766
-					print '<td align="center">';
767
-					print $product->stock_reel;
768
-					if ($product->stock_reel < $toBeShipped[$objp->fk_product])
769
-					{
770
-						print ' '.img_warning($langs->trans("StockTooLow"));
771
-					}
772
-					print '</td>';
773
-				}
774
-				else
775
-				{
776
-					print '<td>&nbsp;</td>';
777
-				}
778
-				print "</tr>\n";
779
-
780
-				// Show subproducts lines
781
-				if ($objp->fk_product > 0 && ! empty($conf->global->PRODUIT_SOUSPRODUITS))
782
-				{
783
-					// Set tree of subproducts in product->sousprods
784
-					$product->get_sousproduits_arbo();
785
-					//var_dump($product->sousprods);exit;
786
-
787
-					// Define a new tree with quantiies recalculated
788
-					$prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
789
-					//var_dump($prods_arbo);
790
-					if (count($prods_arbo) > 0)
791
-					{
792
-						foreach($prods_arbo as $key => $value)
793
-						{
794
-							$img='';
795
-							if ($value['stock'] < $value['stock_alert'])
796
-							{
797
-								$img=img_warning($langs->trans("StockTooLow"));
798
-							}
799
-							print '<tr class="oddeven"><td>&nbsp; &nbsp; &nbsp; -> <a href="'.DOL_URL_ROOT."/product/card.php?id=".$value['id'].'">'.$value['fullpath'].'</a> ('.$value['nb'].')</td>';
800
-							print '<td align="center"> '.$value['nb_total'].'</td>';
801
-							print '<td>&nbsp</td>';
802
-							print '<td>&nbsp</td>';
803
-							print '<td align="center">'.$value['stock'].' '.$img.'</td></tr>'."\n";
804
-						}
805
-					}
806
-				}
807
-
808
-				$i++;
809
-			}
810
-			$db->free($resql);
811
-
812
-			if (! $num)
813
-			{
814
-				print '<tr '.$bc[false].'><td colspan="5">'.$langs->trans("NoArticleOfTypeProduct").'<br>';
815
-			}
816
-
817
-			print "</table>";
818
-		}
819
-		else
820
-		{
821
-			dol_print_error($db);
822
-		}
701
+                    print $form->textwithtooltip($text,$description,3,'','',$i);
702
+
703
+                    // Show range
704
+                    print_date_range($db->jdate($objp->date_start),$db->jdate($objp->date_end));
705
+
706
+                    // Add description in form
707
+                    if (! empty($conf->global->PRODUIT_DESC_IN_FORM))
708
+                    {
709
+                        print ($objp->description && $objp->description!=$objp->product_label)?'<br>'.dol_htmlentitiesbr($objp->description):'';
710
+                    }
711
+
712
+                    print '</td>';
713
+                }
714
+                else
715
+                {
716
+                    print "<td>";
717
+                    if ($type==1) $text = img_object($langs->trans('Service'),'service');
718
+                    else $text = img_object($langs->trans('Product'),'product');
719
+
720
+                    if (! empty($objp->label)) {
721
+                        $text.= ' <strong>'.$objp->label.'</strong>';
722
+                        print $form->textwithtooltip($text,$objp->description,3,'','',$i);
723
+                    } else {
724
+                        print $text.' '.nl2br($objp->description);
725
+                    }
726
+
727
+                    // Show range
728
+                    print_date_range($db->jdate($objp->date_start),$db->jdate($objp->date_end));
729
+                    print "</td>\n";
730
+                }
731
+
732
+                // Qty ordered
733
+                print '<td align="center">' . $objp->qty . '</td>';
734
+
735
+                // Qty already shipped
736
+                $qtyProdCom=$objp->qty;
737
+                print '<td align="center">';
738
+                // Nb of sending products for this line of order
739
+                $qtyAlreadyShipped = (! empty($object->expeditions[$objp->rowid])?$object->expeditions[$objp->rowid]:0);
740
+                print $qtyAlreadyShipped;
741
+                print '</td>';
742
+
743
+                // Qty remains to ship
744
+                print '<td align="center">';
745
+                if ($type == 0 || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
746
+                {
747
+                    $toBeShipped[$objp->fk_product] = $objp->qty - $qtyAlreadyShipped;
748
+                    $toBeShippedTotal += $toBeShipped[$objp->fk_product];
749
+                    print $toBeShipped[$objp->fk_product];
750
+                }
751
+                else
752
+                {
753
+                    print '0 ('.$langs->trans("Service").')';
754
+                }
755
+                print '</td>';
756
+
757
+                if ($objp->fk_product > 0)
758
+                {
759
+                    $product = new Product($db);
760
+                    $product->fetch($objp->fk_product);
761
+                    $product->load_stock('warehouseopen');
762
+                }
763
+
764
+                if ($objp->fk_product > 0 && ($type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) && ! empty($conf->stock->enabled))
765
+                {
766
+                    print '<td align="center">';
767
+                    print $product->stock_reel;
768
+                    if ($product->stock_reel < $toBeShipped[$objp->fk_product])
769
+                    {
770
+                        print ' '.img_warning($langs->trans("StockTooLow"));
771
+                    }
772
+                    print '</td>';
773
+                }
774
+                else
775
+                {
776
+                    print '<td>&nbsp;</td>';
777
+                }
778
+                print "</tr>\n";
779
+
780
+                // Show subproducts lines
781
+                if ($objp->fk_product > 0 && ! empty($conf->global->PRODUIT_SOUSPRODUITS))
782
+                {
783
+                    // Set tree of subproducts in product->sousprods
784
+                    $product->get_sousproduits_arbo();
785
+                    //var_dump($product->sousprods);exit;
786
+
787
+                    // Define a new tree with quantiies recalculated
788
+                    $prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
789
+                    //var_dump($prods_arbo);
790
+                    if (count($prods_arbo) > 0)
791
+                    {
792
+                        foreach($prods_arbo as $key => $value)
793
+                        {
794
+                            $img='';
795
+                            if ($value['stock'] < $value['stock_alert'])
796
+                            {
797
+                                $img=img_warning($langs->trans("StockTooLow"));
798
+                            }
799
+                            print '<tr class="oddeven"><td>&nbsp; &nbsp; &nbsp; -> <a href="'.DOL_URL_ROOT."/product/card.php?id=".$value['id'].'">'.$value['fullpath'].'</a> ('.$value['nb'].')</td>';
800
+                            print '<td align="center"> '.$value['nb_total'].'</td>';
801
+                            print '<td>&nbsp</td>';
802
+                            print '<td>&nbsp</td>';
803
+                            print '<td align="center">'.$value['stock'].' '.$img.'</td></tr>'."\n";
804
+                        }
805
+                    }
806
+                }
807
+
808
+                $i++;
809
+            }
810
+            $db->free($resql);
811
+
812
+            if (! $num)
813
+            {
814
+                print '<tr '.$bc[false].'><td colspan="5">'.$langs->trans("NoArticleOfTypeProduct").'<br>';
815
+            }
823 816
 
824
-		print '</div>';
817
+            print "</table>";
818
+        }
819
+        else
820
+        {
821
+            dol_print_error($db);
822
+        }
825 823
 
824
+        print '</div>';
826 825
 
827
-		/*
826
+
827
+        /*
828 828
 		 * Boutons Actions
829 829
 		 */
830 830
 
831
-		if (empty($user->societe_id))
832
-		{
833
-			print '<div class="tabsAction">';
831
+        if (empty($user->societe_id))
832
+        {
833
+            print '<div class="tabsAction">';
834 834
 
835 835
             // Bouton expedier sans gestion des stocks
836 836
             if (empty($conf->stock->enabled) && ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED))
837
-			{
838
-				if ($user->rights->expedition->creer)
839
-				{
840
-					print '<a class="butAction" href="'.DOL_URL_ROOT.'/expedition/card.php?action=create&amp;origin=commande&amp;object_id='.$id.'">'.$langs->trans("CreateShipment").'</a>';
841
-					if ($toBeShippedTotal <= 0)
842
-					{
843
-						print ' '.img_warning($langs->trans("WarningNoQtyLeftToSend"));
844
-					}
845
-				}
846
-				else
847
-				{
848
-					print '<a class="butActionRefused classfortooltip" href="#">'.$langs->trans("CreateShipment").'</a>';
849
-				}
850
-			}
851
-			print "</div>";
852
-		}
837
+            {
838
+                if ($user->rights->expedition->creer)
839
+                {
840
+                    print '<a class="butAction" href="'.DOL_URL_ROOT.'/expedition/card.php?action=create&amp;origin=commande&amp;object_id='.$id.'">'.$langs->trans("CreateShipment").'</a>';
841
+                    if ($toBeShippedTotal <= 0)
842
+                    {
843
+                        print ' '.img_warning($langs->trans("WarningNoQtyLeftToSend"));
844
+                    }
845
+                }
846
+                else
847
+                {
848
+                    print '<a class="butActionRefused classfortooltip" href="#">'.$langs->trans("CreateShipment").'</a>';
849
+                }
850
+            }
851
+            print "</div>";
852
+        }
853 853
 
854 854
 
855 855
         // Bouton expedier avec gestion des stocks
@@ -859,69 +859,69 @@  discard block
 block discarded – undo
859 859
             print $langs->trans("ValidateOrderFirstBeforeShipment");
860 860
         }
861 861
 
862
-		if (! empty($conf->stock->enabled) && ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED))
863
-		{
864
-			if ($user->rights->expedition->creer)
865
-			{
866
-				//print load_fiche_titre($langs->trans("CreateShipment"));
862
+        if (! empty($conf->stock->enabled) && ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED))
863
+        {
864
+            if ($user->rights->expedition->creer)
865
+            {
866
+                //print load_fiche_titre($langs->trans("CreateShipment"));
867 867
                 print '<div class="tabsAction">';
868 868
 
869
-				print '<form method="GET" action="'.DOL_URL_ROOT.'/expedition/card.php">';
870
-				print '<input type="hidden" name="action" value="create">';
871
-				//print '<input type="hidden" name="id" value="'.$object->id.'">';
869
+                print '<form method="GET" action="'.DOL_URL_ROOT.'/expedition/card.php">';
870
+                print '<input type="hidden" name="action" value="create">';
871
+                //print '<input type="hidden" name="id" value="'.$object->id.'">';
872 872
                 print '<input type="hidden" name="shipping_method_id" value="'.$object->shipping_method_id.'">';
873
-				print '<input type="hidden" name="origin" value="commande">';
874
-				print '<input type="hidden" name="origin_id" value="'.$object->id.'">';
875
-				print '<input type="hidden" name="projectid" value="'.$object->fk_project.'">';
876
-				//print '<table class="border" width="100%">';
877
-
878
-				$langs->load("stocks");
879
-
880
-				//print '<tr>';
881
-
882
-				if (! empty($conf->stock->enabled))
883
-				{
884
-					//print '<td>';
885
-					print $langs->trans("WarehouseSource");
886
-					//print '</td>';
887
-					//print '<td>';
888
-					print $formproduct->selectWarehouses(! empty($object->warehouse_id)?$object->warehouse_id:-1, 'entrepot_id', '', 1, 0, 0, '', 0, 0, array(), 'minwidth200');
889
-					if (count($formproduct->cache_warehouses) <= 0)
890
-					{
891
-						print ' &nbsp; '.$langs->trans("WarehouseSourceNotDefined").' <a href="'.DOL_URL_ROOT.'/product/stock/card.php?action=create">'.$langs->trans("AddOne").'</a>';
892
-					}
893
-					//print '</td>';
894
-				}
895
-				//print '<td align="center">';
896
-				print '<input type="submit" class="butAction" named="save" value="'.$langs->trans("CreateShipment").'">';
897
-				if ($toBeShippedTotal <= 0)
898
-				{
899
-					print ' '.img_warning($langs->trans("WarningNoQtyLeftToSend"));
900
-				}
901
-				//print '</td></tr>';
902
-
903
-				//print "</table>";
904
-				print "</form>\n";
905
-
906
-				print '</div>';
907
-
908
-				$somethingshown=1;
909
-			}
910
-			else
911
-			{
912
-				print '<div class="tabsAction">';
913
-				print '<a class="butActionRefused classfortooltip" href="#">'.$langs->trans("CreateShipment").'</a>';
914
-				print '</div>';
915
-			}
916
-		}
873
+                print '<input type="hidden" name="origin" value="commande">';
874
+                print '<input type="hidden" name="origin_id" value="'.$object->id.'">';
875
+                print '<input type="hidden" name="projectid" value="'.$object->fk_project.'">';
876
+                //print '<table class="border" width="100%">';
877
+
878
+                $langs->load("stocks");
879
+
880
+                //print '<tr>';
881
+
882
+                if (! empty($conf->stock->enabled))
883
+                {
884
+                    //print '<td>';
885
+                    print $langs->trans("WarehouseSource");
886
+                    //print '</td>';
887
+                    //print '<td>';
888
+                    print $formproduct->selectWarehouses(! empty($object->warehouse_id)?$object->warehouse_id:-1, 'entrepot_id', '', 1, 0, 0, '', 0, 0, array(), 'minwidth200');
889
+                    if (count($formproduct->cache_warehouses) <= 0)
890
+                    {
891
+                        print ' &nbsp; '.$langs->trans("WarehouseSourceNotDefined").' <a href="'.DOL_URL_ROOT.'/product/stock/card.php?action=create">'.$langs->trans("AddOne").'</a>';
892
+                    }
893
+                    //print '</td>';
894
+                }
895
+                //print '<td align="center">';
896
+                print '<input type="submit" class="butAction" named="save" value="'.$langs->trans("CreateShipment").'">';
897
+                if ($toBeShippedTotal <= 0)
898
+                {
899
+                    print ' '.img_warning($langs->trans("WarningNoQtyLeftToSend"));
900
+                }
901
+                //print '</td></tr>';
902
+
903
+                //print "</table>";
904
+                print "</form>\n";
905
+
906
+                print '</div>';
907
+
908
+                $somethingshown=1;
909
+            }
910
+            else
911
+            {
912
+                print '<div class="tabsAction">';
913
+                print '<a class="butActionRefused classfortooltip" href="#">'.$langs->trans("CreateShipment").'</a>';
914
+                print '</div>';
915
+            }
916
+        }
917 917
 
918
-		show_list_sending_receive('commande',$object->id);
919
-	}
920
-	else
921
-	{
922
-		/* Order not found */
923
-		setEventMessages($langs->trans("NonExistentOrder"), null, 'errors');
924
-	}
918
+        show_list_sending_receive('commande',$object->id);
919
+    }
920
+    else
921
+    {
922
+        /* Order not found */
923
+        setEventMessages($langs->trans("NonExistentOrder"), null, 'errors');
924
+    }
925 925
 }
926 926
 
927 927
 // End of page
Please login to merge, or discard this patch.
dolibarr/htdocs/expedition/document.php 1 patch
Indentation   +94 added lines, -94 removed lines patch added patch discarded remove patch
@@ -34,7 +34,7 @@  discard block
 block discarded – undo
34 34
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
35 35
 require_once DOL_DOCUMENT_ROOT .'/expedition/class/expedition.class.php';
36 36
 if (! empty($conf->projet->enabled)) {
37
-	require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
37
+    require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
38 38
 }
39 39
 
40 40
 // Load translation files required by the page
@@ -48,7 +48,7 @@  discard block
 block discarded – undo
48 48
 // Security check
49 49
 if ($user->societe_id)
50 50
 {
51
-	$socid = $user->societe_id;
51
+    $socid = $user->societe_id;
52 52
 }
53 53
 $result=restrictedArea($user,'expedition',$id,'');
54 54
 
@@ -71,8 +71,8 @@  discard block
 block discarded – undo
71 71
  */
72 72
 if ($object->fetch($id))
73 73
 {
74
-	$object->fetch_thirdparty();
75
-	$upload_dir = $conf->expedition->dir_output . "/sending/" . dol_sanitizeFileName($object->ref);
74
+    $object->fetch_thirdparty();
75
+    $upload_dir = $conf->expedition->dir_output . "/sending/" . dol_sanitizeFileName($object->ref);
76 76
 }
77 77
 
78 78
 include_once DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php';
@@ -87,102 +87,102 @@  discard block
 block discarded – undo
87 87
 $form = new Form($db);
88 88
 
89 89
 if ($id > 0 || ! empty($ref)){
90
-	if ($object->fetch($id, $ref)){
91
-		$object->fetch_thirdparty();
90
+    if ($object->fetch($id, $ref)){
91
+        $object->fetch_thirdparty();
92 92
 
93
-		$upload_dir = $conf->expedition->dir_output.'/sending/'.dol_sanitizeFileName($object->ref);
93
+        $upload_dir = $conf->expedition->dir_output.'/sending/'.dol_sanitizeFileName($object->ref);
94 94
 
95
-		$head = shipping_prepare_head($object);
96
-		dol_fiche_head($head, 'documents', $langs->trans("Shipment"), -1, 'sending');
95
+        $head = shipping_prepare_head($object);
96
+        dol_fiche_head($head, 'documents', $langs->trans("Shipment"), -1, 'sending');
97 97
 	
98 98
 
99
-		// Build file list
100
-		$filearray=dol_dir_list($upload_dir,"files",0,'','(\.meta|_preview.*\.png)$',$sortfield,(strtolower($sortorder)=='desc'?SORT_DESC:SORT_ASC),1);
101
-		$totalsize=0;
102
-		foreach($filearray as $key => $file){
103
-		    $totalsize+=$file['size'];
104
-		}
105
-
106
-		// Shipment card
107
-		$linkback = '<a href="'.DOL_URL_ROOT.'/expedition/list.php?restore_lastsearch_values=1' . (! empty($socid) ? '&socid=' . $socid : '') . '">'.$langs->trans("BackToList").'</a>';
108
-
109
-
110
-		$morehtmlref='<div class="refidno">';
111
-		// Ref customer
112
-		$morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1);
113
-		$morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1);
114
-		// Thirdparty
115
-		$morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1);
116
-
117
-		// Project
118
-		if (! empty($conf->projet->enabled)) {
119
-			$langs->load("projects");
120
-			$morehtmlref .= '<br>' . $langs->trans('Project') . ' ';
121
-			if (0) {    // Do not change on shipment
122
-				if ($action != 'classify') {
123
-					$morehtmlref .= '<a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
124
-				}
125
-				if ($action == 'classify') {
126
-					// $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
127
-					$morehtmlref .= '<form method="post" action="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '">';
128
-					$morehtmlref .= '<input type="hidden" name="action" value="classin">';
129
-					$morehtmlref .= '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
130
-					$morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
131
-					$morehtmlref .= '<input type="submit" class="button" value="' . $langs->trans("Modify") . '">';
132
-					$morehtmlref .= '</form>';
133
-				} else {
134
-					$morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
135
-				}
136
-			} else {
137
-				// We don't have project on shipment, so we will use the project or source object instead
138
-				// TODO Add project on shipment
139
-				$morehtmlref .= ' : ';
140
-				if (! empty($objectsrc->fk_project)) {
141
-					$proj = new Project($db);
142
-					$proj->fetch($objectsrc->fk_project);
143
-					$morehtmlref .= '<a href="' . DOL_URL_ROOT . '/projet/card.php?id=' . $objectsrc->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
144
-					$morehtmlref .= $proj->ref;
145
-					$morehtmlref .= '</a>';
146
-				} else {
147
-					$morehtmlref .= '';
148
-				}
149
-			}
150
-		}
151
-		$morehtmlref.='</div>';
152
-
153
-		// Order card
154
-
155
-		$linkback = '<a href="' . DOL_URL_ROOT . '/expedition/list.php' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
156
-
157
-		dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
158
-
159
-		print '<div class="fichecenter">';
160
-		print '<div class="underbanner clearboth"></div>';
161
-
162
-		print '<table class="border" width="100%">';
163
-
164
-		print '<tr><td class="titlefield">'.$langs->trans("NbOfAttachedFiles").'</td><td colspan="3">'.count($filearray).'</td></tr>';
165
-		print '<tr><td>'.$langs->trans("TotalSizeOfAttachedFiles").'</td><td colspan="3">'.dol_print_size($totalsize,1,1).'</td></tr>';
166
-
167
-		print "</table>\n";
168
-
169
-		print "</div>\n";
170
-
171
-		print dol_fiche_end();
172
-
173
-		$modulepart = 'expedition';
174
-		$permission = $user->rights->expedition->creer;
175
-		$permtoedit = $user->rights->expedition->creer;
176
-		$param = '&id=' . $object->id;
177
-		include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_post_headers.tpl.php';
178
-	}
179
-	else{
180
-		dol_print_error($db);
181
-	}
99
+        // Build file list
100
+        $filearray=dol_dir_list($upload_dir,"files",0,'','(\.meta|_preview.*\.png)$',$sortfield,(strtolower($sortorder)=='desc'?SORT_DESC:SORT_ASC),1);
101
+        $totalsize=0;
102
+        foreach($filearray as $key => $file){
103
+            $totalsize+=$file['size'];
104
+        }
105
+
106
+        // Shipment card
107
+        $linkback = '<a href="'.DOL_URL_ROOT.'/expedition/list.php?restore_lastsearch_values=1' . (! empty($socid) ? '&socid=' . $socid : '') . '">'.$langs->trans("BackToList").'</a>';
108
+
109
+
110
+        $morehtmlref='<div class="refidno">';
111
+        // Ref customer
112
+        $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1);
113
+        $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1);
114
+        // Thirdparty
115
+        $morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1);
116
+
117
+        // Project
118
+        if (! empty($conf->projet->enabled)) {
119
+            $langs->load("projects");
120
+            $morehtmlref .= '<br>' . $langs->trans('Project') . ' ';
121
+            if (0) {    // Do not change on shipment
122
+                if ($action != 'classify') {
123
+                    $morehtmlref .= '<a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
124
+                }
125
+                if ($action == 'classify') {
126
+                    // $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
127
+                    $morehtmlref .= '<form method="post" action="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '">';
128
+                    $morehtmlref .= '<input type="hidden" name="action" value="classin">';
129
+                    $morehtmlref .= '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
130
+                    $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
131
+                    $morehtmlref .= '<input type="submit" class="button" value="' . $langs->trans("Modify") . '">';
132
+                    $morehtmlref .= '</form>';
133
+                } else {
134
+                    $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
135
+                }
136
+            } else {
137
+                // We don't have project on shipment, so we will use the project or source object instead
138
+                // TODO Add project on shipment
139
+                $morehtmlref .= ' : ';
140
+                if (! empty($objectsrc->fk_project)) {
141
+                    $proj = new Project($db);
142
+                    $proj->fetch($objectsrc->fk_project);
143
+                    $morehtmlref .= '<a href="' . DOL_URL_ROOT . '/projet/card.php?id=' . $objectsrc->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
144
+                    $morehtmlref .= $proj->ref;
145
+                    $morehtmlref .= '</a>';
146
+                } else {
147
+                    $morehtmlref .= '';
148
+                }
149
+            }
150
+        }
151
+        $morehtmlref.='</div>';
152
+
153
+        // Order card
154
+
155
+        $linkback = '<a href="' . DOL_URL_ROOT . '/expedition/list.php' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
156
+
157
+        dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
158
+
159
+        print '<div class="fichecenter">';
160
+        print '<div class="underbanner clearboth"></div>';
161
+
162
+        print '<table class="border" width="100%">';
163
+
164
+        print '<tr><td class="titlefield">'.$langs->trans("NbOfAttachedFiles").'</td><td colspan="3">'.count($filearray).'</td></tr>';
165
+        print '<tr><td>'.$langs->trans("TotalSizeOfAttachedFiles").'</td><td colspan="3">'.dol_print_size($totalsize,1,1).'</td></tr>';
166
+
167
+        print "</table>\n";
168
+
169
+        print "</div>\n";
170
+
171
+        print dol_fiche_end();
172
+
173
+        $modulepart = 'expedition';
174
+        $permission = $user->rights->expedition->creer;
175
+        $permtoedit = $user->rights->expedition->creer;
176
+        $param = '&id=' . $object->id;
177
+        include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_post_headers.tpl.php';
178
+    }
179
+    else{
180
+        dol_print_error($db);
181
+    }
182 182
 }
183 183
 else{
184
-	header('Location: index.php');
185
-	exit;
184
+    header('Location: index.php');
185
+    exit;
186 186
 }
187 187
 
188 188
 // End of page
Please login to merge, or discard this patch.
dolibarr/htdocs/expedition/note.php 1 patch
Indentation   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -91,19 +91,19 @@  discard block
 block discarded – undo
91 91
 if ($id > 0 || ! empty($ref))
92 92
 {
93 93
 
94
-	$head=shipping_prepare_head($object);
95
-	dol_fiche_head($head, 'note', $langs->trans("Shipment"), -1, 'sending');
94
+    $head=shipping_prepare_head($object);
95
+    dol_fiche_head($head, 'note', $langs->trans("Shipment"), -1, 'sending');
96 96
 
97 97
 
98
-	// Shipment card
99
-	$linkback = '<a href="'.DOL_URL_ROOT.'/expedition/list.php?restore_lastsearch_values=1' . (! empty($socid) ? '&socid=' . $socid : '') . '">'.$langs->trans("BackToList").'</a>';
98
+    // Shipment card
99
+    $linkback = '<a href="'.DOL_URL_ROOT.'/expedition/list.php?restore_lastsearch_values=1' . (! empty($socid) ? '&socid=' . $socid : '') . '">'.$langs->trans("BackToList").'</a>';
100 100
 
101
-	$morehtmlref='<div class="refidno">';
102
-	// Ref customer shipment
103
-	$morehtmlref.=$form->editfieldkey("RefCustomer", '', $object->ref_customer, $object, $user->rights->expedition->creer, 'string', '', 0, 1);
104
-	$morehtmlref.=$form->editfieldval("RefCustomer", '', $object->ref_customer, $object, $user->rights->expedition->creer, 'string', '', null, null, '', 1);
105
-	// Thirdparty
106
-	$morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1);
101
+    $morehtmlref='<div class="refidno">';
102
+    // Ref customer shipment
103
+    $morehtmlref.=$form->editfieldkey("RefCustomer", '', $object->ref_customer, $object, $user->rights->expedition->creer, 'string', '', 0, 1);
104
+    $morehtmlref.=$form->editfieldval("RefCustomer", '', $object->ref_customer, $object, $user->rights->expedition->creer, 'string', '', null, null, '', 1);
105
+    // Thirdparty
106
+    $morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1);
107 107
     // Project
108 108
     if (! empty($conf->projet->enabled)) {
109 109
         $langs->load("projects");
@@ -146,10 +146,10 @@  discard block
 block discarded – undo
146 146
 
147 147
     print '<div class="underbanner clearboth"></div>';
148 148
 
149
-	$cssclass='titlefield';
150
-	include DOL_DOCUMENT_ROOT.'/core/tpl/notes.tpl.php';
149
+    $cssclass='titlefield';
150
+    include DOL_DOCUMENT_ROOT.'/core/tpl/notes.tpl.php';
151 151
 
152
-	dol_fiche_end();
152
+    dol_fiche_end();
153 153
 }
154 154
 
155 155
 // End of page
Please login to merge, or discard this patch.