Passed
Push — EXTRACT_CLASSES ( a2ff75...ae6b5c )
by Rafael
34:15
created

Delivery::valid()   F

Complexity

Conditions 25
Paths 1301

Size

Total Lines 144
Code Lines 92

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 25
eloc 92
nc 1301
nop 2
dl 0
loc 144
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* Copyright (C) 2003       Rodolphe Quiedeville        <[email protected]>
4
 * Copyright (C) 2005-2014  Regis Houssin               <[email protected]>
5
 * Copyright (C) 2006-2007  Laurent Destailleur         <[email protected]>
6
 * Copyright (C) 2007       Franky Van Liedekerke       <[email protected]>
7
 * Copyright (C) 2011-2023  Philippe Grand	            <[email protected]>
8
 * Copyright (C) 2013       Florian Henry	            <[email protected]>
9
 * Copyright (C) 2014-2015  Marcos García               <[email protected]>
10
 * Copyright (C) 2023-2024  Frédéric France             <[email protected]>
11
 * Copyright (C) 2024		MDW							<[email protected]>
12
 * Copyright (C) 2024       Rafael San José             <[email protected]>
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 3 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26
 */
27
28
namespace Dolibarr\Code\Delivery\Classes;
29
30
use Dolibarr\Code\Core\Traits\CommonIncoterm;
31
use Dolibarr\Core\Base\CommonObject;
32
use DoliDB;
33
34
/**
35
 *  \file       htdocs/delivery/class/delivery.class.php
36
 *  \ingroup    delivery
37
 *  \brief      Delivery Order Management Class File
38
 */
39
40
require_once constant('DOL_DOCUMENT_ROOT') . '/expedition/class/expedition.class.php';
41
require_once constant('DOL_DOCUMENT_ROOT') . '/product/stock/class/mouvementstock.class.php';
42
if (isModEnabled("propal")) {
43
    use Dolibarr\Code\Comm\Classes\Propal;
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_USE on line 43 at column 4
Loading history...
44
}
45
if (isModEnabled('order')) {
46
    use Dolibarr\Code\Adherents\Classes\Adherent;
47
}
48
49
50
/**
51
 *  Class to manage receptions
52
 */
53
class Delivery extends CommonObject
54
{
55
    use CommonIncoterm;
56
57
    /**
58
     * @var string ID to identify managed object
59
     */
60
    public $element = "delivery";
61
62
    /**
63
     * @var string Field with ID of parent key if this field has a parent
64
     */
65
    public $fk_element = "fk_delivery";
66
67
    /**
68
     * @var string Name of table without prefix where object is stored
69
     */
70
    public $table_element = "delivery";
71
72
    /**
73
     * @var string    Name of subtable line
74
     */
75
    public $table_element_line = "deliverydet";
76
77
    /**
78
     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
79
     */
80
    public $picto = 'sending';
81
82
    /**
83
     * @var int draft status
84
     */
85
    public $draft;
86
87
    /**
88
     * @var int thirdparty id
89
     */
90
    public $socid;
91
92
    /**
93
     * @var string ref customer
94
     */
95
    public $ref_customer;
96
97
    /**
98
     * @var integer|string Date really received
99
     */
100
    public $date_delivery;
101
102
    /**
103
     * @var integer|string date_creation
104
     */
105
    public $date_creation;
106
107
    /**
108
     * @var integer|string date_valid
109
     */
110
    public $date_valid;
111
112
    /**
113
     * @var string model pdf
114
     */
115
    public $model_pdf;
116
117
    public $commande_id;
118
119
    /**
120
     * @var DeliveryLine[] lines
121
     */
122
    public $lines = array();
123
124
    /**
125
     * @var int user_author_id
126
     */
127
    public $user_author_id;
128
129
130
    /**
131
     * Constructor
132
     *
133
     * @param   DoliDB  $db     Database handler
134
     */
135
    public function __construct($db)
136
    {
137
        $this->db = $db;
138
139
        // List of short language codes for status
140
        $this->labelStatus[-1] = 'StatusDeliveryCanceled';
141
        $this->labelStatus[0]  = 'StatusDeliveryDraft';
142
        $this->labelStatus[1]  = 'StatusDeliveryValidated';
143
    }
144
145
    /**
146
     *  Create delivery receipt in database
147
     *
148
     *  @param  User    $user       Object du user qui cree
149
     *  @return int                 Return integer <0 si erreur, id delivery cree si ok
150
     */
151
    public function create($user)
152
    {
153
        global $conf;
154
155
        dol_syslog("Delivery::create");
156
157
        if (empty($this->model_pdf)) {
158
            $this->model_pdf = getDolGlobalString('DELIVERY_ADDON_PDF');
159
        }
160
161
        $error = 0;
162
163
        $now = dol_now();
164
165
        /* Delivery note as draft On positionne en mode draft le bon de livraison */
166
        $this->draft = 1;
167
168
        $this->user = $user;
169
170
        $this->db->begin();
171
172
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "delivery (";
173
        $sql .= "ref";
174
        $sql .= ", entity";
175
        $sql .= ", fk_soc";
176
        $sql .= ", ref_customer";
177
        $sql .= ", date_creation";
178
        $sql .= ", fk_user_author";
179
        $sql .= ", date_delivery";
180
        $sql .= ", fk_address";
181
        $sql .= ", note_private";
182
        $sql .= ", note_public";
183
        $sql .= ", model_pdf";
184
        $sql .= ", fk_incoterms, location_incoterms";
185
        $sql .= ") VALUES (";
186
        $sql .= "'(PROV)'";
187
        $sql .= ", " . ((int) $conf->entity);
188
        $sql .= ", " . ((int) $this->socid);
189
        $sql .= ", '" . $this->db->escape($this->ref_customer) . "'";
190
        $sql .= ", '" . $this->db->idate($now) . "'";
191
        $sql .= ", " . ((int) $user->id);
192
        $sql .= ", " . ($this->date_delivery ? "'" . $this->db->idate($this->date_delivery) . "'" : "null");
193
        $sql .= ", " . ($this->fk_delivery_address > 0 ? $this->fk_delivery_address : "null");
194
        $sql .= ", " . (!empty($this->note_private) ? "'" . $this->db->escape($this->note_private) . "'" : "null");
195
        $sql .= ", " . (!empty($this->note_public) ? "'" . $this->db->escape($this->note_public) . "'" : "null");
196
        $sql .= ", " . (!empty($this->model_pdf) ? "'" . $this->db->escape($this->model_pdf) . "'" : "null");
197
        $sql .= ", " . (int) $this->fk_incoterms;
198
        $sql .= ", '" . $this->db->escape($this->location_incoterms) . "'";
199
        $sql .= ")";
200
201
        dol_syslog("Delivery::create", LOG_DEBUG);
202
        $resql = $this->db->query($sql);
203
        if ($resql) {
204
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "delivery");
205
206
            $numref = "(PROV" . $this->id . ")";
207
208
            $sql = "UPDATE " . MAIN_DB_PREFIX . "delivery ";
209
            $sql .= "SET ref = '" . $this->db->escape($numref) . "'";
210
            $sql .= " WHERE rowid = " . ((int) $this->id);
211
212
            dol_syslog("Delivery::create", LOG_DEBUG);
213
            $resql = $this->db->query($sql);
214
            if ($resql) {
215
                if (!getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION')) {
216
                    $commande = new Commande($this->db);
217
                    $commande->id = $this->commande_id;
218
                    $commande->fetch_lines();
219
                }
220
221
222
                /*
223
                 *  Inserting products into the database
224
                 */
225
                $num = count($this->lines);
226
                for ($i = 0; $i < $num; $i++) {
227
                    $origin_id = $this->lines[$i]->origin_line_id;
228
                    if (!$origin_id) {
229
                        $origin_id = $this->lines[$i]->commande_ligne_id; // For backward compatibility
230
                    }
231
232
                    if (!$this->create_line($origin_id, $this->lines[$i]->qty, $this->lines[$i]->fk_product, $this->lines[$i]->description, $this->lines[$i]->array_options)) {
233
                        $error++;
234
                    }
235
                }
236
237
                if (!$error && $this->id && $this->origin_id) {
238
                    $ret = $this->add_object_linked();
239
                    if (!$ret) {
240
                        $error++;
241
                    }
242
243
                    if (!getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION')) {
244
                        $ret = $this->setStatut(2, $this->origin_id, $this->origin);
245
                        if (!$ret) {
246
                            $error++;
247
                        }
248
                    }
249
                }
250
251
                if (!$error) {
252
                    $this->db->commit();
253
                    return $this->id;
254
                } else {
255
                    $error++;
256
                    $this->error = $this->db->lasterror() . " - sql=" . $this->db->lastqueryerror;
257
                    $this->db->rollback();
258
                    return -3;
259
                }
260
            } else {
261
                $error++;
262
                $this->error = $this->db->lasterror() . " - sql=" . $this->db->lastqueryerror;
263
                $this->db->rollback();
264
                return -2;
265
            }
266
        } else {
267
            $error++;
268
            $this->error = $this->db->lasterror() . " - sql=" . $this->db->lastqueryerror;
269
            $this->db->rollback();
270
            return -1;
271
        }
272
    }
