Passed
Push — EXTRACT_CLASSES ( d4f850...56e940 )
by Rafael
41:39
created

Delivery   F

Complexity

Total Complexity 133

Size/Duplication

Total Lines 1127
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 588
dl 0
loc 1127
rs 2
c 0
b 0
f 0
wmc 133

21 Methods

Rating   Name   Duplication   Size   Complexity  
A setDeliveryDate() 0 18 4
C getNomUrl() 0 57 12
A generateDocument() 0 20 4
A replaceProduct() 0 7 1
A getLibStatut() 0 3 1
A LibStatut() 0 25 5
A addline() 0 13 4
A deleteLine() 0 16 3
B create_line() 0 32 7
B getRemainingDelivered() 0 56 8
A __construct() 0 8 1
B update_line() 0 22 8
A getTooltipContentArray() 0 12 1
B delete() 0 66 11
B fetch() 0 67 5
F valid() 0 144 25
F create() 0 120 20
A replaceThirdparty() 0 7 1
A fetch_lines() 0 67 3
B create_from_sending() 0 42 6
A initAsSpecimen() 0 47 3

How to fix   Complexity   

Complex Class

Complex classes like Delivery often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Delivery, and based on these observations, apply Extract Interface, too.

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
43
/**
44
 *  Class to manage receptions
45
 */
46
class Delivery extends CommonObject
47
{
48
    use CommonIncoterm;
0 ignored issues
show
Bug introduced by
The trait Dolibarr\Code\Core\Traits\CommonIncoterm requires the property $code which is not provided by Dolibarr\Code\Delivery\Classes\Delivery.
Loading history...
49
50
    /**
51
     * @var string ID to identify managed object
52
     */
53
    public $element = "delivery";
54
55
    /**
56
     * @var string Field with ID of parent key if this field has a parent
57
     */
58
    public $fk_element = "fk_delivery";
59
60
    /**
61
     * @var string Name of table without prefix where object is stored
62
     */
63
    public $table_element = "delivery";
64
65
    /**
66
     * @var string    Name of subtable line
67
     */
68
    public $table_element_line = "deliverydet";
69
70
    /**
71
     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
72
     */
73
    public $picto = 'sending';
74
75
    /**
76
     * @var int draft status
77
     */
78
    public $draft;
79
80
    /**
81
     * @var int thirdparty id
82
     */
83
    public $socid;
84
85
    /**
86
     * @var string ref customer
87
     */
88
    public $ref_customer;
89
90
    /**
91
     * @var integer|string Date really received
92
     */
93
    public $date_delivery;
94
95
    /**
96
     * @var integer|string date_creation
97
     */
98
    public $date_creation;
99
100
    /**
101
     * @var integer|string date_valid
102
     */
103
    public $date_valid;
104
105
    /**
106
     * @var string model pdf
107
     */
108
    public $model_pdf;
109
110
    public $commande_id;
111
112
    /**
113
     * @var DeliveryLine[] lines
114
     */
115
    public $lines = array();
116
117
    /**
118
     * @var int user_author_id
119
     */
120
    public $user_author_id;
121
122
123
    /**
124
     * Constructor
125
     *
126
     * @param   DoliDB  $db     Database handler
127
     */
128
    public function __construct($db)
129
    {
130
        $this->db = $db;
131
132
        // List of short language codes for status
133
        $this->labelStatus[-1] = 'StatusDeliveryCanceled';
134
        $this->labelStatus[0]  = 'StatusDeliveryDraft';
135
        $this->labelStatus[1]  = 'StatusDeliveryValidated';
136
    }
137
138
    /**
139
     *  Create delivery receipt in database
140
     *
141
     *  @param  User    $user       Object du user qui cree
142
     *  @return int                 Return integer <0 si erreur, id delivery cree si ok
143
     */
144
    public function create($user)
145
    {
146
        global $conf;
147
148
        dol_syslog("Delivery::create");
149
150
        if (empty($this->model_pdf)) {
151
            $this->model_pdf = getDolGlobalString('DELIVERY_ADDON_PDF');
152
        }
153
154
        $error = 0;
155
156
        $now = dol_now();
157
158
        /* Delivery note as draft On positionne en mode draft le bon de livraison */
159
        $this->draft = 1;
160
161
        $this->user = $user;
162
163
        $this->db->begin();
164
165
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "delivery (";
166
        $sql .= "ref";
167
        $sql .= ", entity";
168
        $sql .= ", fk_soc";
169
        $sql .= ", ref_customer";
170
        $sql .= ", date_creation";
171
        $sql .= ", fk_user_author";
172
        $sql .= ", date_delivery";
173
        $sql .= ", fk_address";
174
        $sql .= ", note_private";
175
        $sql .= ", note_public";
176
        $sql .= ", model_pdf";
177
        $sql .= ", fk_incoterms, location_incoterms";
178
        $sql .= ") VALUES (";
179
        $sql .= "'(PROV)'";
180
        $sql .= ", " . ((int) $conf->entity);
181
        $sql .= ", " . ((int) $this->socid);
182
        $sql .= ", '" . $this->db->escape($this->ref_customer) . "'";
183
        $sql .= ", '" . $this->db->idate($now) . "'";
184
        $sql .= ", " . ((int) $user->id);
185
        $sql .= ", " . ($this->date_delivery ? "'" . $this->db->idate($this->date_delivery) . "'" : "null");
186
        $sql .= ", " . ($this->fk_delivery_address > 0 ? $this->fk_delivery_address : "null");
187
        $sql .= ", " . (!empty($this->note_private) ? "'" . $this->db->escape($this->note_private) . "'" : "null");
188
        $sql .= ", " . (!empty($this->note_public) ? "'" . $this->db->escape($this->note_public) . "'" : "null");
189
        $sql .= ", " . (!empty($this->model_pdf) ? "'" . $this->db->escape($this->model_pdf) . "'" : "null");
190
        $sql .= ", " . (int) $this->fk_incoterms;
191
        $sql .= ", '" . $this->db->escape($this->location_incoterms) . "'";
192
        $sql .= ")";
193
194
        dol_syslog("Delivery::create", LOG_DEBUG);
195
        $resql = $this->db->query($sql);
196
        if ($resql) {
197
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "delivery");
198
199
            $numref = "(PROV" . $this->id . ")";
200
201
            $sql = "UPDATE " . MAIN_DB_PREFIX . "delivery ";
202
            $sql .= "SET ref = '" . $this->db->escape($numref) . "'";
203
            $sql .= " WHERE rowid = " . ((int) $this->id);
204
205
            dol_syslog("Delivery::create", LOG_DEBUG);
206
            $resql = $this->db->query($sql);
207
            if ($resql) {
208
                if (!getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION')) {
209
                    $commande = new Commande($this->db);
210
                    $commande->id = $this->commande_id;
211
                    $commande->fetch_lines();
212
                }
213
214
215
                /*
216
                 *  Inserting products into the database
217
                 */
218
                $num = count($this->lines);
219
                for ($i = 0; $i < $num; $i++) {
220
                    $origin_id = $this->lines[$i]->origin_line_id;
221
                    if (!$origin_id) {
222
                        $origin_id = $this->lines[$i]->commande_ligne_id; // For backward compatibility
223
                    }
224
225
                    if (!$this->create_line($origin_id, $this->lines[$i]->qty, $this->lines[$i]->fk_product, $this->lines[$i]->description, $this->lines[$i]->array_options)) {
226
                        $error++;
227
                    }
228
                }
229
230
                if (!$error && $this->id && $this->origin_id) {
231
                    $ret = $this->add_object_linked();
232
                    if (!$ret) {
233
                        $error++;
234
                    }
235
236
                    if (!getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION')) {
237
                        $ret = $this->setStatut(2, $this->origin_id, $this->origin);
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$origin has been deprecated: Use $origin_type and $origin_id instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

237
                        $ret = $this->setStatut(2, $this->origin_id, /** @scrutinizer ignore-deprecated */ $this->origin);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
238
                        if (!$ret) {
239
                            $error++;
240
                        }
241
                    }
242
                }
243
244
                if (!$error) {
245
                    $this->db->commit();
246
                    return $this->id;
247
                } else {
248
                    $error++;
249
                    $this->error = $this->db->lasterror() . " - sql=" . $this->db->lastqueryerror;
250
                    $this->db->rollback();
251
                    return -3;
252
                }
253
            } else {
254
                $error++;
255
                $this->error = $this->db->lasterror() . " - sql=" . $this->db->lastqueryerror;
256
                $this->db->rollback();
257
                return -2;
258
            }
259
        } else {
260
            $error++;
261
            $this->error = $this->db->lasterror() . " - sql=" . $this->db->lastqueryerror;
262
            $this->db->rollback();
263
            return -1;
264
        }
265
    }
