Passed
Push — EXTRACT_CLASSES ( d3ffdd...d4f850 )
by Rafael
39:11
created

InterfaceWorkflowManager::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* Copyright (C) 2010       Regis Houssin               <[email protected]>
4
 * Copyright (C) 2011-2017  Laurent Destailleur         <[email protected]>
5
 * Copyright (C) 2014       Marcos García               <[email protected]>
6
 * Copyright (C) 2022       Ferran Marcet               <[email protected]>
7
 * Copyright (C) 2023       Alexandre Janniaux          <[email protected]>
8
 * Copyright (C) 2024		MDW							<[email protected]>
9
 * Copyright (C) 2024       Rafael San José             <[email protected]>
10
 *
11
 * This program is free software; you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation; either version 3 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23
 */
24
25
use Dolibarr\Code\Commande\Classes\Commande;
26
use Dolibarr\Code\Core\Classes\Conf;
27
use Dolibarr\Code\Core\Classes\Translate;
28
use Dolibarr\Code\User\Classes\User;
29
use Dolibarr\Core\Base\CommonObject;
30
31
/**
32
 *  \file       htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php
33
 *  \ingroup    core
34
 *  \brief      Trigger file for workflows
35
 */
36
37
require_once constant('DOL_DOCUMENT_ROOT') . '/core/triggers/dolibarrtriggers.class.php';
38
39
40
/**
41
 *  Class of triggers for workflow module
42
 */
43
class InterfaceWorkflowManager extends DolibarrTriggers
44
{
45
    /**
46
     * Constructor
47
     *
48
     * @param DoliDB $db Database handler
49
     */
50
    public function __construct($db)
51
    {
52
        $this->db = $db;
53
54
        $this->name = preg_replace('/^Interface/i', '', get_class($this));
55
        $this->family = "core";
56
        $this->description = "Triggers of this module allows to manage workflows";
57
        $this->version = self::VERSIONS['prod'];
58
        $this->picto = 'technic';
59
    }
60
61
    /**
62
     * Function called when a Dolibarr business event is done.
63
     * All functions "runTrigger" are triggered if file is inside directory htdocs/core/triggers or htdocs/module/code/triggers (and declared)
64
     *
65
     * @param string $action Event action code
66
     * @param CommonObject $object Object
67
     * @param User $user Object user
68
     * @param Translate $langs Object langs
69
     * @param Conf $conf Object conf
70
     * @return int                      Return integer <0 if KO, 0 if no triggered ran, >0 if OK
71
     */
72
    public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf)
73
    {
74
        if (empty($conf->workflow) || empty($conf->workflow->enabled)) {
75
            return 0; // Module not active, we do nothing
76
        }
77
78
        $ret = 0;
79
80
        // Proposals to order
81
        if ($action == 'PROPAL_CLOSE_SIGNED') {
82
            dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id);
83
            if (isModEnabled('order') && getDolGlobalString('WORKFLOW_PROPAL_AUTOCREATE_ORDER')) {
84
                $object->fetchObjectLinked();
85
                if (!empty($object->linkedObjectsIds['commande'])) {
86
                    if (empty($object->context['closedfromonlinesignature'])) {
87
                        $langs->load("orders");
88
                        setEventMessages($langs->trans("OrderExists"), null, 'warnings');
89
                    }
90
                    return $ret;
91
                }
92
93
                $newobject = new Commande($this->db);
94
95
                $newobject->context['createfrompropal'] = 'createfrompropal';
96
                $newobject->context['origin'] = $object->element;
97
                $newobject->context['origin_id'] = $object->id;
98
99
                $ret = $newobject->createFromProposal($object, $user);
100
                if ($ret < 0) {
101
                    $this->setErrorsFromObject($newobject);
102
                }
103
104
                $object->clearObjectLinkedCache();
105
106
                return (int)$ret;
107
            }
108
        }
109
110
        // Order to invoice
111
        if ($action == 'ORDER_CLOSE') {
112
            dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id);