273
274
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
275
    /**
276
     *  Create a line
277
     *
278
     *  @param  string  $origin_id              Id of order
279
     *  @param  string  $qty                    Quantity
280
     *  @param  string  $fk_product             Id of predefined product
281
     *  @param  string  $description            Description
282
     *  @param  array   $array_options          Array options
283
     *  @return int                             Return integer <0 if KO, >0 if OK
284
     */
285
    public function create_line($origin_id, $qty, $fk_product, $description, $array_options = [])
286
    {
287
		// phpcs:enable
288
        $error = 0;
289
        $idprod = $fk_product;
290
291
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "deliverydet (fk_delivery, fk_origin_line,";
292
        $sql .= " fk_product, description, qty)";
293
        $sql .= " VALUES (" . $this->id . "," . ((int) $origin_id) . ",";
294
        $sql .= " " . ($idprod > 0 ? ((int) $idprod) : "null") . ",";
295
        $sql .= " " . ($description ? "'" . $this->db->escape($description) . "'" : "null") . ",";
296
        $sql .= (price2num($qty, 'MS')) . ")";
297
298
        dol_syslog(get_class($this) . "::create_line", LOG_DEBUG);
299
        if (!$this->db->query($sql)) {
300
            $error++;
301
        }
302
303
        $id = $this->db->last_insert_id(MAIN_DB_PREFIX . "deliverydet");
304
305
        if (is_array($array_options) && count($array_options) > 0) {
306
            $line = new DeliveryLine($this->db);
307
            $line->id = $id;
308
            $line->array_options = $array_options;
309
            $result = $line->insertExtraFields();
310
        }
311
312
        if (!$error) {
313
            return 1;
314
        }
315
316
        return -1;
317
    }
318
319
    /**
320
     *  Load a delivery receipt
321
     *
322
     *  @param  int     $id         Id of object to load
323
     *  @return integer
324
     */
325
    public function fetch($id)