266
267
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
268
    /**
269
     *  Create a line
270
     *
271
     *  @param  string  $origin_id              Id of order
272
     *  @param  string  $qty                    Quantity
273
     *  @param  string  $fk_product             Id of predefined product
274
     *  @param  string  $description            Description
275
     *  @param  array   $array_options          Array options
276
     *  @return int                             Return integer <0 if KO, >0 if OK
277
     */
278
    public function create_line($origin_id, $qty, $fk_product, $description, $array_options = [])
279
    {
280
		// phpcs:enable
281
        $error = 0;
282
        $idprod = $fk_product;
283
284
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "deliverydet (fk_delivery, fk_origin_line,";
285
        $sql .= " fk_product, description, qty)";
286
        $sql .= " VALUES (" . $this->id . "," . ((int) $origin_id) . ",";
287
        $sql .= " " . ($idprod > 0 ? ((int) $idprod) : "null") . ",";
288
        $sql .= " " . ($description ? "'" . $this->db->escape($description) . "'" : "null") . ",";
289
        $sql .= (price2num($qty, 'MS')) . ")";
290
291
        dol_syslog(get_class($this) . "::create_line", LOG_DEBUG);
292
        if (!$this->db->query($sql)) {
293
            $error++;
294
        }
295
296
        $id = $this->db->last_insert_id(MAIN_DB_PREFIX . "deliverydet");
297
298
        if (is_array($array_options) && count($array_options) > 0) {
299
            $line = new DeliveryLine($this->db);
300
            $line->id = $id;
301
            $line->array_options = $array_options;
302
            $result = $line->insertExtraFields();
303
        }
304
305
        if (!$error) {
306
            return 1;
307
        }
308
309
        return -1;
310
    }
311
312
    /**
313
     *  Load a delivery receipt
314
     *
315
     *  @param  int     $id         Id of object to load
316
     *  @return integer
317
     */
318
    public function fetch($id)