113
            if (isModEnabled('invoice') && getDolGlobalString('WORKFLOW_ORDER_AUTOCREATE_INVOICE')) {
114
                $newobject = new Facture($this->db);
115
116
                $newobject->context['createfromorder'] = 'createfromorder';
117
                $newobject->context['origin'] = $object->element;
118
                $newobject->context['origin_id'] = $object->id;
119
120
                $ret = $newobject->createFromOrder($object, $user);
121
                if ($ret < 0) {
122
                    $this->setErrorsFromObject($newobject);
123
                } else {
124
                    if (empty($object->fk_account) && !empty($object->thirdparty->fk_account) && !getDolGlobalInt('BANK_ASK_PAYMENT_BANK_DURING_ORDER')) {
125
                        $res = $newobject->setBankAccount($object->thirdparty->fk_account, true, $user);
126
                        if ($ret < 0) {
127
                            $this->setErrorsFromObject($newobject);
128
                        }
129
                    }
130
                }
131
132
                $object->clearObjectLinkedCache();
133
134
                return $ret;
135
            }
136
        }
137
138
        // Order classify billed proposal
139
        if ($action == 'ORDER_CLASSIFY_BILLED') {
140
            dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id);
141
            if (isModEnabled("propal") && !empty($conf->workflow->enabled) && getDolGlobalString('WORKFLOW_ORDER_CLASSIFY_BILLED_PROPAL')) {
142
                $object->fetchObjectLinked('', 'propal', $object->id, $object->element);
143
                if (!empty($object->linkedObjects)) {
144
                    $totalonlinkedelements = 0;
145
                    foreach ($object->linkedObjects['propal'] as $element) {
146
                        if ($element->statut == Propal::STATUS_SIGNED || $element->statut == Propal::STATUS_BILLED) {
147
                            $totalonlinkedelements += $element->total_ht;
148
                        }
149
                    }
150
                    dol_syslog("Amount of linked proposals = " . $totalonlinkedelements . ", of order = " . $object->total_ht . ", egality is " . json_encode($totalonlinkedelements == $object->total_ht));
151
                    if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
152
                        foreach ($object->linkedObjects['propal'] as $element) {
153
                            $ret = $element->classifyBilled($user);
154
                        }
155
                    }
156
                }
157
                return $ret;
158
            }
159
        }
160
161
        // classify billed order & billed propososal
162
        if ($action == 'BILL_VALIDATE') {
163
            dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id);
164
165
            // First classify billed the order to allow the proposal classify process
166
            if (isModEnabled('order') && !empty($conf->workflow->enabled) && getDolGlobalString('WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER')) {
167
                $object->fetchObjectLinked('', 'commande', $object->id, $object->element);
168
                if (!empty($object->linkedObjects)) {
169
                    $totalonlinkedelements = 0;
170
                    foreach ($object->linkedObjects['commande'] as $element) {
171
                        if ($element->statut == Commande::STATUS_VALIDATED || $element->statut == Commande::STATUS_SHIPMENTONPROCESS || $element->statut == Commande::STATUS_CLOSED) {
172
                            $totalonlinkedelements += $element->total_ht;
173
                        }
174
                    }
175
                    dol_syslog("Amount of linked orders = " . $totalonlinkedelements . ", of invoice = " . $object->total_ht . ", egality is " . json_encode($totalonlinkedelements == $object->total_ht));
176
                    if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
177
                        foreach ($object->linkedObjects['commande'] as $element) {
178
                            $ret = $element->classifyBilled($user);
179
                        }
180
                    }
181
                }
182
            }
183
184
            // Second classify billed the proposal.