326
    {
327
        $sql = "SELECT l.rowid, l.fk_soc, l.date_creation, l.date_valid, l.ref, l.ref_customer, l.fk_user_author,";
328
        $sql .= " l.total_ht, l.fk_statut, l.fk_user_valid, l.note_private, l.note_public";
329
        $sql .= ", l.date_delivery, l.fk_address, l.model_pdf";
330
        $sql .= ", el.fk_source as origin_id, el.sourcetype as origin";
331
        $sql .= ', l.fk_incoterms, l.location_incoterms';
332
        $sql .= ", i.libelle as label_incoterms";
333
        $sql .= " FROM " . MAIN_DB_PREFIX . "delivery as l";
334
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "element_element as el ON el.fk_target = l.rowid AND el.targettype = '" . $this->db->escape($this->element) . "'";
335
        $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'c_incoterms as i ON l.fk_incoterms = i.rowid';
336
        $sql .= " WHERE l.rowid = " . ((int) $id);
337
338
        dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
339
        $result = $this->db->query($sql);
340
        if ($result) {
341
            if ($this->db->num_rows($result)) {
342
                $obj = $this->db->fetch_object($result);
343
344
                $this->id                   = $obj->rowid;
345
                $this->date_delivery        = $this->db->jdate($obj->date_delivery);
346
                $this->date_creation        = $this->db->jdate($obj->date_creation);
347
                $this->date_valid           = $this->db->jdate($obj->date_valid);
348
                $this->ref                  = $obj->ref;
349
                $this->ref_customer         = $obj->ref_customer;
350
                $this->socid                = $obj->fk_soc;
351
                $this->statut               = $obj->fk_statut;
352
                $this->status               = $obj->fk_statut;
353
                $this->user_author_id       = $obj->fk_user_author;
354
                $this->user_validation_id   = $obj->fk_user_valid;
355
                $this->fk_delivery_address  = $obj->fk_address;
356
                $this->note                 = $obj->note_private; //TODO deprecated
357
                $this->note_private         = $obj->note_private;
358
                $this->note_public          = $obj->note_public;
359
                $this->model_pdf            = $obj->model_pdf;
360
                $this->origin               = $obj->origin; // May be 'shipping'
361
                $this->origin_id            = $obj->origin_id; // May be id of shipping
362
363
                //Incoterms
364
                $this->fk_incoterms = $obj->fk_incoterms;
365
                $this->location_incoterms = $obj->location_incoterms;
366
                $this->label_incoterms = $obj->label_incoterms;
367
                $this->db->free($result);
368
369
                if ($this->statut == 0) {
370
                    $this->draft = 1;
371
                }
372
373
                // Retrieve all extrafields
374
                // fetch optionals attributes and labels
375
                $this->fetch_optionals();
376
377
                // Load lines
378
                $result = $this->fetch_lines();
379
                if ($result < 0) {
380
                    return -3;
381
                }
382
383
                return 1;
384
            } else {
385
                $this->error = 'Delivery with id ' . $id . ' not found sql=' . $sql;
386
                dol_syslog(get_class($this) . '::fetch Error ' . $this->error, LOG_ERR);
387
                return -2;
388
            }
389
        } else {
390
            $this->error = $this->db->error();
391
            return -1;
392
        }
393
    }
394
395
    /**
396
     *  Validate object and update stock if option enabled
397
     *
398
     *  @param  User    $user       Object user that validate
399
     *  @param  int     $notrigger  1=Does not execute triggers, 0= execute triggers
400
     *  @return int
401
     */
402
    public function valid($user, $notrigger = 0)