319
    {
320
        $sql = "SELECT l.rowid, l.fk_soc, l.date_creation, l.date_valid, l.ref, l.ref_customer, l.fk_user_author,";
321
        $sql .= " l.total_ht, l.fk_statut, l.fk_user_valid, l.note_private, l.note_public";
322
        $sql .= ", l.date_delivery, l.fk_address, l.model_pdf";
323
        $sql .= ", el.fk_source as origin_id, el.sourcetype as origin";
324
        $sql .= ', l.fk_incoterms, l.location_incoterms';
325
        $sql .= ", i.libelle as label_incoterms";
326
        $sql .= " FROM " . MAIN_DB_PREFIX . "delivery as l";
327
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "element_element as el ON el.fk_target = l.rowid AND el.targettype = '" . $this->db->escape($this->element) . "'";
328
        $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'c_incoterms as i ON l.fk_incoterms = i.rowid';
329
        $sql .= " WHERE l.rowid = " . ((int) $id);
330
331
        dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
332
        $result = $this->db->query($sql);
333
        if ($result) {
334
            if ($this->db->num_rows($result)) {
335
                $obj = $this->db->fetch_object($result);
336
337
                $this->id                   = $obj->rowid;
338
                $this->date_delivery        = $this->db->jdate($obj->date_delivery);
339
                $this->date_creation        = $this->db->jdate($obj->date_creation);
340
                $this->date_valid           = $this->db->jdate($obj->date_valid);
341
                $this->ref                  = $obj->ref;
342
                $this->ref_customer         = $obj->ref_customer;
343
                $this->socid                = $obj->fk_soc;
344
                $this->statut               = $obj->fk_statut;
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$statut has been deprecated: Use $status instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

344
                /** @scrutinizer ignore-deprecated */ $this->statut               = $obj->fk_statut;

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
345
                $this->status               = $obj->fk_statut;
346
                $this->user_author_id       = $obj->fk_user_author;
347
                $this->user_validation_id   = $obj->fk_user_valid;
348
                $this->fk_delivery_address  = $obj->fk_address;
349
                $this->note                 = $obj->note_private; //TODO deprecated
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$note has been deprecated: Use $note_private instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

349
                /** @scrutinizer ignore-deprecated */ $this->note                 = $obj->note_private; //TODO deprecated

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
350
                $this->note_private         = $obj->note_private;
351
                $this->note_public          = $obj->note_public;
352
                $this->model_pdf            = $obj->model_pdf;
353
                $this->origin               = $obj->origin; // May be 'shipping'
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$origin has been deprecated: Use $origin_type and $origin_id instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

353
                /** @scrutinizer ignore-deprecated */ $this->origin               = $obj->origin; // May be 'shipping'

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
354
                $this->origin_id            = $obj->origin_id; // May be id of shipping
355
356
                //Incoterms
357
                $this->fk_incoterms = $obj->fk_incoterms;
358
                $this->location_incoterms = $obj->location_incoterms;
359
                $this->label_incoterms = $obj->label_incoterms;
360
                $this->db->free($result);
361
362
                if ($this->statut == 0) {
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$statut has been deprecated: Use $status instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

362
                if (/** @scrutinizer ignore-deprecated */ $this->statut == 0) {

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
363
                    $this->draft = 1;
364
                }
365
366
                // Retrieve all extrafields
367
                // fetch optionals attributes and labels
368
                $this->fetch_optionals();
369
370
                // Load lines
371
                $result = $this->fetch_lines();
372
                if ($result < 0) {
373
                    return -3;
374
                }
375
376
                return 1;
377
            } else {
378
                $this->error = 'Delivery with id ' . $id . ' not found sql=' . $sql;
379
                dol_syslog(get_class($this) . '::fetch Error ' . $this->error, LOG_ERR);
380
                return -2;
381
            }
382
        } else {
383
            $this->error = $this->db->error();
384
            return -1;
385
        }
386
    }
387
388
    /**
389
     *  Validate object and update stock if option enabled
390
     *
391
     *  @param  User    $user       Object user that validate
392
     *  @param  int     $notrigger  1=Does not execute triggers, 0= execute triggers
393
     *  @return int
394
     */
395
    public function valid($user, $notrigger = 0)
396
    {
397
        global $conf;
398
399
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
400
401
        dol_syslog(get_class($this) . "::valid begin");
402
403
        $this->db->begin();
404
405
        $error = 0;
406
407
        if (
408
            (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('expedition', 'delivery', 'creer'))
409
            || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('expedition', 'delivery_advance', 'validate'))
410
        ) {
411
            if (getDolGlobalString('DELIVERY_ADDON_NUMBER')) {
412
                // Setting the command numbering module name
413
                $modName = getDolGlobalString('DELIVERY_ADDON_NUMBER');
414
415
                if (is_readable(DOL_DOCUMENT_ROOT . '/core/modules/delivery/' . $modName . '.php')) {
416
                    require_once constant('DOL_DOCUMENT_ROOT') . '/core/modules/delivery/' . $modName . '.php';
417
418
                    $now = dol_now();
419
420
                    // Retrieving the new reference
421
                    $objMod = new $modName($this->db);
422
                    $soc = new Societe($this->db);
423
                    $soc->fetch($this->socid);
424
425
                    if (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref)) { // empty should not happened, but when it occurs, the test save life
426
                        $numref = $objMod->delivery_get_num($soc, $this);
427
                    } else {
428
                        $numref = $this->ref;
429
                    }
430
                    $this->newref = dol_sanitizeFileName($numref);
431
432
                    // Test if is not already in valid status. If so, we stop to avoid decrementing the stock twice.
433
                    $sql = "SELECT ref";
434
                    $sql .= " FROM " . MAIN_DB_PREFIX . "delivery";
435
                    $sql .= " WHERE ref = '" . $this->db->escape($numref) . "'";
436
                    $sql .= " AND fk_statut <> 0";
437
                    $sql .= " AND entity = " . ((int) $conf->entity);
438
439
                    $resql = $this->db->query($sql);
440
                    if ($resql) {
441
                        $num = $this->db->num_rows($resql);
442
                        if ($num > 0) {
443
                            return 0;
444
                        }
445
                    }
446
447
                    $sql = "UPDATE " . MAIN_DB_PREFIX . "delivery SET";
448
                    $sql .= " ref='" . $this->db->escape($numref) . "'";
449
                    $sql .= ", fk_statut = 1";
450
                    $sql .= ", date_valid = '" . $this->db->idate($now) . "'";
451
                    $sql .= ", fk_user_valid = " . $user->id;
452
                    $sql .= " WHERE rowid = " . ((int) $this->id);
453
                    $sql .= " AND fk_statut = 0";
454
455
                    $resql = $this->db->query($sql);
456
                    if (!$resql) {
457
                        dol_print_error($this->db);
458
                        $this->error = $this->db->lasterror();
459
                        $error++;
460
                    }
461
462
                    if (!$error && !$notrigger) {
463
                        // Call trigger
464
                        $result = $this->call_trigger('DELIVERY_VALIDATE', $user);
465
                        if ($result < 0) {
466
                            $error++;
467
                        }
468
                        // End call triggers
469
                    }
470
471
                    if (!$error) {
472
                        $this->oldref = $this->ref;
473
474
                        // Rename directory if dir was a temporary ref
475
                        if (preg_match('/^[\(]?PROV/i', $this->ref)) {
476
                            // Now we rename also files into index
477
                            $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) . "'";
478
                            $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'expedition/receipt/" . $this->db->escape($this->ref) . "' and entity = " . ((int) $conf->entity);
479
                            $resql = $this->db->query($sql);
480
                            if (!$resql) {
481
                                $error++;
482
                                $this->error = $this->db->lasterror();
483
                            }
484
                            $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filepath = 'expedition/receipt/" . $this->db->escape($this->newref) . "'";
485
                            $sql .= " WHERE filepath = 'expedition/receipt/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
486
                            $resql = $this->db->query($sql);
487
                            if (!$resql) {
488
                                $error++;
489
                                $this->error = $this->db->lasterror();
490
                            }
491
492
                            // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
493
                            $oldref = dol_sanitizeFileName($this->ref);
494
                            $newref = dol_sanitizeFileName($numref);
495
                            $dirsource = $conf->expedition->dir_output . '/receipt/' . $oldref;
496
                            $dirdest = $conf->expedition->dir_output . '/receipt/' . $newref;
497
                            if (!$error && file_exists($dirsource)) {
498
                                dol_syslog(get_class($this) . "::valid rename dir " . $dirsource . " into " . $dirdest);
499
500
                                if (@rename($dirsource, $dirdest)) {
501
                                    dol_syslog("Rename ok");
502
                                    // Rename docs starting with $oldref with $newref
503
                                    $listoffiles = dol_dir_list($conf->expedition->dir_output . '/receipt/' . $newref, 'files', 1, '^' . preg_quote($oldref, '/'));
504
                                    foreach ($listoffiles as $fileentry) {
505
                                        $dirsource = $fileentry['name'];
506
                                        $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
507
                                        $dirsource = $fileentry['path'] . '/' . $dirsource;
508
                                        $dirdest = $fileentry['path'] . '/' . $dirdest;
509
                                        @rename($dirsource, $dirdest);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for rename(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

509
                                        /** @scrutinizer ignore-unhandled */ @rename($dirsource, $dirdest);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
510
                                    }
511
                                }
512
                            }
513
                        }
514
515
                        // Set new ref and current status
516
                        if (!$error) {
517
                            $this->ref = $numref;
518
                            $this->statut = 1;
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$statut has been deprecated: Use $status instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

518
                            /** @scrutinizer ignore-deprecated */ $this->statut = 1;

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
519
                        }
520
521
                        dol_syslog(get_class($this) . "::valid ok");
522
                    }
523
524
                    if (!$error) {
525
                        $this->db->commit();
526
                        return 1;
527
                    } else {
528
                        $this->db->rollback();
529
                        return -1;
530
                    }
531
                }
532
            }
533
534
            return -1;
535
        } else {
536
            $this->error = "NotAllowed";
537
            dol_syslog(get_class($this) . "::valid " . $this->error, LOG_ERR);
538
            return -1;
539
        }