185
            if (isModEnabled("propal") && !empty($conf->workflow->enabled) && getDolGlobalString('WORKFLOW_INVOICE_CLASSIFY_BILLED_PROPAL')) {
186
                $object->fetchObjectLinked('', 'propal', $object->id, $object->element);
187
                if (!empty($object->linkedObjects)) {
188
                    $totalonlinkedelements = 0;
189
                    foreach ($object->linkedObjects['propal'] as $element) {
190
                        if ($element->statut == Propal::STATUS_SIGNED || $element->statut == Propal::STATUS_BILLED) {
191
                            $totalonlinkedelements += $element->total_ht;
192
                        }
193
                    }
194
                    dol_syslog("Amount of linked proposals = " . $totalonlinkedelements . ", of invoice = " . $object->total_ht . ", egality is " . json_encode($totalonlinkedelements == $object->total_ht));
195
                    if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
196
                        foreach ($object->linkedObjects['propal'] as $element) {
197
                            $ret = $element->classifyBilled($user);
198
                        }
199
                    }
200
                }
201
            }
202
203
            // Set shipment to "Closed" if WORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE is set (deprecated, has been replaced with WORKFLOW_SHIPPING_CLASSIFY_BILLED_INVOICE instead))
204
            if (isModEnabled("shipping") && !empty($conf->workflow->enabled) && getDolGlobalString('WORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE')) {
205
                $object->fetchObjectLinked('', 'shipping', $object->id, $object->element);
206
                if (!empty($object->linkedObjects)) {
207
                    $totalonlinkedelements = 0;
208
                    foreach ($object->linkedObjects['shipping'] as $element) {
209
                        if ($element->statut == Expedition::STATUS_VALIDATED) {
210
                            $totalonlinkedelements += $element->total_ht;
211
                        }
212
                    }
213
                    dol_syslog("Amount of linked shipment = " . $totalonlinkedelements . ", of invoice = " . $object->total_ht . ", egality is " . json_encode($totalonlinkedelements == $object->total_ht), LOG_DEBUG);
214
                    if ($totalonlinkedelements == $object->total_ht) {
215
                        foreach ($object->linkedObjects['shipping'] as $element) {
216
                            $ret = $element->setClosed();
217
                            if ($ret < 0) {
218
                                return (int)$ret;
219
                            }
220
                        }
221
                    }
222
                }
223
            }
224
225
            if (isModEnabled("shipping") && !empty($conf->workflow->enabled) && getDolGlobalString('WORKFLOW_SHIPPING_CLASSIFY_BILLED_INVOICE')) {
226
                $object->fetchObjectLinked('', 'shipping', $object->id, $object->element);
227
                if (!empty($object->linkedObjects)) {
228
                    $totalonlinkedelements = 0;
229
                    foreach ($object->linkedObjects['shipping'] as $element) {
230
                        if ($element->statut == Expedition::STATUS_VALIDATED || $element->statut == Expedition::STATUS_CLOSED) {
231
                            $totalonlinkedelements += $element->total_ht;
232
                        }
233
                    }
234
                    dol_syslog("Amount of linked shipment = " . $totalonlinkedelements . ", of invoice = " . $object->total_ht . ", egality is " . json_encode($totalonlinkedelements == $object->total_ht), LOG_DEBUG);
235
                    if ($totalonlinkedelements == $object->total_ht) {
236
                        foreach ($object->linkedObjects['shipping'] as $element) {
237
                            $ret = $element->setBilled();
238
                            if ($ret < 0) {
239
                                return (int)$ret;
240
                            }
241
                        }
242
                    }
243
                }
244
            }
245
246
            // First classify billed the order to allow the proposal classify process