403
    {
404
        global $conf;
405
406
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
407
408
        dol_syslog(get_class($this) . "::valid begin");
409
410
        $this->db->begin();
411
412
        $error = 0;
413
414
        if (
415
            (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('expedition', 'delivery', 'creer'))
416
            || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('expedition', 'delivery_advance', 'validate'))
417
        ) {
418
            if (getDolGlobalString('DELIVERY_ADDON_NUMBER')) {
419
                // Setting the command numbering module name
420
                $modName = getDolGlobalString('DELIVERY_ADDON_NUMBER');
421
422
                if (is_readable(DOL_DOCUMENT_ROOT . '/core/modules/delivery/' . $modName . '.php')) {
423
                    require_once constant('DOL_DOCUMENT_ROOT') . '/core/modules/delivery/' . $modName . '.php';
424
425
                    $now = dol_now();
426
427
                    // Retrieving the new reference
428
                    $objMod = new $modName($this->db);
429
                    $soc = new Societe($this->db);
430
                    $soc->fetch($this->socid);
431
432
                    if (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref)) { // empty should not happened, but when it occurs, the test save life
433
                        $numref = $objMod->delivery_get_num($soc, $this);
434
                    } else {
435
                        $numref = $this->ref;
436
                    }
437
                    $this->newref = dol_sanitizeFileName($numref);
438
439
                    // Test if is not already in valid status. If so, we stop to avoid decrementing the stock twice.
440
                    $sql = "SELECT ref";
441
                    $sql .= " FROM " . MAIN_DB_PREFIX . "delivery";
442
                    $sql .= " WHERE ref = '" . $this->db->escape($numref) . "'";
443
                    $sql .= " AND fk_statut <> 0";
444
                    $sql .= " AND entity = " . ((int) $conf->entity);
445
446
                    $resql = $this->db->query($sql);
447
                    if ($resql) {
448
                        $num = $this->db->num_rows($resql);
449
                        if ($num > 0) {
450
                            return 0;
451
                        }
452
                    }
453
454
                    $sql = "UPDATE " . MAIN_DB_PREFIX . "delivery SET";
455
                    $sql .= " ref='" . $this->db->escape($numref) . "'";
456
                    $sql .= ", fk_statut = 1";
457
                    $sql .= ", date_valid = '" . $this->db->idate($now) . "'";
458
                    $sql .= ", fk_user_valid = " . $user->id;
459
                    $sql .= " WHERE rowid = " . ((int) $this->id);
460
                    $sql .= " AND fk_statut = 0";
461
462
                    $resql = $this->db->query($sql);
463
                    if (!$resql) {
464
                        dol_print_error($this->db);
465
                        $this->error = $this->db->lasterror();
466
                        $error++;
467
                    }
468
469
                    if (!$error && !$notrigger) {
470
                        // Call trigger
471
                        $result = $this->call_trigger('DELIVERY_VALIDATE', $user);
472
                        if ($result < 0) {
473
                            $error++;
474
                        }
475
                        // End call triggers
476
                    }
477
478
                    if (!$error) {
479
                        $this->oldref = $this->ref;
480
481
                        // Rename directory if dir was a temporary ref
482
                        if (preg_match('/^[\(]?PROV/i', $this->ref)) {
483
                            // Now we rename also files into index
484
                            $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filename = CONCAT('" . $this->db->escape($this->newref) . "', SUBSTR(filename, " . (strlen($this->ref) + 1) . ")), filepath = 'expedition/receipt/" . $this->db->escape($this->newref) . "'";
485
                            $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'expedition/receipt/" . $this->db->escape($this->ref) . "' and entity = " . ((int) $conf->entity);
486
                            $resql = $this->db->query($sql);
487
                            if (!$resql) {
488
                                $error++;
489
                                $this->error = $this->db->lasterror();
490
                            }
491
                            $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filepath = 'expedition/receipt/" . $this->db->escape($this->newref) . "'";
492
                            $sql .= " WHERE filepath = 'expedition/receipt/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
493
                            $resql = $this->db->query($sql);
494
                            if (!$resql) {
495
                                $error++;
496
                                $this->error = $this->db->lasterror();
497
                            }
498
499
                            // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
500
                            $oldref = dol_sanitizeFileName($this->ref);
501
                            $newref = dol_sanitizeFileName($numref);
502
                            $dirsource = $conf->expedition->dir_output . '/receipt/' . $oldref;
503
                            $dirdest = $conf->expedition->dir_output . '/receipt/' . $newref;
504
                            if (!$error && file_exists($dirsource)) {
505
                                dol_syslog(get_class($this) . "::valid rename dir " . $dirsource . " into " . $dirdest);
506
507
                                if (@rename($dirsource, $dirdest)) {
508
                                    dol_syslog("Rename ok");
509
                                    // Rename docs starting with $oldref with $newref
510
                                    $listoffiles = dol_dir_list($conf->expedition->dir_output . '/receipt/' . $newref, 'files', 1, '^' . preg_quote($oldref, '/'));
511
                                    foreach ($listoffiles as $fileentry) {
512
                                        $dirsource = $fileentry['name'];
513
                                        $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
514
                                        $dirsource = $fileentry['path'] . '/' . $dirsource;
515
                                        $dirdest = $fileentry['path'] . '/' . $dirdest;
516
                                        @rename($dirsource, $dirdest);
517
                                    }
518
                                }
519
                            }
520
                        }
521
522
                        // Set new ref and current status
523
                        if (!$error) {
524
                            $this->ref = $numref;
525
                            $this->statut = 1;
526
                        }
527
528
                        dol_syslog(get_class($this) . "::valid ok");
529
                    }
530
531
                    if (!$error) {
532
                        $this->db->commit();
533
                        return 1;
534
                    } else {
535
                        $this->db->rollback();
536
                        return -1;
537
                    }
538
                }
539
            }
540
541
            return -1;
542
        } else {
543
            $this->error = "NotAllowed";
544
            dol_syslog(get_class($this) . "::valid " . $this->error, LOG_ERR);
545
            return -1;
546
        }
547
    }
548
549
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
550
    /**
551
     *  Creating the delivery slip from an existing shipment
552
     *
553
     *  @param  User    $user           User who creates
554
     *  @param  int     $sending_id     Id of the expedition that serves as a model
555
     *  @return integer                 Return integer <=0 if KO, >0 if OK
556
     */
557
    public function create_from_sending($user, $sending_id)
558
    {
559
		// phpcs:enable
560
        global $conf;
561
562
        $expedition = new Expedition($this->db);
563
        $result = $expedition->fetch($sending_id);
564
        if ($result <= 0) {
565
            return $result;
566
        }
567
568
        $this->lines = array();
569
570
        $num = count($expedition->lines);
571
        for ($i = 0; $i < $num; $i++) {
572
            $line = new DeliveryLine($this->db);
573
            $line->origin_line_id    = $expedition->lines[$i]->origin_line_id;
574
            $line->label             = $expedition->lines[$i]->label;
575
            $line->description       = $expedition->lines[$i]->description;
576
            $line->qty               = $expedition->lines[$i]->qty_shipped;
577
            $line->fk_product        = $expedition->lines[$i]->fk_product;
578
            if (!getDolGlobalString('MAIN_EXTRAFIELDS_DISABLED') && is_array($expedition->lines[$i]->array_options) && count($expedition->lines[$i]->array_options) > 0) { // For avoid conflicts if trigger used
579
                $line->array_options = $expedition->lines[$i]->array_options;
580
            }
581
            $this->lines[$i] = $line;
582
        }
583
584
        $this->origin               = $expedition->element;
585
        $this->origin_id            = $expedition->id;
586
        $this->note_private         = $expedition->note_private;
587
        $this->note_public          = $expedition->note_public;
588
        $this->fk_project           = $expedition->fk_project;
589
        $this->date_delivery        = $expedition->date_delivery;
590
        $this->fk_delivery_address  = $expedition->fk_delivery_address;
591
        $this->socid                = $expedition->socid;
592
        $this->ref_customer         = $expedition->ref_customer;
593
594
        //Incoterms
595
        $this->fk_incoterms = $expedition->fk_incoterms;
596
        $this->location_incoterms = $expedition->location_incoterms;
597
598
        return $this->create($user);
599
    }
600
601
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
602
    /**
603
     * Update a livraison line (only extrafields)
604
     *
605
     * @param   int     $id                 Id of line (livraison line)
606
     * @param   array   $array_options      extrafields array
607
     * @return  int                         Return integer <0 if KO, >0 if OK
608
     */