540
    }
541
542
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
543
    /**
544
     *  Creating the delivery slip from an existing shipment
545
     *
546
     *  @param  User    $user           User who creates
547
     *  @param  int     $sending_id     Id of the expedition that serves as a model
548
     *  @return integer                 Return integer <=0 if KO, >0 if OK
549
     */
550
    public function create_from_sending($user, $sending_id)
551
    {
552
		// phpcs:enable
553
        global $conf;
554
555
        $expedition = new Expedition($this->db);
556
        $result = $expedition->fetch($sending_id);
557
        if ($result <= 0) {
558
            return $result;
559
        }
560
561
        $this->lines = array();
562
563
        $num = count($expedition->lines);
564
        for ($i = 0; $i < $num; $i++) {
565
            $line = new DeliveryLine($this->db);
566
            $line->origin_line_id    = $expedition->lines[$i]->origin_line_id;
567
            $line->label             = $expedition->lines[$i]->label;
568
            $line->description       = $expedition->lines[$i]->description;
569
            $line->qty               = $expedition->lines[$i]->qty_shipped;
570
            $line->fk_product        = $expedition->lines[$i]->fk_product;
571
            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
572
                $line->array_options = $expedition->lines[$i]->array_options;
573
            }
574
            $this->lines[$i] = $line;
575
        }
576
577
        $this->origin               = $expedition->element;
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$origin has been deprecated: Use $origin_type and $origin_id instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

577
        /** @scrutinizer ignore-deprecated */ $this->origin               = $expedition->element;

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
578
        $this->origin_id            = $expedition->id;
579
        $this->note_private         = $expedition->note_private;
580
        $this->note_public          = $expedition->note_public;
581
        $this->fk_project           = $expedition->fk_project;
582
        $this->date_delivery        = $expedition->date_delivery;
583
        $this->fk_delivery_address  = $expedition->fk_delivery_address;
584
        $this->socid                = $expedition->socid;
585
        $this->ref_customer         = $expedition->ref_customer;
586
587
        //Incoterms
588
        $this->fk_incoterms = $expedition->fk_incoterms;
589
        $this->location_incoterms = $expedition->location_incoterms;
590
591
        return $this->create($user);
592
    }
593
594
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
595
    /**
596
     * Update a livraison line (only extrafields)
597
     *
598
     * @param   int     $id                 Id of line (livraison line)
599
     * @param   array   $array_options      extrafields array
600
     * @return  int                         Return integer <0 if KO, >0 if OK
601
     */