247
            if (isModEnabled('order') && isModEnabled('workflow') && getDolGlobalString('WORKFLOW_SUM_INVOICES_AMOUNT_CLASSIFY_BILLED_ORDER')) {
248
                $object->fetchObjectLinked('', 'commande', $object->id, $object->element);
249
                if (!empty($object->linkedObjects['commande']) && count($object->linkedObjects['commande']) == 1) { // If the invoice has only 1 source order
250
                    $orderLinked = reset($object->linkedObjects['commande']);
251
                    $orderLinked->fetchObjectLinked($orderLinked->id, '', $orderLinked->element);
252
                    if (count($orderLinked->linkedObjects['facture']) >= 1) {
253
                        $totalHTInvoices = 0;
254
                        $areAllInvoicesValidated = true;
255
                        foreach ($orderLinked->linkedObjects['facture'] as $key => $invoice) {
256
                            if ($invoice->statut == Facture::STATUS_VALIDATED || $object->id == $invoice->id) {
257
                                $totalHTInvoices += (float)$invoice->total_ht;
258
                            } else {
259
                                $areAllInvoicesValidated = false;
260
                                break;
261
                            }
262
                        }
263
                        if ($areAllInvoicesValidated) {
264
                            $isSameTotal = (price2num($totalHTInvoices, 'MT') == price2num($orderLinked->total_ht, 'MT'));
265
                            dol_syslog("Amount of linked invoices = " . $totalHTInvoices . ", of order = " . $orderLinked->total_ht . ", isSameTotal = " . (string)$isSameTotal, LOG_DEBUG);
266
                            if ($isSameTotal) {
267
                                $ret = $orderLinked->classifyBilled($user);
268
                                if ($ret < 0) {
269
                                    return $ret;
270
                                }
271
                            }
272
                        }
273
                    }
274
                }
275
            }
276
            return $ret;
277
        }
278
279
        // classify billed order & billed proposal
280
        if ($action == 'BILL_SUPPLIER_VALIDATE') {
281
            dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id);
282
283
            // Firstly, we set to purchase order to "Billed" if WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER is set.
284
            // After we will set proposals
285
            if ((isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && getDolGlobalString('WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER')) {
286
                $object->fetchObjectLinked('', 'order_supplier', $object->id, $object->element);
287
                if (!empty($object->linkedObjects)) {
288
                    $totalonlinkedelements = 0;
289
                    foreach ($object->linkedObjects['order_supplier'] as $element) {
290
                        if ($element->statut == CommandeFournisseur::STATUS_ACCEPTED || $element->statut == CommandeFournisseur::STATUS_ORDERSENT || $element->statut == CommandeFournisseur::STATUS_RECEIVED_PARTIALLY || $element->statut == CommandeFournisseur::STATUS_RECEIVED_COMPLETELY) {
291
                            $totalonlinkedelements += $element->total_ht;
292
                        }
293
                    }
294
                    dol_syslog("Amount of linked orders = " . $totalonlinkedelements . ", of invoice = " . $object->total_ht . ", egality is " . json_encode($totalonlinkedelements == $object->total_ht));
295
                    if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
296
                        foreach ($object->linkedObjects['order_supplier'] as $element) {
297
                            $ret = $element->classifyBilled($user);
298
                            if ($ret < 0) {
299
                                return $ret;
300
                            }
301
                        }
302
                    }
303
                }
304
            }
305
306
            // Secondly, we set to linked Proposal to "Billed" if WORKFLOW_INVOICE_CLASSIFY_BILLED_SUPPLIER_PROPOSAL is set.
307
            if (isModEnabled('supplier_proposal') && getDolGlobalString('WORKFLOW_INVOICE_CLASSIFY_BILLED_SUPPLIER_PROPOSAL')) {
308
                $object->fetchObjectLinked('', 'supplier_proposal', $object->id, $object->element);
309
                if (!empty($object->linkedObjects)) {
310
                    $totalonlinkedelements = 0;
311
                    foreach ($object->linkedObjects['supplier_proposal'] as $element) {
312
                        if ($element->statut == SupplierProposal::STATUS_SIGNED || $element->statut == SupplierProposal::STATUS_CLOSE) {
313
                            $totalonlinkedelements += $element->total_ht;
314
                        }
315
                    }
316
                    dol_syslog("Amount of linked supplier proposals = " . $totalonlinkedelements . ", of supplier invoice = " . $object->total_ht . ", egality is " . json_encode($totalonlinkedelements == $object->total_ht));
317
                    if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
318
                        foreach ($object->linkedObjects['supplier_proposal'] as $element) {
319
                            $ret = $element->classifyBilled($user);
320
                            if ($ret < 0) {
321
                                return $ret;
322
                            }
323
                        }
324
                    }
325
                }
326
            }