609
    public function update_line($id, $array_options = [])
610
    {
611
		// phpcs:enable
612
        global $conf;
613
        $error = 0;
614
615
        if ($id > 0 && !$error && !getDolGlobalString('MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) { // For avoid conflicts if trigger used
616
            $line = new DeliveryLine($this->db);
617
            $line->array_options = $array_options;
618
            $line->id = $id;
619
            $result = $line->insertExtraFields();
620
621
            if ($result < 0) {
622
                $this->errors[] = $line->error;
623
                $error++;
624
            }
625
        }
626
627
        if (!$error) {
628
            return 1;
629
        } else {
630
            return -1;
631
        }
632
    }
633
634
635
    /**
636
     *  Add line
637
     *
638
     *  @param  int     $origin_id              Origin id
639
     *  @param  float   $qty                    Qty
640
     *  @param  array   $array_options          Array options
641
     *  @return void
642
     */
643
    public function addline($origin_id, $qty, $array_options = [])
644
    {
645
        global $conf;
646
647
        $num = count($this->lines);
648
        $line = new DeliveryLine($this->db);
649
650
        $line->origin_id = $origin_id;
651
        $line->qty = $qty;
652
        if (!getDolGlobalString('MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) { // For avoid conflicts if trigger used
653
            $line->array_options = $array_options;
654
        }
655
        $this->lines[$num] = $line;
656
    }
657
658
    /**
659
     *  Delete line
660
     *
661
     *  @param  int     $lineid     Line id
662
     *  @return integer             Return integer <0 if KO, 0 if nothing done, >0 if OK
663
     */
664
    public function deleteLine($lineid)
665
    {
666
        if ($this->statut == 0) {
667
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "commandedet";
668
            $sql .= " WHERE rowid = " . ((int) $lineid);
669
670
            if ($this->db->query($sql)) {
671
                $this->update_price(1);
672
673
                return 1;
674
            } else {
675
                return -1;
676
            }
677
        }
678
679
        return 0;
680
    }
681
682
    /**
683
     * Delete object
684
     *
685
     * @param   User        $user       User making the deletion
686
     * @return  integer
687
     */
688
    public function delete($user = null)
689
    {
690
        global $conf, $langs;
691
692
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
693
694
        $this->db->begin();
695
696
        $error = 0;
697
698
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "deliverydet";
699
        $sql .= " WHERE fk_delivery = " . ((int) $this->id);
700
        if ($this->db->query($sql)) {
701
            // Delete linked object
702
            $res = $this->deleteObjectLinked();
703
            if ($res < 0) {
704
                $error++;
705
            }
706
707
            if (!$error) {
708
                $sql = "DELETE FROM " . MAIN_DB_PREFIX . "delivery";
709
                $sql .= " WHERE rowid = " . ((int) $this->id);
710
                if ($this->db->query($sql)) {
711
                    $this->db->commit();
712
713
                    // Deleting pdf folder's draft On efface le repertoire de pdf provisoire
714
                    $ref = dol_sanitizeFileName($this->ref);
715
                    if (!empty($conf->expedition->dir_output)) {
716
                        $dir = $conf->expedition->dir_output . '/receipt/' . $ref;
717
                        $file = $dir . '/' . $ref . '.pdf';
718
                        if (file_exists($file)) {
719
                            if (!dol_delete_file($file)) {
720
                                return 0;
721
                            }
722
                        }
723
                        if (file_exists($dir)) {
724
                            if (!dol_delete_dir($dir)) {
725
                                $this->error = $langs->trans("ErrorCanNotDeleteDir", $dir);
726
                                return 0;
727
                            }
728
                        }
729
                    }
730
731
                    // Call trigger
732
                    $result = $this->call_trigger('DELIVERY_DELETE', $user);
733
                    if ($result < 0) {
734
                        $this->db->rollback();
735
                        return -4;
736
                    }
737
                    // End call triggers
738
739
                    return 1;
740
                } else {
741
                    $this->error = $this->db->lasterror() . " - sql=$sql";
742
                    $this->db->rollback();
743
                    return -3;
744
                }
745
            } else {
746
                $this->error = $this->db->lasterror() . " - sql=$sql";
747
                $this->db->rollback();
748
                return -2;
749
            }
750
        } else {
751
            $this->error = $this->db->lasterror() . " - sql=$sql";
752
            $this->db->rollback();
753
            return -1;
754
        }
755
    }
756
757
    /**
758
     * getTooltipContentArray
759
     * @param array $params params to construct tooltip data
760
     * @since v18
761
     * @return array
762
     */
763
    public function getTooltipContentArray($params)
764
    {
765
        global $langs;
766
767
        $langs->load('deliveries');
768
769
        $datas = [];
770
771
        $datas['picto'] = img_picto('', $this->picto) . ' <u>' . $langs->trans("ShowReceiving") . '</u>:<br>';
772
        $datas['picto'] .= '<b>' . $langs->trans("Status") . '</b>: ' . $this->ref;
773
774
        return $datas;
775
    }
776
777
    /**
778
     *  Return clicable name (with picto eventually)
779
     *
780
     *  @param  int     $withpicto                  0=No picto, 1=Include picto into link, 2=Only picto
781
     *  @param  int     $save_lastsearch_value      -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
782
     *  @return string                              Chaine avec URL
783
     */
784
    public function getNomUrl($withpicto = 0, $save_lastsearch_value = -1)
785
    {
786
        global $langs, $hookmanager;
787
788
        $result = '';
789
790
        $params = [
791
            'id' => $this->id,
792
            'objecttype' => $this->element,
793
        ];
794
        $classfortooltip = 'classfortooltip';
795
        $dataparams = '';
796
        if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
797
            $classfortooltip = 'classforajaxtooltip';
798
            $dataparams = ' data-params="' . dol_escape_htmltag(json_encode($params)) . '"';
799
            $label = '';
800
        } else {
801
            $label = implode($this->getTooltipContentArray($params));
802
        }
803
804
        $url = constant('BASE_URL') . '/delivery/card.php?id=' . $this->id;
805
806
        //if ($option !== 'nolink')
807
        //{
808
        // Add param to save lastsearch_values or not
809
        $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
810
        if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
811
            $add_save_lastsearch_values = 1;
812
        }
813
        if ($add_save_lastsearch_values) {
814
            $url .= '&save_lastsearch_values=1';
815
        }
816
        //}
817
818
        $linkstart = '<a href="' . $url . '"';
819
        $linkstart .= ($label ? ' title="' . dol_escape_htmltag($label, 1) . '"' : ' title="tocomplete"');
820
        $linkstart .= $dataparams . ' class="' . $classfortooltip . '">';
821
        $linkend = '</a>';
822
823
        if ($withpicto) {
824
            $result .= ($linkstart . img_object($label, $this->picto, $dataparams . ' class="' . $classfortooltip . '"') . $linkend);
825
        }
826
        if ($withpicto && $withpicto != 2) {
827
            $result .= ' ';
828
        }
829
        $result .= $linkstart . $this->ref . $linkend;
830
831
        global $action;
832
        $hookmanager->initHooks(array($this->element . 'dao'));
833
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
834
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
835
        if ($reshook > 0) {
836
            $result = $hookmanager->resPrint;
837
        } else {
838
            $result .= $hookmanager->resPrint;
839
        }
840
        return $result;
841
    }