602
    public function update_line($id, $array_options = [])
603
    {
604
		// phpcs:enable
605
        global $conf;
606
        $error = 0;
607
608
        if ($id > 0 && !$error && !getDolGlobalString('MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) { // For avoid conflicts if trigger used
609
            $line = new DeliveryLine($this->db);
610
            $line->array_options = $array_options;
611
            $line->id = $id;
612
            $result = $line->insertExtraFields();
613
614
            if ($result < 0) {
615
                $this->errors[] = $line->error;
616
                $error++;
617
            }
618
        }
619
620
        if (!$error) {
621
            return 1;
622
        } else {
623
            return -1;
624
        }
625
    }
626
627
628
    /**
629
     *  Add line
630
     *
631
     *  @param  int     $origin_id              Origin id
632
     *  @param  float   $qty                    Qty
633
     *  @param  array   $array_options          Array options
634
     *  @return void
635
     */
636
    public function addline($origin_id, $qty, $array_options = [])
637
    {
638
        global $conf;
639
640
        $num = count($this->lines);
641
        $line = new DeliveryLine($this->db);
642
643
        $line->origin_id = $origin_id;
644
        $line->qty = $qty;
645
        if (!getDolGlobalString('MAIN_EXTRAFIELDS_DISABLED') && is_array($array_options) && count($array_options) > 0) { // For avoid conflicts if trigger used
646
            $line->array_options = $array_options;
647
        }
648
        $this->lines[$num] = $line;
649
    }
650
651
    /**
652
     *  Delete line
653
     *
654
     *  @param  int     $lineid     Line id
655
     *  @return integer             Return integer <0 if KO, 0 if nothing done, >0 if OK
656
     */
657
    public function deleteLine($lineid)
658
    {
659
        if ($this->statut == 0) {
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$statut has been deprecated: Use $status instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

659
        if (/** @scrutinizer ignore-deprecated */ $this->statut == 0) {

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
660
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "commandedet";
661
            $sql .= " WHERE rowid = " . ((int) $lineid);
662
663
            if ($this->db->query($sql)) {
664
                $this->update_price(1);
665
666
                return 1;
667
            } else {
668
                return -1;
669
            }
670
        }
671
672
        return 0;
673
    }
674
675
    /**
676
     * Delete object
677
     *
678
     * @param   User        $user       User making the deletion
679
     * @return  integer
680
     */
681
    public function delete($user = null)
682
    {
683
        global $conf, $langs;
684
685
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
686
687
        $this->db->begin();
688
689
        $error = 0;
690
691
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "deliverydet";
692
        $sql .= " WHERE fk_delivery = " . ((int) $this->id);
693
        if ($this->db->query($sql)) {
694
            // Delete linked object
695
            $res = $this->deleteObjectLinked();
696
            if ($res < 0) {
697
                $error++;
698
            }
699
700
            if (!$error) {
701
                $sql = "DELETE FROM " . MAIN_DB_PREFIX . "delivery";
702
                $sql .= " WHERE rowid = " . ((int) $this->id);
703
                if ($this->db->query($sql)) {
704
                    $this->db->commit();
705
706
                    // Deleting pdf folder's draft On efface le repertoire de pdf provisoire
707
                    $ref = dol_sanitizeFileName($this->ref);
708
                    if (!empty($conf->expedition->dir_output)) {
709
                        $dir = $conf->expedition->dir_output . '/receipt/' . $ref;
710
                        $file = $dir . '/' . $ref . '.pdf';
711
                        if (file_exists($file)) {
712
                            if (!dol_delete_file($file)) {
713
                                return 0;
714
                            }
715
                        }
716
                        if (file_exists($dir)) {
717
                            if (!dol_delete_dir($dir)) {
718
                                $this->error = $langs->trans("ErrorCanNotDeleteDir", $dir);
719
                                return 0;
720
                            }
721
                        }
722
                    }
723
724
                    // Call trigger
725
                    $result = $this->call_trigger('DELIVERY_DELETE', $user);
726
                    if ($result < 0) {
727
                        $this->db->rollback();
728
                        return -4;
729
                    }
730
                    // End call triggers
731
732
                    return 1;
733
                } else {
734
                    $this->error = $this->db->lasterror() . " - sql=$sql";
735
                    $this->db->rollback();
736
                    return -3;
737
                }
738
            } else {
739
                $this->error = $this->db->lasterror() . " - sql=$sql";
740
                $this->db->rollback();
741
                return -2;
742
            }
743
        } else {
744
            $this->error = $this->db->lasterror() . " - sql=$sql";
745
            $this->db->rollback();
746
            return -1;
747
        }
748
    }
749
750
    /**
751
     * getTooltipContentArray
752
     * @param array $params params to construct tooltip data
753
     * @since v18
754
     * @return array
755
     */
756
    public function getTooltipContentArray($params)
757
    {
758
        global $langs;
759
760
        $langs->load('deliveries');
761
762
        $datas = [];
763
764
        $datas['picto'] = img_picto('', $this->picto) . ' <u>' . $langs->trans("ShowReceiving") . '</u>:<br>';
765
        $datas['picto'] .= '<b>' . $langs->trans("Status") . '</b>: ' . $this->ref;
766
767
        return $datas;
768
    }
769
770
    /**
771
     *  Return clicable name (with picto eventually)
772
     *
773
     *  @param  int     $withpicto                  0=No picto, 1=Include picto into link, 2=Only picto
774
     *  @param  int     $save_lastsearch_value      -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
775
     *  @return string                              Chaine avec URL
776
     */
777
    public function getNomUrl($withpicto = 0, $save_lastsearch_value = -1)
778
    {
779
        global $langs, $hookmanager;
780
781
        $result = '';
782
783
        $params = [
784
            'id' => $this->id,
785
            'objecttype' => $this->element,
786
        ];
787
        $classfortooltip = 'classfortooltip';
788
        $dataparams = '';
789
        if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
790
            $classfortooltip = 'classforajaxtooltip';
791
            $dataparams = ' data-params="' . dol_escape_htmltag(json_encode($params)) . '"';
792
            $label = '';
793
        } else {
794
            $label = implode($this->getTooltipContentArray($params));
795
        }
796
797
        $url = constant('BASE_URL') . '/delivery/card.php?id=' . $this->id;
798
799
        //if ($option !== 'nolink')
800
        //{
801
        // Add param to save lastsearch_values or not
802
        $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
803
        if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
804
            $add_save_lastsearch_values = 1;
805
        }
806
        if ($add_save_lastsearch_values) {
807
            $url .= '&save_lastsearch_values=1';
808
        }
809
        //}
810
811
        $linkstart = '<a href="' . $url . '"';
812
        $linkstart .= ($label ? ' title="' . dol_escape_htmltag($label, 1) . '"' : ' title="tocomplete"');
813
        $linkstart .= $dataparams . ' class="' . $classfortooltip . '">';
814
        $linkend = '</a>';
815
816
        if ($withpicto) {
817
            $result .= ($linkstart . img_object($label, $this->picto, $dataparams . ' class="' . $classfortooltip . '"') . $linkend);
818
        }
819
        if ($withpicto && $withpicto != 2) {
820
            $result .= ' ';
821
        }
822
        $result .= $linkstart . $this->ref . $linkend;
823
824
        global $action;
825
        $hookmanager->initHooks(array($this->element . 'dao'));
826
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
827
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
828
        if ($reshook > 0) {
829
            $result = $hookmanager->resPrint;
830
        } else {
831
            $result .= $hookmanager->resPrint;
832
        }
833
        return $result;
834
    }