327
328
            // Set reception to "Closed" if WORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE is set (deprecated, WORKFLOW_RECEPTION_CLASSIFY_BILLED_INVOICE instead))
329
            /*
330
            if (isModEnabled("reception") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE)) {
331
                $object->fetchObjectLinked('', 'reception', $object->id, $object->element);
332
                if (!empty($object->linkedObjects)) {
333
                    $totalonlinkedelements = 0;
334
                    foreach ($object->linkedObjects['reception'] as $element) {
335
                        if ($element->statut == Reception::STATUS_VALIDATED || $element->statut == Reception::STATUS_CLOSED) {
336
                            $totalonlinkedelements += $element->total_ht;
337
                        }
338
                    }
339
                    dol_syslog("Amount of linked reception = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht), LOG_DEBUG);
340
                    if ($totalonlinkedelements == $object->total_ht) {
341
                        foreach ($object->linkedObjects['reception'] as $element) {
342
                            $ret = $element->setClosed();
343
                            if ($ret < 0) {
344
                                return $ret;
345
                            }
346
                        }
347
                    }
348
                }
349
            }
350
            */
351
352
            // Then set reception to "Billed" if WORKFLOW_RECEPTION_CLASSIFY_BILLED_INVOICE is set
353
            if (isModEnabled("reception") && !empty($conf->workflow->enabled) && getDolGlobalString('WORKFLOW_RECEPTION_CLASSIFY_BILLED_INVOICE')) {
354
                $object->fetchObjectLinked('', 'reception', $object->id, $object->element);
355
                if (!empty($object->linkedObjects)) {
356
                    $totalonlinkedelements = 0;
357
                    foreach ($object->linkedObjects['reception'] as $element) {
358
                        if ($element->statut == Reception::STATUS_VALIDATED || $element->statut == Reception::STATUS_CLOSED) {
359
                            $totalonlinkedelements += $element->total_ht;
360
                        }
361
                    }
362
                    dol_syslog("Amount of linked reception = " . $totalonlinkedelements . ", of invoice = " . $object->total_ht . ", egality is " . json_encode($totalonlinkedelements == $object->total_ht), LOG_DEBUG);
363
                    if ($totalonlinkedelements == $object->total_ht) {
364
                        foreach ($object->linkedObjects['reception'] as $element) {
365
                            $ret = $element->setBilled();
366
                            if ($ret < 0) {
367
                                return $ret;
368
                            }
369
                        }
370
                    }
371
                }
372
            }
373
374
            return $ret;
375
        }
376
377
        // Invoice classify billed order
378
        if ($action == 'BILL_PAYED') {
379
            dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id);
380
381
            if (isModEnabled('order') && getDolGlobalString('WORKFLOW_INVOICE_CLASSIFY_BILLED_ORDER')) {
382
                $object->fetchObjectLinked('', 'commande', $object->id, $object->element);
383
                if (!empty($object->linkedObjects)) {
384
                    $totalonlinkedelements = 0;
385
                    foreach ($object->linkedObjects['commande'] as $element) {
386
                        if ($element->statut == Commande::STATUS_VALIDATED || $element->statut == Commande::STATUS_SHIPMENTONPROCESS || $element->statut == Commande::STATUS_CLOSED) {
387
                            $totalonlinkedelements += $element->total_ht;
388
                        }
389
                    }
390
                    dol_syslog("Amount of linked orders = " . $totalonlinkedelements . ", of invoice = " . $object->total_ht . ", egality is " . json_encode($totalonlinkedelements == $object->total_ht));
391
                    if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
392
                        foreach ($object->linkedObjects['commande'] as $element) {
393
                            $ret = $element->classifyBilled($user);
394
                        }
395
                    }
396
                }
397
                return $ret;
398
            }
399
        }
400
401
        // If we validate or close a shipment
402
        if (($action == 'SHIPPING_VALIDATE') || ($action == 'SHIPPING_CLOSED')) {
403
            dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id);