842
843
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
844
    /**
845
     *  Load lines insto $this->lines.
846
     *
847
     *  @return     int                             Return integer <0 if KO, >0 if OK
848
     */
849
    public function fetch_lines()
850
    {
851
		// phpcs:enable
852
        $this->lines = array();
853
854
        $sql = "SELECT ld.rowid, ld.fk_product, ld.description, ld.subprice, ld.total_ht, ld.qty as qty_shipped, ld.fk_origin_line, ";
855
        $sql .= " cd.qty as qty_asked, cd.label as custom_label, cd.fk_unit,";
856
        $sql .= " p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc,";
857
        $sql .= " p.weight, p.weight_units,  p.width, p.width_units, p.length, p.length_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units, p.tobatch as product_tobatch";
858
        $sql .= " FROM " . MAIN_DB_PREFIX . "commandedet as cd, " . MAIN_DB_PREFIX . "deliverydet as ld";
859
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p on p.rowid = ld.fk_product";
860
        $sql .= " WHERE ld.fk_origin_line = cd.rowid";
861
        $sql .= " AND ld.fk_delivery = " . ((int) $this->id);
862
863
        dol_syslog(get_class($this) . "::fetch_lines", LOG_DEBUG);
864
        $resql = $this->db->query($sql);
865
        if ($resql) {
866
            $num = $this->db->num_rows($resql);
867
            $i = 0;
868
            while ($i < $num) {
869
                $obj = $this->db->fetch_object($resql);
870
871
                $line = new DeliveryLine($this->db);
872
873
                $line->id = $obj->rowid;
874
                $line->label = $obj->custom_label;
875
                $line->description  = $obj->description;
876
                $line->fk_product   = $obj->fk_product;
877
                $line->qty_asked    = $obj->qty_asked;
878
                $line->qty_shipped  = $obj->qty_shipped;
879
880
                $line->product_label    = $obj->product_label; // Product label
881
                $line->product_ref      = $obj->product_ref; // Product ref
882
                $line->product_desc     = $obj->product_desc; // Product description
883
                $line->product_type     = $obj->fk_product_type;
884
885
                $line->fk_origin_line = $obj->fk_origin_line;
886
887
                $line->price = $obj->subprice;
888
                $line->total_ht = $obj->total_ht;
889
890
                // units
891
                $line->weight           = $obj->weight;
892
                $line->weight_units     = $obj->weight_units;
893
                $line->width            = $obj->width;
894
                $line->width_units      = $obj->width_units;
895
                $line->height           = $obj->height;
896
                $line->height_units     = $obj->height_units;
897
                $line->length           = $obj->length;
898
                $line->length_units     = $obj->length_units;
899
                $line->surface          = $obj->surface;
900
                $line->surface_units = $obj->surface_units;
901
                $line->volume           = $obj->volume;
902
                $line->volume_units     = $obj->volume_units;
903
904
                $line->fk_unit = $obj->fk_unit;
905
                $line->fetch_optionals();
906
907
                $this->lines[$i] = $line;
908
909
                $i++;
910
            }
911
            $this->db->free($resql);
912
913
            return 1;
914
        } else {
915
            return -1;
916
        }
917
    }
918
919
920
    /**
921
     *  Return the label of the status
922
     *
923
     *  @param  int     $mode          0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
924
     *  @return string                 Label of status
925
     */
926
    public function getLibStatut($mode = 0)
927
    {
928
        return $this->LibStatut($this->statut, $mode);
929
    }
930
931
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
932
    /**
933
     *  Return the label of a given status
934
     *
935
     *  @param  int     $status        Id status
936
     *  @param  int     $mode          0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
937
     *  @return string                 Label of status
938
     */
939
    public function LibStatut($status, $mode)
940
    {
941
		// phpcs:enable
942
        global $langs;
943
944
        if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
945
            global $langs;
946
            //$langs->load("mymodule");
947
            $this->labelStatus[-1] = $langs->transnoentitiesnoconv('StatusDeliveryCanceled');
948
            $this->labelStatus[0] = $langs->transnoentitiesnoconv('StatusDeliveryDraft');
949
            $this->labelStatus[1] = $langs->transnoentitiesnoconv('StatusDeliveryValidated');
950
            $this->labelStatusShort[-1] = $langs->transnoentitiesnoconv('StatusDeliveryCanceled');
951
            $this->labelStatusShort[0] = $langs->transnoentitiesnoconv('StatusDeliveryDraft');
952
            $this->labelStatusShort[1] = $langs->transnoentitiesnoconv('StatusDeliveryValidated');
953
        }