835
836
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
837
    /**
838
     *  Load lines insto $this->lines.
839
     *
840
     *  @return     int                             Return integer <0 if KO, >0 if OK
841
     */
842
    public function fetch_lines()
843
    {
844
		// phpcs:enable
845
        $this->lines = array();
846
847
        $sql = "SELECT ld.rowid, ld.fk_product, ld.description, ld.subprice, ld.total_ht, ld.qty as qty_shipped, ld.fk_origin_line, ";
848
        $sql .= " cd.qty as qty_asked, cd.label as custom_label, cd.fk_unit,";
849
        $sql .= " p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc,";
850
        $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";
851
        $sql .= " FROM " . MAIN_DB_PREFIX . "commandedet as cd, " . MAIN_DB_PREFIX . "deliverydet as ld";
852
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p on p.rowid = ld.fk_product";
853
        $sql .= " WHERE ld.fk_origin_line = cd.rowid";
854
        $sql .= " AND ld.fk_delivery = " . ((int) $this->id);
855
856
        dol_syslog(get_class($this) . "::fetch_lines", LOG_DEBUG);
857
        $resql = $this->db->query($sql);
858
        if ($resql) {
859
            $num = $this->db->num_rows($resql);
860
            $i = 0;
861
            while ($i < $num) {
862
                $obj = $this->db->fetch_object($resql);
863
864
                $line = new DeliveryLine($this->db);
865
866
                $line->id = $obj->rowid;
867
                $line->label = $obj->custom_label;
868
                $line->description  = $obj->description;
869
                $line->fk_product   = $obj->fk_product;
870
                $line->qty_asked    = $obj->qty_asked;
871
                $line->qty_shipped  = $obj->qty_shipped;
872
873
                $line->product_label    = $obj->product_label; // Product label
874
                $line->product_ref      = $obj->product_ref; // Product ref
875
                $line->product_desc     = $obj->product_desc; // Product description
876
                $line->product_type     = $obj->fk_product_type;
877
878
                $line->fk_origin_line = $obj->fk_origin_line;
879
880
                $line->price = $obj->subprice;
881
                $line->total_ht = $obj->total_ht;
882
883
                // units
884
                $line->weight           = $obj->weight;
885
                $line->weight_units     = $obj->weight_units;
886
                $line->width            = $obj->width;
887
                $line->width_units      = $obj->width_units;
888
                $line->height           = $obj->height;
889
                $line->height_units     = $obj->height_units;
890
                $line->length           = $obj->length;
891
                $line->length_units     = $obj->length_units;
892
                $line->surface          = $obj->surface;
893
                $line->surface_units = $obj->surface_units;
894
                $line->volume           = $obj->volume;
895
                $line->volume_units     = $obj->volume_units;
896
897
                $line->fk_unit = $obj->fk_unit;
898
                $line->fetch_optionals();
899
900
                $this->lines[$i] = $line;
901
902
                $i++;
903
            }
904
            $this->db->free($resql);
905
906
            return 1;
907
        } else {
908
            return -1;
909
        }
910
    }
911
912
913
    /**
914
     *  Return the label of the status
915
     *
916
     *  @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
917
     *  @return string                 Label of status
918
     */
919
    public function getLibStatut($mode = 0)
920
    {
921
        return $this->LibStatut($this->statut, $mode);
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$statut has been deprecated: Use $status instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

921
        return $this->LibStatut(/** @scrutinizer ignore-deprecated */ $this->statut, $mode);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
922
    }
923
924
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
925
    /**
926
     *  Return the label of a given status
927
     *
928
     *  @param  int     $status        Id status
929
     *  @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
930
     *  @return string                 Label of status
931
     */
932
    public function LibStatut($status, $mode)
933
    {
934
		// phpcs:enable
935
        global $langs;
936
937
        if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
938
            global $langs;
939
            //$langs->load("mymodule");
940
            $this->labelStatus[-1] = $langs->transnoentitiesnoconv('StatusDeliveryCanceled');
941
            $this->labelStatus[0] = $langs->transnoentitiesnoconv('StatusDeliveryDraft');
942
            $this->labelStatus[1] = $langs->transnoentitiesnoconv('StatusDeliveryValidated');
943
            $this->labelStatusShort[-1] = $langs->transnoentitiesnoconv('StatusDeliveryCanceled');
944
            $this->labelStatusShort[0] = $langs->transnoentitiesnoconv('StatusDeliveryDraft');
945
            $this->labelStatusShort[1] = $langs->transnoentitiesnoconv('StatusDeliveryValidated');
946
        }
