|
1
|
|
|
<?php |
|
2
|
|
|
/* Copyright (C) 2003-2008 Rodolphe Quiedeville <[email protected]> |
|
3
|
|
|
* Copyright (C) 2005-2012 Regis Houssin <[email protected]> |
|
4
|
|
|
* Copyright (C) 2007 Franky Van Liedekerke <[email protected]> |
|
5
|
|
|
* Copyright (C) 2006-2012 Laurent Destailleur <[email protected]> |
|
6
|
|
|
* Copyright (C) 2011-2017 Juanjo Menent <[email protected]> |
|
7
|
|
|
* Copyright (C) 2013 Florian Henry <[email protected]> |
|
8
|
|
|
* Copyright (C) 2014 Cedric GROSS <[email protected]> |
|
9
|
|
|
* Copyright (C) 2014-2015 Marcos García <[email protected]> |
|
10
|
|
|
* Copyright (C) 2014-2017 Francis Appels <[email protected]> |
|
11
|
|
|
* Copyright (C) 2015 Claudio Aschieri <[email protected]> |
|
12
|
|
|
* Copyright (C) 2016 Ferran Marcet <[email protected]> |
|
13
|
|
|
* Copyright (C) 2018 Nicolas ZABOURI <[email protected]> |
|
14
|
|
|
* Copyright (C) 2018 Frédéric France <[email protected]> |
|
15
|
|
|
* |
|
16
|
|
|
* This program is free software; you can redistribute it and/or modify |
|
17
|
|
|
* it under the terms of the GNU General Public License as published by |
|
18
|
|
|
* the Free Software Foundation; either version 3 of the License, or |
|
19
|
|
|
* (at your option) any later version. |
|
20
|
|
|
* |
|
21
|
|
|
* This program is distributed in the hope that it will be useful, |
|
22
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
23
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
24
|
|
|
* GNU General Public License for more details. |
|
25
|
|
|
* |
|
26
|
|
|
* You should have received a copy of the GNU General Public License |
|
27
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
28
|
|
|
*/ |
|
29
|
|
|
|
|
30
|
|
|
/** |
|
31
|
|
|
* \file htdocs/expedition/class/expedition.class.php |
|
32
|
|
|
* \ingroup expedition |
|
33
|
|
|
* \brief Fichier de la classe de gestion des expeditions |
|
34
|
|
|
*/ |
|
35
|
|
|
|
|
36
|
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; |
|
37
|
|
|
require_once DOL_DOCUMENT_ROOT."/core/class/commonobjectline.class.php"; |
|
38
|
|
|
if (! empty($conf->propal->enabled)) require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; |
|
39
|
|
|
if (! empty($conf->commande->enabled)) require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; |
|
40
|
|
|
if (! empty($conf->productbatch->enabled)) require_once DOL_DOCUMENT_ROOT.'/expedition/class/expeditionbatch.class.php'; |
|
41
|
|
|
|
|
42
|
|
|
|
|
43
|
|
|
/** |
|
44
|
|
|
* Class to manage shipments |
|
45
|
|
|
*/ |
|
46
|
|
|
class Expedition extends CommonObject |
|
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
|
|
|
} |
|
436
|
|
|
|
|
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
|
|
|
} |
|
463
|
|
|
|
|
464
|
|
|
|
|
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 |
|
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
|
|
|
} |
|
863
|
|
|
|
|
864
|
|
|
|
|
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; |
|
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
|
|
|
} |
|
973
|
|
|
|
|
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; |
|
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
|
|
|
} |
|
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
|
|
|
} |
|
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
|
|
|
} |
|
1362
|
|
|
|
|
1363
|
|
|
// 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
|
|
|
} |
|
1650
|
|
|
|
|
1651
|
|
|
// 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
|
|
|
{ |
|
1661
|
|
|
// phpcs:enable |
|
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
|
|
|
} |
|
1810
|
|
|
|
|
1811
|
|
|
// 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
|
|
|
{ |
|
1819
|
|
|
// phpcs:enable |
|
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
|
|
|
} |
|
1838
|
|
|
|
|
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
|
|
|
} |
|
1874
|
|
|
|
|
1875
|
|
|
// 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
|
|
|
{ |
|
1885
|
|
|
// 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
|
|
|
} |
|
1904
|
|
|
|
|
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; |
|
1918
|
|
|
|
|
1919
|
|
|
$resql = $this->db->query($sql); |
|
1920
|
|
|
} |
|
1921
|
|
|
|
|
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; |
|
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
|
|
|
} |
|
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
|
|
|
|
|
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
|
|
|
{ |
|
2133
|
|
|
// phpcs:enable |
|
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
|
|
|
} |
|
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
|
|
|
} |
|
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
|
|
|
} |
|
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
|
|
|
} |
|
2347
|
|
|
} |
|
2348
|
|
|
|
|
2349
|
|
|
|
|
2350
|
|
|
/** |
|
2351
|
|
|
* Classe de gestion des lignes de bons d'expedition |
|
2352
|
|
|
*/ |
|
2353
|
|
|
class ExpeditionLigne extends CommonObjectLine |
|
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
|
|
|
/** |
|
2372
|
|
|
* @var int ID |
|
2373
|
|
|
*/ |
|
2374
|
|
|
public $fk_origin_line; |
|
2375
|
|
|
|
|
2376
|
|
|
/** |
|
2377
|
|
|
* @var int Id of shipment |
|
2378
|
|
|
*/ |
|
2379
|
|
|
public $fk_expedition; |
|
2380
|
|
|
|
|
2381
|
|
|
/** |
|
2382
|
|
|
* @var DoliDB Database handler. |
|
2383
|
|
|
*/ |
|
2384
|
|
|
public $db; |
|
2385
|
|
|
|
|
2386
|
|
|
/** |
|
2387
|
|
|
* @var float qty asked From llx_expeditiondet |
|
2388
|
|
|
*/ |
|
2389
|
|
|
public $qty; |
|
2390
|
|
|
|
|
2391
|
|
|
/** |
|
2392
|
|
|
* @var float qty shipped |
|
2393
|
|
|
*/ |
|
2394
|
|
|
public $qty_shipped; |
|
2395
|
|
|
|
|
2396
|
|
|
/** |
|
2397
|
|
|
* @var int Id of product |
|
2398
|
|
|
*/ |
|
2399
|
|
|
public $fk_product; |
|
2400
|
|
|
public $detail_batch; |
|
2401
|
|
|
|
|
2402
|
|
|
/** |
|
2403
|
|
|
* @var int Id of warehouse |
|
2404
|
|
|
*/ |
|
2405
|
|
|
public $entrepot_id; |
|
2406
|
|
|
|
|
2407
|
|
|
|
|
2408
|
|
|
/** |
|
2409
|
|
|
* @var float qty asked From llx_commandedet or llx_propaldet |
|
2410
|
|
|
*/ |
|
2411
|
|
|
public $qty_asked; |
|
2412
|
|
|
|
|
2413
|
|
|
/** |
|
2414
|
|
|
* @deprecated |
|
2415
|
|
|
* @see product_ref |
|
2416
|
|
|
*/ |
|
2417
|
|
|
public $ref; |
|
2418
|
|
|
|
|
2419
|
|
|
/** |
|
2420
|
|
|
* @var string product ref |
|
2421
|
|
|
*/ |
|
2422
|
|
|
public $product_ref; |
|
2423
|
|
|
|
|
2424
|
|
|
/** |
|
2425
|
|
|
* @deprecated |
|
2426
|
|
|
* @see product_label |
|
2427
|
|
|
*/ |
|
2428
|
|
|
public $libelle; |
|
2429
|
|
|
|
|
2430
|
|
|
/** |
|
2431
|
|
|
* @var string product label |
|
2432
|
|
|
*/ |
|
2433
|
|
|
public $product_label; |
|
2434
|
|
|
|
|
2435
|
|
|
/** |
|
2436
|
|
|
* @var string product description |
|
2437
|
|
|
* @deprecated |
|
2438
|
|
|
* @see product_desc |
|
2439
|
|
|
*/ |
|
2440
|
|
|
public $desc; |
|
2441
|
|
|
|
|
2442
|
|
|
/** |
|
2443
|
|
|
* @var string product description |
|
2444
|
|
|
*/ |
|
2445
|
|
|
public $product_desc; |
|
2446
|
|
|
|
|
2447
|
|
|
/** |
|
2448
|
|
|
* @var float weight |
|
2449
|
|
|
*/ |
|
2450
|
|
|
public $weight; |
|
2451
|
|
|
public $weight_units; |
|
2452
|
|
|
|
|
2453
|
|
|
/** |
|
2454
|
|
|
* @var float weight |
|
2455
|
|
|
*/ |
|
2456
|
|
|
public $length; |
|
2457
|
|
|
public $length_units; |
|
2458
|
|
|
|
|
2459
|
|
|
/** |
|
2460
|
|
|
* @var float weight |
|
2461
|
|
|
*/ |
|
2462
|
|
|
public $surface; |
|
2463
|
|
|
public $surface_units; |
|
2464
|
|
|
|
|
2465
|
|
|
/** |
|
2466
|
|
|
* @var float weight |
|
2467
|
|
|
*/ |
|
2468
|
|
|
public $volume; |
|
2469
|
|
|
public $volume_units; |
|
2470
|
|
|
|
|
2471
|
|
|
// Invoicing |
|
2472
|
|
|
public $remise_percent; |
|
2473
|
|
|
public $tva_tx; |
|
2474
|
|
|
|
|
2475
|
|
|
/** |
|
2476
|
|
|
* @var float total without tax |
|
2477
|
|
|
*/ |
|
2478
|
|
|
public $total_ht; |
|
2479
|
|
|
|
|
2480
|
|
|
/** |
|
2481
|
|
|
* @var float total with tax |
|
2482
|
|
|
*/ |
|
2483
|
|
|
public $total_ttc; |
|
2484
|
|
|
|
|
2485
|
|
|
/** |
|
2486
|
|
|
* @var float total vat |
|
2487
|
|
|
*/ |
|
2488
|
|
|
public $total_tva; |
|
2489
|
|
|
|
|
2490
|
|
|
/** |
|
2491
|
|
|
* @var float total localtax 1 |
|
2492
|
|
|
*/ |
|
2493
|
|
|
public $total_localtax1; |
|
2494
|
|
|
|
|
2495
|
|
|
/** |
|
2496
|
|
|
* @var float total localtax 2 |
|
2497
|
|
|
*/ |
|
2498
|
|
|
public $total_localtax2; |
|
2499
|
|
|
|
|
2500
|
|
|
|
|
2501
|
|
|
/** |
|
2502
|
|
|
* Constructor |
|
2503
|
|
|
* |
|
2504
|
|
|
* @param DoliDB $db Database handler |
|
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; |
|
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
|
|
|
} |
|
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
|
|
|
} |
|
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
|
|
|
} |
|
2903
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountIdthat can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theidproperty of an instance of theAccountclass. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.