954
955
        $statusType = 'status0';
956
        if ($status == -1) {
957
            $statusType = 'status5';
958
        }
959
        if ($status == 1) {
960
            $statusType = 'status4';
961
        }
962
963
        return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
964
    }
965
966
967
    /**
968
     *  Initialise an instance with random values.
969
     *  Used to build previews or test instances.
970
     *  id must be 0 if object instance is a specimen.
971
     *
972
     *  @return int
973
     */
974
    public function initAsSpecimen()
975
    {
976
        $now = dol_now();
977
978
        // Load array of products prodids
979
        $num_prods = 0;
980
        $prodids = array();
981
        $sql = "SELECT rowid";
982
        $sql .= " FROM " . MAIN_DB_PREFIX . "product";
983
        $sql .= " WHERE entity IN (" . getEntity('product') . ")";
984
        $sql .= " AND tosell = 1";
985
        $sql .= $this->db->plimit(100);
986
987
        $resql = $this->db->query($sql);
988
        if ($resql) {
989
            $num_prods = $this->db->num_rows($resql);
990
            $i = 0;
991
            while ($i < $num_prods) {
992
                $i++;
993
                $row = $this->db->fetch_row($resql);
994
                $prodids[$i] = $row[0];
995
            }
996
        }
997
998
        // Initialise parameters
999
        $this->id = 0;
1000
        $this->ref = 'SPECIMEN';
1001
        $this->specimen = 1;
1002
        $this->socid = 1;
1003
        $this->date_delivery = $now;
1004
        $this->note_public = 'Public note';
1005
        $this->note_private = 'Private note';
1006
1007
        $i = 0;
1008
        $line = new DeliveryLine($this->db);
1009
        $line->fk_product     = reset($prodids);
1010
        $line->qty_asked      = 10;
1011
        $line->qty_shipped    = 9;
1012
        $line->ref            = 'REFPROD';
1013
        $line->label          = 'Specimen';
1014
        $line->description    = 'Description';
1015
        $line->price          = 100;
1016
        $line->total_ht       = 100;
1017
1018
        $this->lines[$i] = $line;
1019
1020
        return 1;
1021
    }
1022
1023
    /**
1024
     *  Renvoie la quantite de produit restante a livrer pour une commande
1025
     *
1026
     *  @return     array|int       Product remaining to be delivered or <0 if KO
1027
     *  TODO use new function
1028
     */
1029
    public function getRemainingDelivered()
1030
    {
1031
        // Get the linked object
1032
        $this->fetchObjectLinked('', '', $this->id, $this->element);
1033
        //var_dump($this->linkedObjectsIds);
1034
        // Get the product ref and qty in source
1035
        $sqlSourceLine = "SELECT st.rowid, st.description, st.qty";
1036
        $sqlSourceLine .= ", p.ref, p.label";
1037
        $sqlSourceLine .= " FROM " . MAIN_DB_PREFIX . $this->linkedObjectsIds[0]['type'] . "det as st";
1038
        $sqlSourceLine .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON st.fk_product = p.rowid";
1039
        $sqlSourceLine .= " WHERE fk_" . $this->linked_objects[0]['type'] . " = " . ((int) $this->linked_objects[0]['linkid']);
1040
1041
        $resultSourceLine = $this->db->query($sqlSourceLine);
1042
        if ($resultSourceLine) {
1043
            $num_lines = $this->db->num_rows($resultSourceLine);
1044
            $i = 0;
1045
            $array = array();
1046
            while ($i < $num_lines) {
1047
                $objSourceLine = $this->db->fetch_object($resultSourceLine);
1048
1049
                // Get lines of sources already delivered
1050
                $sql = "SELECT ld.fk_origin_line, sum(ld.qty) as qty";
1051
                $sql .= " FROM " . MAIN_DB_PREFIX . "deliverydet as ld, " . MAIN_DB_PREFIX . "delivery as l,";
1052
                $sql .= " " . MAIN_DB_PREFIX . $this->linked_objects[0]['type'] . " as c";
1053
                $sql .= ", " . MAIN_DB_PREFIX . $this->linked_objects[0]['type'] . "det as cd";
1054
                $sql .= " WHERE ld.fk_delivery = l.rowid";
1055
                $sql .= " AND ld.fk_origin_line = cd.rowid";
1056
                $sql .= " AND cd.fk_" . $this->linked_objects[0]['type'] . " = c.rowid";
1057
                $sql .= " AND cd.fk_" . $this->linked_objects[0]['type'] . " = " . ((int) $this->linked_objects[0]['linkid']);
1058
                $sql .= " AND ld.fk_origin_line = " . ((int) $objSourceLine->rowid);
1059
                $sql .= " GROUP BY ld.fk_origin_line";
1060
1061
                $result = $this->db->query($sql);
1062
                $row = $this->db->fetch_row($result);
1063
1064
                if ($objSourceLine->qty - $row[1] > 0) {
1065
                    if ($row[0] == $objSourceLine->rowid) {
1066
                        $array[$i]['qty'] = $objSourceLine->qty - $row[1];
1067
                    } else {
1068
                        $array[$i]['qty'] = $objSourceLine->qty;
1069
                    }
1070
1071
                    $array[$i]['ref'] = $objSourceLine->ref;
1072
                    $array[$i]['label'] = $objSourceLine->label ? $objSourceLine->label : $objSourceLine->description;
1073
                } elseif ($objSourceLine->qty - $row[1] < 0) {
1074
                    $array[$i]['qty'] = $objSourceLine->qty - $row[1] . " Erreur livraison !";
1075
                    $array[$i]['ref'] = $objSourceLine->ref;
1076
                    $array[$i]['label'] = $objSourceLine->label ? $objSourceLine->label : $objSourceLine->description;
1077
                }
1078
1079
                $i++;
1080
            }
1081
            return $array;
1082
        } else {
1083
            $this->error = $this->db->error() . " - sql=$sqlSourceLine";
1084
            return -1;
1085
        }
1086
    }