947
948
        $statusType = 'status0';
949
        if ($status == -1) {
950
            $statusType = 'status5';
951
        }
952
        if ($status == 1) {
953
            $statusType = 'status4';
954
        }
955
956
        return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
957
    }
958
959
960
    /**
961
     *  Initialise an instance with random values.
962
     *  Used to build previews or test instances.
963
     *  id must be 0 if object instance is a specimen.
964
     *
965
     *  @return int
966
     */
967
    public function initAsSpecimen()
968
    {
969
        $now = dol_now();
970
971
        // Load array of products prodids
972
        $num_prods = 0;
973
        $prodids = array();
974
        $sql = "SELECT rowid";
975
        $sql .= " FROM " . MAIN_DB_PREFIX . "product";
976
        $sql .= " WHERE entity IN (" . getEntity('product') . ")";
977
        $sql .= " AND tosell = 1";
978
        $sql .= $this->db->plimit(100);
979
980
        $resql = $this->db->query($sql);
981
        if ($resql) {
982
            $num_prods = $this->db->num_rows($resql);
983
            $i = 0;
984
            while ($i < $num_prods) {
985
                $i++;
986
                $row = $this->db->fetch_row($resql);
987
                $prodids[$i] = $row[0];
988
            }
989
        }
990
991
        // Initialise parameters
992
        $this->id = 0;
993
        $this->ref = 'SPECIMEN';
994
        $this->specimen = 1;
995
        $this->socid = 1;
996
        $this->date_delivery = $now;
997
        $this->note_public = 'Public note';
998
        $this->note_private = 'Private note';
999
1000
        $i = 0;
1001
        $line = new DeliveryLine($this->db);
1002
        $line->fk_product     = reset($prodids);
1003
        $line->qty_asked      = 10;
1004
        $line->qty_shipped    = 9;
1005
        $line->ref            = 'REFPROD';
1006
        $line->label          = 'Specimen';
1007
        $line->description    = 'Description';
1008
        $line->price          = 100;
1009
        $line->total_ht       = 100;
1010
1011
        $this->lines[$i] = $line;
1012
1013
        return 1;
1014
    }
1015
1016
    /**
1017
     *  Renvoie la quantite de produit restante a livrer pour une commande
1018
     *
1019
     *  @return     array|int       Product remaining to be delivered or <0 if KO
1020
     *  TODO use new function
1021
     */
1022
    public function getRemainingDelivered()
1023
    {
1024
        // Get the linked object
1025
        $this->fetchObjectLinked('', '', $this->id, $this->element);
1026
        //var_dump($this->linkedObjectsIds);
1027
        // Get the product ref and qty in source
1028
        $sqlSourceLine = "SELECT st.rowid, st.description, st.qty";
1029
        $sqlSourceLine .= ", p.ref, p.label";
1030
        $sqlSourceLine .= " FROM " . MAIN_DB_PREFIX . $this->linkedObjectsIds[0]['type'] . "det as st";
1031
        $sqlSourceLine .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON st.fk_product = p.rowid";
1032
        $sqlSourceLine .= " WHERE fk_" . $this->linked_objects[0]['type'] . " = " . ((int) $this->linked_objects[0]['linkid']);
1033
1034
        $resultSourceLine = $this->db->query($sqlSourceLine);
1035
        if ($resultSourceLine) {
1036
            $num_lines = $this->db->num_rows($resultSourceLine);
1037
            $i = 0;
1038
            $array = array();
1039
            while ($i < $num_lines) {
1040
                $objSourceLine = $this->db->fetch_object($resultSourceLine);
1041
1042
                // Get lines of sources already delivered
1043
                $sql = "SELECT ld.fk_origin_line, sum(ld.qty) as qty";
1044
                $sql .= " FROM " . MAIN_DB_PREFIX . "deliverydet as ld, " . MAIN_DB_PREFIX . "delivery as l,";
1045
                $sql .= " " . MAIN_DB_PREFIX . $this->linked_objects[0]['type'] . " as c";
1046
                $sql .= ", " . MAIN_DB_PREFIX . $this->linked_objects[0]['type'] . "det as cd";
1047
                $sql .= " WHERE ld.fk_delivery = l.rowid";
1048
                $sql .= " AND ld.fk_origin_line = cd.rowid";
1049
                $sql .= " AND cd.fk_" . $this->linked_objects[0]['type'] . " = c.rowid";
1050
                $sql .= " AND cd.fk_" . $this->linked_objects[0]['type'] . " = " . ((int) $this->linked_objects[0]['linkid']);
1051
                $sql .= " AND ld.fk_origin_line = " . ((int) $objSourceLine->rowid);
1052
                $sql .= " GROUP BY ld.fk_origin_line";
1053
1054
                $result = $this->db->query($sql);
1055
                $row = $this->db->fetch_row($result);
1056
1057
                if ($objSourceLine->qty - $row[1] > 0) {
1058
                    if ($row[0] == $objSourceLine->rowid) {
1059
                        $array[$i]['qty'] = $objSourceLine->qty - $row[1];
1060
                    } else {
1061
                        $array[$i]['qty'] = $objSourceLine->qty;
1062
                    }
1063
1064
                    $array[$i]['ref'] = $objSourceLine->ref;
1065
                    $array[$i]['label'] = $objSourceLine->label ? $objSourceLine->label : $objSourceLine->description;
1066
                } elseif ($objSourceLine->qty - $row[1] < 0) {
1067
                    $array[$i]['qty'] = $objSourceLine->qty - $row[1] . " Erreur livraison !";
1068
                    $array[$i]['ref'] = $objSourceLine->ref;
1069
                    $array[$i]['label'] = $objSourceLine->label ? $objSourceLine->label : $objSourceLine->description;
1070
                }
1071
1072
                $i++;
1073
            }
1074
            return $array;
1075
        } else {
1076
            $this->error = $this->db->error() . " - sql=$sqlSourceLine";
1077
            return -1;
1078
        }
1079
    }