404
405
            if (
406
                isModEnabled('order') && isModEnabled("shipping") && !empty($conf->workflow->enabled) &&
407
                (
408
                    (getDolGlobalString('WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING') && ($action == 'SHIPPING_VALIDATE')) ||
409
                    (getDolGlobalString('WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING_CLOSED') && ($action == 'SHIPPING_CLOSED'))
410
                )
411
            ) {
412
                $qtyshipped = array();
413
                $qtyordred = array();
414
415
                // The original sale order is id in $object->origin_id
416
                // Find all shipments on sale order origin
417
418
                if (in_array($object->origin, array('order', 'commande')) && $object->origin_id > 0) {
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

418
                if (in_array(/** @scrutinizer ignore-deprecated */ $object->origin, array('order', 'commande')) && $object->origin_id > 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...
419
                    $order = new Commande($this->db);
420
                    $ret = $order->fetch($object->origin_id);
421
                    if ($ret < 0) {
422
                        $this->setErrorsFromObject($order);
423
                        return $ret;
424
                    }
425
                    $ret = $order->fetchObjectLinked($order->id, 'commande', null, 'shipping');
426
                    if ($ret < 0) {
427
                        $this->setErrorsFromObject($order);
428
                        return $ret;
429
                    }
430
                    //Build array of quantity shipped by product for an order
431
                    if (is_array($order->linkedObjects) && count($order->linkedObjects) > 0) {
432
                        foreach ($order->linkedObjects as $type => $shipping_array) {
433
                            if ($type != 'shipping' || !is_array($shipping_array) || count($shipping_array) == 0) {
434
                                continue;
435
                            }
436
                            /** @var Expedition[] $shipping_array */
437
                            foreach ($shipping_array as $shipping) {
438
                                if ($shipping->status <= 0 || !is_array($shipping->lines) || count($shipping->lines) == 0) {
439
                                    continue;
440
                                }
441
442
                                foreach ($shipping->lines as $shippingline) {
443
                                    if (isset($qtyshipped[$shippingline->fk_product])) {
444
                                        $qtyshipped[$shippingline->fk_product] += $shippingline->qty;
445
                                    } else {
446
                                        $qtyshipped[$shippingline->fk_product] = $shippingline->qty;
447
                                    }
448
                                }
449
                            }
450
                        }
451
                    }
452
453
                    //Build array of quantity ordered to be shipped
454
                    if (is_array($order->lines) && count($order->lines) > 0) {
455
                        foreach ($order->lines as $orderline) {
456
                            // Exclude lines not qualified for shipment, similar code is found into calcAndSetStatusDispatch() for vendors
457
                            if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES') && $orderline->product_type > 0) {
458
                                continue;
459
                            }
460
                            if (isset($qtyordred[$shippingline->fk_product])) {
461
                                $qtyordred[$orderline->fk_product] += $orderline->qty;
462
                            } else {
463
                                $qtyordred[$orderline->fk_product] = $orderline->qty;
464
                            }
465
                        }
466
                    }
467
                    //dol_syslog(var_export($qtyordred,true),LOG_DEBUG);
468
                    //dol_syslog(var_export($qtyshipped,true),LOG_DEBUG);
469
                    //Compare array
470
                    $diff_array = array_diff_assoc($qtyordred, $qtyshipped);
471
                    if (count($diff_array) == 0) {
472
                        //No diff => mean everything is shipped
473
                        $ret = $order->setStatut(Commande::STATUS_CLOSED, $object->origin_id, $object->origin, 'ORDER_CLOSE');
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

473
                        $ret = $order->setStatut(Commande::STATUS_CLOSED, $object->origin_id, /** @scrutinizer ignore-deprecated */ $object->origin, 'ORDER_CLOSE');

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...
474
                        if ($ret < 0) {
475
                            $this->setErrorsFromObject($order);
476
                            return $ret;
477
                        }
478
                    }
479
                }
480
            }
481
        }
482
483
        // If we validate or close a shipment
484
        if (($action == 'RECEPTION_VALIDATE') || ($action == 'RECEPTION_CLOSED')) {
485
            dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id);