1087
1088
    /**
1089
     *  Set the planned delivery date
1090
     *
1091
     *  @param      User            $user               Object utilisateur qui modifie
1092
     *  @param      integer         $delivery_date     Delivery date
1093
     *  @return     int                                 Return integer <0 if KO, >0 if OK
1094
     */
1095
    public function setDeliveryDate($user, $delivery_date)
1096
    {
1097
        if ($user->hasRight('expedition', 'creer')) {
1098
            $sql = "UPDATE " . MAIN_DB_PREFIX . "delivery";
1099
            $sql .= " SET date_delivery = " . ($delivery_date ? "'" . $this->db->idate($delivery_date) . "'" : 'null');
1100
            $sql .= " WHERE rowid = " . ((int) $this->id);
1101
1102
            dol_syslog(get_class($this) . "::setDeliveryDate", LOG_DEBUG);
1103
            $resql = $this->db->query($sql);
1104
            if ($resql) {
1105
                $this->date_delivery = $delivery_date;
1106
                return 1;
1107
            } else {
1108
                $this->error = $this->db->error();
1109
                return -1;
1110
            }
1111
        } else {
1112
            return -2;
1113
        }
1114
    }
1115
1116
    /**
1117
     *  Create object on disk
1118
     *
1119
     *  @param     string       $modele         force le modele a utiliser ('' to not force)
1120
     *  @param     Translate    $outputlangs    Object langs to use for output
1121
     *  @param     int          $hidedetails    Hide details of lines
1122
     *  @param     int          $hidedesc       Hide description
1123
     *  @param     int          $hideref        Hide ref
1124
     *  @return    int                          0 if KO, 1 if OK
1125
     */
1126
    public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
1127
    {
1128
        global $conf, $langs;
1129
1130
        $langs->load("deliveries");
1131
        $outputlangs->load("products");
1132
1133
        if (!dol_strlen($modele)) {
1134
            $modele = 'typhon';
1135
1136
            if ($this->model_pdf) {
1137
                $modele = $this->model_pdf;
1138
            } elseif (getDolGlobalString('DELIVERY_ADDON_PDF')) {
1139
                $modele = getDolGlobalString('DELIVERY_ADDON_PDF');
1140
            }
1141
        }
1142
1143
        $modelpath = "core/modules/delivery/doc/";
1144
1145
        return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
1146
    }
1147
1148
    /**
1149
     * Function used to replace a thirdparty id with another one.
1150
     *
1151
     * @param   DoliDB  $dbs        Database handler, because function is static we name it $dbs not $db to avoid breaking coding test
1152
     * @param   int     $origin_id  Old thirdparty id
1153
     * @param   int     $dest_id    New thirdparty id
1154
     * @return  bool
1155
     */
1156
    public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
1157
    {
1158
        $tables = array(
1159
            'delivery'
1160
        );
1161
1162
        return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
1163
    }
1164
1165
    /**
1166
     * Function used to replace a product id with another one.
1167
     *
1168
     * @param DoliDB $db Database handler
1169
     * @param int $origin_id Old product id
1170
     * @param int $dest_id New product id
1171
     * @return bool
1172
     */
1173
    public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
1174
    {
1175
        $tables = array(
1176
            'deliverydet'
1177
        );
1178
1179
        return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
1180
    }
1181
}
1182
1183
1184
/**
1185
 *  Management class of delivery note lines
1186
 */
1187
class DeliveryLine extends CommonObjectLine
1188
{
1189
    /**
1190
     * @var DoliDB Database handler.
1191
     */
1192
    public $db;
1193
1194
    /**
1195
     * @var string ID to identify managed object
1196
     */
1197
    public $element = 'deliverydet';
1198
1199
    /**
1200
     * @var string Name of table without prefix where object is stored
1201
     */
1202
    public $table_element = 'deliverydet';
1203
1204
    /**
1205
     * @var string delivery note lines label
1206
     */
1207
    public $label;
1208
1209
    /**
1210
     * @var string product description
1211
     */
1212
    public $description;
1213
1214
    /**
1215
     * @deprecated
1216
     * @see $product_ref
1217
     */
1218
    public $ref;
1219
    /**
1220
     * @deprecated
1221
     * @see product_label;
1222
     */
1223
    public $libelle;
1224
1225
    // From llx_expeditiondet
1226
    /**
1227
     * @var float Quantity
1228
     */
1229
    public $qty;
1230
1231
    /**
1232
     * @var float Quantity asked
1233
     */
1234
    public $qty_asked;
1235
1236
    /**
1237
     * @var float Quantity shiiped
1238
     */
1239
    public $qty_shipped;
1240
1241
    public $fk_product;
1242
    public $product_desc;
1243
    public $product_type;
1244
    public $product_ref;
1245
    public $product_label;
1246
1247
    public $price;
1248
1249
    public $fk_origin_line;
1250
    public $origin_id;
1251
1252
    /**
1253
     * @var int origin line ID
1254
     */
1255
    public $origin_line_id;
1256
1257
    /**
1258
     * @var int origin line ID
1259
     * @deprecated
1260
     * @see $origin_line_id
1261
     */
1262
    public $commande_ligne_id;
1263
1264
1265
    /**
1266
     *  Constructor
1267
     *
1268
     *  @param  DoliDB  $db     Database handler
1269
     */
1270
    public function __construct($db)
1271
    {
1272
        $this->db = $db;
1273
    }
1274
}
1275