1080
1081
    /**
1082
     *  Set the planned delivery date
1083
     *
1084
     *  @param      User            $user               Object utilisateur qui modifie
1085
     *  @param      integer         $delivery_date     Delivery date
1086
     *  @return     int                                 Return integer <0 if KO, >0 if OK
1087
     */
1088
    public function setDeliveryDate($user, $delivery_date)
1089
    {
1090
        if ($user->hasRight('expedition', 'creer')) {
1091
            $sql = "UPDATE " . MAIN_DB_PREFIX . "delivery";
1092
            $sql .= " SET date_delivery = " . ($delivery_date ? "'" . $this->db->idate($delivery_date) . "'" : 'null');
1093
            $sql .= " WHERE rowid = " . ((int) $this->id);
1094
1095
            dol_syslog(get_class($this) . "::setDeliveryDate", LOG_DEBUG);
1096
            $resql = $this->db->query($sql);
1097
            if ($resql) {
1098
                $this->date_delivery = $delivery_date;
1099
                return 1;
1100
            } else {
1101
                $this->error = $this->db->error();
1102
                return -1;
1103
            }
1104
        } else {
1105
            return -2;
1106
        }
1107
    }
1108
1109
    /**
1110
     *  Create object on disk
1111
     *
1112
     *  @param     string       $modele         force le modele a utiliser ('' to not force)
1113
     *  @param     Translate    $outputlangs    Object langs to use for output
1114
     *  @param     int          $hidedetails    Hide details of lines
1115
     *  @param     int          $hidedesc       Hide description
1116
     *  @param     int          $hideref        Hide ref
1117
     *  @return    int                          0 if KO, 1 if OK
1118
     */
1119
    public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
1120
    {
1121
        global $conf, $langs;
1122
1123
        $langs->load("deliveries");
1124
        $outputlangs->load("products");
1125
1126
        if (!dol_strlen($modele)) {
1127
            $modele = 'typhon';
1128
1129
            if ($this->model_pdf) {
1130
                $modele = $this->model_pdf;
1131
            } elseif (getDolGlobalString('DELIVERY_ADDON_PDF')) {
1132
                $modele = getDolGlobalString('DELIVERY_ADDON_PDF');
1133
            }
1134
        }
1135
1136
        $modelpath = "core/modules/delivery/doc/";
1137
1138
        return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
1139
    }
1140
1141
    /**
1142
     * Function used to replace a thirdparty id with another one.
1143
     *
1144
     * @param   DoliDB  $dbs        Database handler, because function is static we name it $dbs not $db to avoid breaking coding test
1145
     * @param   int     $origin_id  Old thirdparty id
1146
     * @param   int     $dest_id    New thirdparty id
1147
     * @return  bool
1148
     */
1149
    public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
1150
    {
1151
        $tables = array(
1152
            'delivery'
1153
        );
1154
1155
        return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
1156
    }
1157
1158
    /**
1159
     * Function used to replace a product id with another one.
1160
     *
1161
     * @param DoliDB $db Database handler
1162
     * @param int $origin_id Old product id
1163
     * @param int $dest_id New product id
1164
     * @return bool
1165
     */
1166
    public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
1167
    {
1168
        $tables = array(
1169
            'deliverydet'
1170
        );
1171
1172
        return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
1173
    }
1174
}
1175
1176
1177
/**
1178
 *  Management class of delivery note lines
1179
 */
1180
class DeliveryLine extends CommonObjectLine
1181
{
1182
    /**
1183
     * @var DoliDB Database handler.
1184
     */
1185
    public $db;
1186
1187
    /**
1188
     * @var string ID to identify managed object
1189
     */
1190
    public $element = 'deliverydet';
1191
1192
    /**
1193
     * @var string Name of table without prefix where object is stored
1194
     */
1195
    public $table_element = 'deliverydet';
1196
1197
    /**
1198
     * @var string delivery note lines label
1199
     */
1200
    public $label;
1201
1202
    /**
1203
     * @var string product description
1204
     */
1205
    public $description;
1206
1207
    /**
1208
     * @deprecated
1209
     * @see $product_ref
1210
     */
1211
    public $ref;
1212
    /**
1213
     * @deprecated
1214
     * @see product_label;
1215
     */
1216
    public $libelle;
1217
1218
    // From llx_expeditiondet
1219
    /**
1220
     * @var float Quantity
1221
     */
1222
    public $qty;
1223
1224
    /**
1225
     * @var float Quantity asked
1226
     */
1227
    public $qty_asked;
1228
1229
    /**
1230
     * @var float Quantity shiiped
1231
     */
1232
    public $qty_shipped;
1233
1234
    public $fk_product;
1235
    public $product_desc;
1236
    public $product_type;
1237
    public $product_ref;
1238
    public $product_label;
1239
1240
    public $price;
1241
1242
    public $fk_origin_line;
1243
    public $origin_id;
1244
1245
    /**
1246
     * @var int origin line ID
1247
     */
1248
    public $origin_line_id;
1249
1250
    /**
1251
     * @var int origin line ID
1252
     * @deprecated
1253
     * @see $origin_line_id
1254
     */
1255
    public $commande_ligne_id;
1256
1257
1258
    /**
1259
     *  Constructor
1260
     *
1261
     *  @param  DoliDB  $db     Database handler
1262
     */
1263
    public function __construct($db)
1264
    {
1265
        $this->db = $db;
1266
    }
1267
}
1268