486
487
            if (
488
                (isModEnabled("fournisseur") || isModEnabled("supplier_order")) && isModEnabled("reception") && isModEnabled('workflow') &&
489
                (
490
                    (getDolGlobalString('WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION') && ($action == 'RECEPTION_VALIDATE')) ||
491
                    (getDolGlobalString('WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED') && ($action == 'RECEPTION_CLOSED'))
492
                )
493
            ) {
494
                $qtyshipped = array();
495
                $qtyordred = array();
496
497
                // The original purchase order is id in $object->origin_id
498
                // Find all reception on purchase order origin
499
500
                if (in_array($object->origin, array('order_supplier', 'supplier_order', 'commandeFournisseur')) && $object->origin_id > 0) {
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

500
                if (in_array(/** @scrutinizer ignore-deprecated */ $object->origin, array('order_supplier', 'supplier_order', 'commandeFournisseur')) && $object->origin_id > 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...
501
                    $order = new CommandeFournisseur($this->db);
502
                    $ret = $order->fetch($object->origin_id);
503
                    if ($ret < 0) {
504
                        $this->setErrorsFromObject($order);
505
                        return $ret;
506
                    }
507
                    $ret = $order->fetchObjectLinked($order->id, $order->element, null, 'reception');
508
                    if ($ret < 0) {
509
                        $this->setErrorsFromObject($order);
510
                        return $ret;
511
                    }
512
513
                    // Build array of quantity received by product for a purchase order
514
                    if (is_array($order->linkedObjects) && count($order->linkedObjects) > 0) {
515
                        foreach ($order->linkedObjects as $type => $shipping_array) {
516
                            if ($type != 'reception' || !is_array($shipping_array) || count($shipping_array) == 0) {
517
                                continue;
518
                            }
519
520
                            foreach ($shipping_array as $shipping) {
521
                                if (!is_array($shipping->lines) || count($shipping->lines) == 0) {
522
                                    continue;
523
                                }
524
525
                                foreach ($shipping->lines as $shippingline) {
526
                                    $qtyshipped[$shippingline->fk_product] += $shippingline->qty;
527
                                }
528
                            }
529
                        }
530
                    }
531
532
                    // Build array of quantity ordered to be received
533
                    if (is_array($order->lines) && count($order->lines) > 0) {
534
                        foreach ($order->lines as $orderline) {
535
                            // Exclude lines not qualified for shipment, similar code is found into calcAndSetStatusDispatch() for vendors
536
                            if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES') && $orderline->product_type > 0) {
537
                                continue;
538
                            }
539
                            $qtyordred[$orderline->fk_product] += $orderline->qty;
540
                        }
541
                    }
542
                    //dol_syslog(var_export($qtyordred,true),LOG_DEBUG);
543
                    //dol_syslog(var_export($qtyshipped,true),LOG_DEBUG);
544
                    //Compare array
545
                    $diff_array = array_diff_assoc($qtyordred, $qtyshipped);
546
                    if (count($diff_array) == 0) {
547
                        //No diff => mean everything is received
548
                        $ret = $order->setStatut(CommandeFournisseur::STATUS_RECEIVED_COMPLETELY, null, null, 'SUPPLIER_ORDER_CLOSE');
549
                        if ($ret < 0) {
550
                            $this->setErrorsFromObject($order);
551
                            return $ret;
552
                        }
553
                    }
554
                }
555
            }
556
        }
557
558
        if ($action == 'TICKET_CREATE') {
559
            dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id);
560
            // Auto link ticket to contract
561
            if (isModEnabled('contract') && isModEnabled('ticket') && isModEnabled('workflow') && getDolGlobalString('WORKFLOW_TICKET_LINK_CONTRACT') && getDolGlobalString('TICKET_PRODUCT_CATEGORY') && !empty($object->fk_soc)) {
562
                $societe = new Societe($this->db);
563
                $company_ids = (!getDolGlobalString('WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS')) ? [$object->fk_soc] : $societe->getParentsForCompany($object->fk_soc, [$object->fk_soc]);
564
565
                $contrat = new Contrat($this->db);
566
                $number_contracts_found = 0;
567
                foreach ($company_ids as $company_id) {
568
                    $contrat->socid = $company_id;
569
                    $list = $contrat->getListOfContracts('all', array(Contrat::STATUS_DRAFT, Contrat::STATUS_VALIDATED), array(getDolGlobalString('TICKET_PRODUCT_CATEGORY')), array(ContratLigne::STATUS_INITIAL, ContratLigne::STATUS_OPEN));
570
                    if (!is_array($list) || empty($list)) {
571
                        continue;
572
                    }
573
                    $number_contracts_found = count($list);
574
                    if ($number_contracts_found == 0) {
575
                        continue;
576
                    }
577
578
                    foreach ($list as $linked_contract) {
579
                        $object->setContract($linked_contract->id);
0 ignored issues
show
Bug introduced by
The method setContract() does not exist on Dolibarr\Core\Base\CommonObject. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

579
                        $object->/** @scrutinizer ignore-call */ 
580
                                 setContract($linked_contract->id);
Loading history...
580
                        // don't set '$contractid' so it is not used when creating an intervention.
581
                    }
582
583
                    if ($number_contracts_found > 1 && !defined('NOLOGIN')) {
584
                        setEventMessages($langs->trans('TicketManyContractsLinked'), null, 'warnings');
585
                    }
586
                    break;
587
                }
588
                if ($number_contracts_found == 0 && !defined('NOLOGIN')) {
589
                    setEventMessages($langs->trans('TicketNoContractFoundToLink'), null, 'mesgs');
590
                }
591
            }
592
            // Automatically create intervention
593
            if (isModEnabled('intervention') && isModEnabled('ticket') && !empty($conf->workflow->enabled) && getDolGlobalString('WORKFLOW_TICKET_CREATE_INTERVENTION')) {
594
                $fichinter = new Fichinter($this->db);
595
                $fichinter->socid = (int)$object->fk_soc;
596
                $fichinter->fk_project = (int)$object->fk_project;
597
                $fichinter->fk_contrat = (int)$object->fk_contract;
0 ignored issues
show
Bug Best Practice introduced by
The property fk_contract does not exist on Dolibarr\Core\Base\CommonObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
598
                $fichinter->author = $user->id;
599
                $fichinter->model_pdf = (getDolGlobalString('FICHEINTER_ADDON_PDF')) ? $conf->global->FICHEINTER_ADDON_PDF : 'soleil';
600
                $fichinter->origin = $object->element;
601
                $fichinter->origin_id = $object->id;
602
603
                // Extrafields
604
                $extrafields = new ExtraFields($this->db);
605
                $extrafields->fetch_name_optionals_label($fichinter->table_element);
606
                $array_options = $extrafields->getOptionalsFromPost($fichinter->table_element);
607
                $fichinter->array_options = $array_options;
608
609
                $id = $fichinter->create($user);
610
                if ($id <= 0) {
611
                    setEventMessages($fichinter->error, null, 'errors');
612
                }
613
            }
614
        }
615
        return 0;
616
    }
617
618
    /**
619
     * @param Object $conf Dolibarr settings object
620
     * @param float $totalonlinkedelements Sum of total amounts (excl VAT) of
621
     *                                      invoices linked to $object
622
     * @param float $object_total_ht The total amount (excl VAT) of the object
623
     *                                      (an order, a proposal, a bill, etc.)
624
     * @return bool  True if the amounts are equal (rounded on total amount)
625
     *               True if the module is configured to skip the amount equality check
626
     *               False otherwise.
627
     */
628
    private function shouldClassify($conf, $totalonlinkedelements, $object_total_ht)
629
    {
630
        // if the configuration allows unmatching amounts, allow classification anyway
631
        if (getDolGlobalString('WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS')) {
632
            return true;
633
        }
634
        // if the amount are same, allow classification, else deny
635
        return (price2num($totalonlinkedelements, 'MT') == price2num($object_total_ht, 'MT'));
636
    }
637
}
638