Passed
Push — EXTRACT_CLASSES ( 0382f2...c25e41 )
by Rafael
52:18
created

Orders::index()   F

Complexity

Conditions 21
Paths 2017

Size

Total Lines 89
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 21
eloc 56
nc 2017
nop 8
dl 0
loc 89
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* Copyright (C) 2015       Jean-François Ferry         <[email protected]>
4
 * Copyright (C) 2016	    Laurent Destailleur		    <[email protected]>
5
 * Copyright (C) 2024       Rafael San José             <[email protected]>
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
namespace Dolibarr\Code\Commande\Api;
22
23
use Luracast\Restler\RestException;
24
25
require_once constant('DOL_DOCUMENT_ROOT') . '/commande/class/commande.class.php';
26
27
/**
28
 * API class for orders
29
 *
30
 * @access protected
31
 * @class  DolibarrApiAccess {@requires user,external}
32
 */
33
class Orders extends DolibarrApi
34
{
35
    /**
36
     * @var array $FIELDS Mandatory fields, checked when create and update object
37
     */
38
    public static $FIELDS = array(
39
        'socid',
40
        'date'
41
    );
42
43
    /**
44
     * @var Commande $commande {@type Commande}
45
     */
46
    public $commande;
47
48
    /**
49
     * Constructor
50
     */
51
    public function __construct()
52
    {
53
        global $db, $conf;
54
        $this->db = $db;
55
        $this->commande = new Commande($this->db);
56
    }
57
58
    /**
59
     * Get properties of an order object by ref
60
     *
61
     * Return an array with order information
62
     *
63
     * @param string $ref Ref of object
64
     * @param int $contact_list 0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id
65
     * @return  array|mixed data without useless information
66
     *
67
     * @url GET    ref/{ref}
68
     *
69
     * @throws  RestException
70
     */
71
    public function getByRef($ref, $contact_list = 1)
72
    {
73
        return $this->_fetch('', $ref, '', $contact_list);
74
    }
75
76
    /**
77
     * Get properties of an order object
78
     *
79
     * Return an array with order information
80
     *
81
     * @param int $id ID of order
82
     * @param string $ref Ref of object
83
     * @param string $ref_ext External reference of object
84
     * @param int $contact_list 0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id
85
     * @return      Object                      Object with cleaned properties
86
     *
87
     * @throws  RestException
88
     */
89
    private function _fetch($id, $ref = '', $ref_ext = '', $contact_list = 1)
90
    {
91
        if (!DolibarrApiAccess::$user->hasRight('commande', 'lire')) {
92
            throw new RestException(403);
93
        }
94
95
        $result = $this->commande->fetch($id, $ref, $ref_ext);
96
        if (!$result) {
97
            throw new RestException(404, 'Order not found');
98
        }
99
100
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
101
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
102
        }
103
104
        // Add external contacts ids
105
        $tmparray = $this->commande->liste_contact(-1, 'external', $contact_list);
106
        if (is_array($tmparray)) {
107
            $this->commande->contacts_ids = $tmparray;
108
        }
109
        $this->commande->fetchObjectLinked();
110
111
        // Add online_payment_url, cf #20477
112
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/payments.lib.php';
113
        $this->commande->online_payment_url = getOnlinePaymentUrl(0, 'order', $this->commande->ref);
114
115
        return $this->_cleanObjectDatas($this->commande);
116
    }
117
118
    /**
119
     * Clean sensible object datas
120
     *
121
     * @param Object $object Object to clean
122
     * @return  Object                  Object with cleaned properties
123
     */
124
    protected function _cleanObjectDatas($object)
125
    {
126
        // phpcs:enable
127
        $object = parent::_cleanObjectDatas($object);
128
129
        unset($object->note);
130
        unset($object->address);
131
        unset($object->barcode_type);
132
        unset($object->barcode_type_code);
133
        unset($object->barcode_type_label);
134
        unset($object->barcode_type_coder);
135
136
        return $object;
137
    }
138
139
    /**
140
     * Get properties of an order object by ref_ext
141
     *
142
     * Return an array with order information
143
     *
144
     * @param string $ref_ext External reference of object
145
     * @param int $contact_list 0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id
146
     * @return  array|mixed data without useless information
147
     *
148
     * @url GET    ref_ext/{ref_ext}
149
     *
150
     * @throws  RestException
151
     */
152
    public function getByRefExt($ref_ext, $contact_list = 1)
153
    {
154
        return $this->_fetch('', '', $ref_ext, $contact_list);
155
    }
156
157
    /**
158
     * List orders
159
     *
160
     * Get a list of orders
161
     *
162
     * @param string $sortfield Sort field
163
     * @param string $sortorder Sort order
164
     * @param int $limit Limit for list
165
     * @param int $page Page number
166
     * @param string $thirdparty_ids Thirdparty ids to filter orders of (example '1' or '1,2,3') {@pattern /^[0-9,]*$/i}
167
     * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
168
     * @param string $sqlfilterlines Other criteria to filter answers separated by a comma. Syntax example "(tl.fk_product:=:'17') and (tl.price:<:'250')"
169
     * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names
170
     * @return  array                               Array of order objects
171
     *
172
     * @throws RestException 404 Not found
173
     * @throws RestException 503 Error
174
     */
175
    public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '', $sqlfilterlines = '', $properties = '')
176
    {
177
        if (!DolibarrApiAccess::$user->hasRight('commande', 'lire')) {
178
            throw new RestException(403);
179
        }
180
181
        $obj_ret = array();
182
183
        // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
184
        $socids = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $thirdparty_ids;
185
186
        // If the internal user must only see his customers, force searching by him
187
        $search_sale = 0;
188
        if (!DolibarrApiAccess::$user->hasRight('societe', 'client', 'voir') && !$socids) {
189
            $search_sale = DolibarrApiAccess::$user->id;
190
        }
191
192
        $sql = "SELECT t.rowid";
193
        $sql .= " FROM " . MAIN_DB_PREFIX . "commande AS t";
194
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "commande_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields
195
        $sql .= ' WHERE t.entity IN (' . getEntity('commande') . ')';
196
        if ($socids) {
197
            $sql .= " AND t.fk_soc IN (" . $this->db->sanitize($socids) . ")";
198
        }
199
        // Search on sale representative
200
        if ($search_sale && $search_sale != '-1') {
201
            if ($search_sale == -2) {
202
                $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc)";
203
            } elseif ($search_sale > 0) {
204
                $sql .= " AND EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc AND sc.fk_user = " . ((int)$search_sale) . ")";
205
            }
206
        }
207
        // Add sql filters
208
        if ($sqlfilters) {
209
            $errormessage = '';
210
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
211
            if ($errormessage) {
212
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
213
            }
214
        }
215
        // Add sql filters for lines
216
        if ($sqlfilterlines) {
217
            $errormessage = '';
218
            $sql .= " AND EXISTS (SELECT tl.rowid FROM " . MAIN_DB_PREFIX . "commandedet AS tl WHERE tl.fk_commande = t.rowid";
219
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilterlines, $errormessage);
220
            $sql .= ")";
221
            if ($errormessage) {
222
                throw new RestException(400, 'Error when validating parameter sqlfilterlines -> ' . $errormessage);
223
            }
224
        }
225
        $sql .= $this->db->order($sortfield, $sortorder);
226
        if ($limit) {
227
            if ($page < 0) {
228
                $page = 0;
229
            }
230
            $offset = $limit * $page;
231
232
            $sql .= $this->db->plimit($limit + 1, $offset);
233
        }
234
235
        dol_syslog("API Rest request");
236
        $result = $this->db->query($sql);
237
238
        if ($result) {
239
            $num = $this->db->num_rows($result);
240
            $min = min($num, ($limit <= 0 ? $num : $limit));
241
            $i = 0;
242
            while ($i < $min) {
243
                $obj = $this->db->fetch_object($result);
244
                $commande_static = new Commande($this->db);
245
                if ($commande_static->fetch($obj->rowid)) {
246
                    // Add external contacts ids
247
                    $tmparray = $commande_static->liste_contact(-1, 'external', 1);
248
                    if (is_array($tmparray)) {
249
                        $commande_static->contacts_ids = $tmparray;
250
                    }
251
                    // Add online_payment_url, cf #20477
252
                    require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/payments.lib.php';
253
                    $commande_static->online_payment_url = getOnlinePaymentUrl(0, 'order', $commande_static->ref);
254
255
                    $obj_ret[] = $this->_filterObjectProperties($this->_cleanObjectDatas($commande_static), $properties);
256
                }
257
                $i++;
258
            }
259
        } else {
260
            throw new RestException(503, 'Error when retrieve commande list : ' . $this->db->lasterror());
261
        }
262
263
        return $obj_ret;
264
    }
265
266
    /**
267
     * Create a sale order
268
     *
269
     * Example: { "socid": 2, "date": 1595196000, "type": 0, "lines": [{ "fk_product": 2, "qty": 1 }] }
270
     *
271
     * @param array $request_data Request data
272
     * @return  int     ID of order
273
     */
274
    public function post($request_data = null)
275
    {
276
        if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) {
277
            throw new RestException(403, "Insuffisant rights");
278
        }
279
        // Check mandatory fields
280
        $result = $this->_validate($request_data);
281
282
        foreach ($request_data as $field => $value) {
283
            if ($field === 'caller') {
284
                // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller
285
                $this->commande->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
286
                continue;
287
            }
288
289
            $this->commande->$field = $this->_checkValForAPI($field, $value, $this->commande);
290
        }
291
        /*if (isset($request_data["lines"])) {
292
          $lines = array();
293
          foreach ($request_data["lines"] as $line) {
294
            array_push($lines, (object) $line);
295
          }
296
          $this->commande->lines = $lines;
297
        }*/
298
299
        if ($this->commande->create(DolibarrApiAccess::$user) < 0) {
300
            throw new RestException(500, "Error creating order", array_merge(array($this->commande->error), $this->commande->errors));
301
        }
302
303
        return ((int)$this->commande->id);
304
    }
305
306
    /**
307
     * Validate fields before create or update object
308
     *
309
     * @param array $data Array with data to verify
310
     * @return  array
311
     * @throws  RestException
312
     */
313
    private function _validate($data)
314
    {
315
        $commande = array();
316
        foreach (Orders::$FIELDS as $field) {
317
            if (!isset($data[$field])) {
318
                throw new RestException(400, $field . " field missing");
319
            }
320
            $commande[$field] = $data[$field];
321
        }
322
        return $commande;
323
    }
324
325
    /**
326
     * Get lines of an order
327
     *
328
     * @param int $id Id of order
329
     *
330
     * @url GET {id}/lines
331
     *
332
     * @return array
333
     */
334
    public function getLines($id)
335
    {
336
        if (!DolibarrApiAccess::$user->hasRight('commande', 'lire')) {
337
            throw new RestException(403);
338
        }
339
340
        $result = $this->commande->fetch($id);
341
        if (!$result) {
342
            throw new RestException(404, 'Order not found');
343
        }
344
345
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
346
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
347
        }
348
        $this->commande->getLinesArray();
349
        $result = array();
350
        foreach ($this->commande->lines as $line) {
351
            array_push($result, $this->_cleanObjectDatas($line));
352
        }
353
        return $result;
354
    }
355
356
    /**
357
     * Add a line to given order
358
     *
359
     * @param int $id Id of order to update
360
     * @param array $request_data OrderLine data
361
     *
362
     * @url POST {id}/lines
363
     *
364
     * @return int
365
     */
366
    public function postLine($id, $request_data = null)
367
    {
368
        if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) {
369
            throw new RestException(403);
370
        }
371
372
        $result = $this->commande->fetch($id);
373
        if (!$result) {
374
            throw new RestException(404, 'Order not found');
375
        }
376
377
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
378
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
379
        }
380
381
        $request_data = (object)$request_data;
382
383
        $request_data->desc = sanitizeVal($request_data->desc, 'restricthtml');
384
        $request_data->label = sanitizeVal($request_data->label);
385
386
        $updateRes = $this->commande->addline(
387
            $request_data->desc,
388
            $request_data->subprice,
389
            $request_data->qty,
390
            $request_data->tva_tx,
391
            $request_data->localtax1_tx,
392
            $request_data->localtax2_tx,
393
            $request_data->fk_product,
394
            $request_data->remise_percent,
395
            $request_data->info_bits,
396
            $request_data->fk_remise_except,
397
            $request_data->price_base_type ? $request_data->price_base_type : 'HT',
398
            $request_data->subprice,
399
            $request_data->date_start,
400
            $request_data->date_end,
401
            $request_data->product_type,
402
            $request_data->rang,
403
            $request_data->special_code,
404
            $request_data->fk_parent_line,
405
            $request_data->fk_fournprice,
406
            $request_data->pa_ht,
407
            $request_data->label,
408
            $request_data->array_options,
409
            $request_data->fk_unit,
410
            $request_data->origin,
411
            $request_data->origin_id,
412
            $request_data->multicurrency_subprice,
413
            $request_data->ref_ext
414
        );
415
416
        if ($updateRes > 0) {
417
            return $updateRes;
418
        } else {
419
            throw new RestException(400, $this->commande->error);
420
        }
421
    }
422
423
    /**
424
     * Update a line to given order
425
     *
426
     * @param int $id Id of order to update
427
     * @param int $lineid Id of line to update
428
     * @param array $request_data OrderLine data
429
     * @return  Object|false          Object with cleaned properties
430
     *
431
     * @url PUT {id}/lines/{lineid}
432
     */
433
    public function putLine($id, $lineid, $request_data = null)
434
    {
435
        if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) {
436
            throw new RestException(403);
437
        }
438
439
        $result = $this->commande->fetch($id);
440
        if (!$result) {
441
            throw new RestException(404, 'Order not found');
442
        }
443
444
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
445
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
446
        }
447
448
        $request_data = (object)$request_data;
449
450
        $request_data->desc = sanitizeVal($request_data->desc, 'restricthtml');
451
        $request_data->label = sanitizeVal($request_data->label);
452
453
        $updateRes = $this->commande->updateline(
454
            $lineid,
455
            $request_data->desc,
456
            $request_data->subprice,
457
            $request_data->qty,
458
            $request_data->remise_percent,
459
            $request_data->tva_tx,
460
            $request_data->localtax1_tx,
461
            $request_data->localtax2_tx,
462
            $request_data->price_base_type ? $request_data->price_base_type : 'HT',
463
            $request_data->info_bits,
464
            $request_data->date_start,
465
            $request_data->date_end,
466
            $request_data->product_type,
467
            $request_data->fk_parent_line,
468
            0,
469
            $request_data->fk_fournprice,
470
            $request_data->pa_ht,
471
            $request_data->label,
472
            $request_data->special_code,
473
            $request_data->array_options,
474
            $request_data->fk_unit,
475
            $request_data->multicurrency_subprice,
476
            0,
477
            $request_data->ref_ext,
478
            $request_data->rang
479
        );
480
481
        if ($updateRes > 0) {
482
            $result = $this->get($id);
483
            unset($result->line);
484
            return $this->_cleanObjectDatas($result);
485
        }
486
        return false;
487
    }
488
489
    /**
490
     * Get properties of an order object by id
491
     *
492
     * Return an array with order information
493
     *
494
     * @param int $id ID of order
495
     * @param int $contact_list 0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id
496
     * @return  array|mixed data without useless information
497
     *
498
     * @throws  RestException
499
     */
500
    public function get($id, $contact_list = 1)
501
    {
502
        return $this->_fetch($id, '', '', $contact_list);
503
    }
504
505
    /**
506
     * Delete a line of a given order
507
     *
508
     * @param int $id Id of order to update
509
     * @param int $lineid Id of line to delete
510
     * @return  Object                  Object with cleaned properties
511
     *
512
     * @url DELETE {id}/lines/{lineid}
513
     *
514
     * @throws RestException 401
515
     * @throws RestException 404
516
     */
517
    public function deleteLine($id, $lineid)
518
    {
519
        if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) {
520
            throw new RestException(403);
521
        }
522
523
        $result = $this->commande->fetch($id);
524
        if (!$result) {
525
            throw new RestException(404, 'Order not found');
526
        }
527
528
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
529
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
530
        }
531
532
        $updateRes = $this->commande->deleteLine(DolibarrApiAccess::$user, $lineid, $id);
533
        if ($updateRes > 0) {
534
            return $this->get($id);
535
        } else {
536
            throw new RestException(405, $this->commande->error);
537
        }
538
    }
539
540
    /**
541
     * Get contacts of given order
542
     *
543
     * Return an array with contact information
544
     *
545
     * @param int $id ID of order
546
     * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER)
547
     * @return  Object              Object with cleaned properties
548
     *
549
     * @url GET {id}/contacts
550
     *
551
     * @throws  RestException
552
     */
553
    public function getContacts($id, $type = '')
554
    {
555
        if (!DolibarrApiAccess::$user->hasRight('commande', 'lire')) {
556
            throw new RestException(403);
557
        }
558
559
        $result = $this->commande->fetch($id);
560
        if (!$result) {
561
            throw new RestException(404, 'Order not found');
562
        }
563
564
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
565
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
566
        }
567
568
        $contacts = $this->commande->liste_contact(-1, 'external', 0, $type);
569
570
        return $this->_cleanObjectDatas($contacts);
571
    }
572
573
    /**
574
     * Add a contact type of given order
575
     *
576
     * @param int $id Id of order to update
577
     * @param int $contactid Id of contact to add
578
     * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER)
579
     * @return array
580
     *
581
     * @url POST {id}/contact/{contactid}/{type}
582
     *
583
     * @throws RestException 401
584
     * @throws RestException 404
585
     */
586
    public function postContact($id, $contactid, $type)
587
    {
588
        if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) {
589
            throw new RestException(403);
590
        }
591
592
        $result = $this->commande->fetch($id);
593
        if (!$result) {
594
            throw new RestException(404, 'Order not found');
595
        }
596
597
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
598
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
599
        }
600
601
        $result = $this->commande->add_contact($contactid, $type, 'external');
602
603
        if ($result < 0) {
604
            throw new RestException(500, 'Error when added the contact');
605
        }
606
607
        if ($result == 0) {
608
            throw new RestException(304, 'contact already added');
609
        }
610
611
        return array(
612
            'success' => array(
613
                'code' => 200,
614
                'message' => 'Contact linked to the order'
615
            )
616
        );
617
    }
618
619
    /**
620
     * Unlink a contact type of given order
621
     *
622
     * @param int $id Id of order to update
623
     * @param int $contactid Id of contact
624
     * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER).
625
     *
626
     * @url DELETE {id}/contact/{contactid}/{type}
627
     *
628
     * @return array
629
     *
630
     * @throws RestException 401
631
     * @throws RestException 404
632
     * @throws RestException 500 System error
633
     */
634
    public function deleteContact($id, $contactid, $type)
635
    {
636
        if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) {
637
            throw new RestException(403);
638
        }
639
640
        $result = $this->commande->fetch($id);
641
        if (!$result) {
642
            throw new RestException(404, 'Order not found');
643
        }
644
645
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
646
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
647
        }
648
649
        $contacts = $this->commande->liste_contact();
650
651
        foreach ($contacts as $contact) {
652
            if ($contact['id'] == $contactid && $contact['code'] == $type) {
653
                $result = $this->commande->delete_contact($contact['rowid']);
654
655
                if (!$result) {
656
                    throw new RestException(500, 'Error when deleted the contact');
657
                }
658
            }
659
        }
660
661
        return array(
662
            'success' => array(
663
                'code' => 200,
664
                'message' => 'Contact unlinked from order'
665
            )
666
        );
667
    }
668
669
    /**
670
     * Update order general fields (won't touch lines of order)
671
     *
672
     * @param int $id Id of order to update
673
     * @param array $request_data Datas
674
     * @return  Object                  Object with cleaned properties
675
     */
676
    public function put($id, $request_data = null)
677
    {
678
        if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) {
679
            throw new RestException(403);
680
        }
681
682
        $result = $this->commande->fetch($id);
683
        if (!$result) {
684
            throw new RestException(404, 'Order not found');
685
        }
686
687
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
688
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
689
        }
690
        foreach ($request_data as $field => $value) {
691
            if ($field == 'id') {
692
                continue;
693
            }
694
            if ($field === 'caller') {
695
                // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller
696
                $this->commande->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
697
                continue;
698
            }
699
            if ($field == 'array_options' && is_array($value)) {
700
                foreach ($value as $index => $val) {
701
                    $this->commande->array_options[$index] = $this->_checkValForAPI($field, $val, $this->commande);
702
                }
703
                continue;
704
            }
705
706
            $this->commande->$field = $this->_checkValForAPI($field, $value, $this->commande);
707
        }
708
709
        // Update availability
710
        if (!empty($this->commande->availability_id)) {
711
            if ($this->commande->availability($this->commande->availability_id) < 0) {
712
                throw new RestException(400, 'Error while updating availability');
713
            }
714
        }
715
716
        if ($this->commande->update(DolibarrApiAccess::$user) > 0) {
717
            return $this->get($id);
718
        } else {
719
            throw new RestException(500, $this->commande->error);
720
        }
721
    }
722
723
    /**
724
     * Delete order
725
     *
726
     * @param int $id Order ID
727
     * @return  array
728
     */
729
    public function delete($id)
730
    {
731
        if (!DolibarrApiAccess::$user->hasRight('commande', 'supprimer')) {
732
            throw new RestException(403);
733
        }
734
        $result = $this->commande->fetch($id);
735
        if (!$result) {
736
            throw new RestException(404, 'Order not found');
737
        }
738
739
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
740
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
741
        }
742
743
        if (!$this->commande->delete(DolibarrApiAccess::$user)) {
744
            throw new RestException(500, 'Error when deleting order : ' . $this->commande->error);
745
        }
746
747
        return array(
748
            'success' => array(
749
                'code' => 200,
750
                'message' => 'Order deleted'
751
            )
752
        );
753
    }
754
755
    /**
756
     * Validate an order
757
     *
758
     * If you get a bad value for param notrigger check, provide this in body
759
     * {
760
     *   "idwarehouse": 0,
761
     *   "notrigger": 0
762
     * }
763
     *
764
     * @param int $id Order ID
765
     * @param int $idwarehouse Warehouse ID
766
     * @param int $notrigger 1=Does not execute triggers, 0= execute triggers
767
     * @return  Object              Object with cleaned properties
768
     *
769
     * @url POST    {id}/validate
770
     *
771
     * @throws RestException 304
772
     * @throws RestException 401
773
     * @throws RestException 404
774
     * @throws RestException 500 System error
775
     *
776
     */
777
    public function validate($id, $idwarehouse = 0, $notrigger = 0)
778
    {
779
        if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) {
780
            throw new RestException(403);
781
        }
782
        $result = $this->commande->fetch($id);
783
        if (!$result) {
784
            throw new RestException(404, 'Order not found');
785
        }
786
787
        $result = $this->commande->fetch_thirdparty(); // do not check result, as failure is not fatal (used only for mail notification substitutes)
788
789
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
790
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
791
        }
792
793
        $result = $this->commande->valid(DolibarrApiAccess::$user, $idwarehouse, $notrigger);
794
        if ($result == 0) {
795
            throw new RestException(304, 'Error nothing done. May be object is already validated');
796
        }
797
        if ($result < 0) {
798
            throw new RestException(500, 'Error when validating Order: ' . $this->commande->error);
799
        }
800
        $result = $this->commande->fetch($id);
801
802
        $this->commande->fetchObjectLinked();
803
804
        //fix #20477 : add online_payment_url
805
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/payments.lib.php';
806
        $this->commande->online_payment_url = getOnlinePaymentUrl(0, 'order', $this->commande->ref);
807
808
        return $this->_cleanObjectDatas($this->commande);
809
    }
810
811
    /**
812
     *  Tag the order as validated (opened)
813
     *
814
     *  Function used when order is reopend after being closed.
815
     *
816
     * @param int $id Id of the order
817
     *
818
     * @url     POST {id}/reopen
819
     *
820
     * @return int
821
     *
822
     * @throws RestException 304
823
     * @throws RestException 400
824
     * @throws RestException 401
825
     * @throws RestException 404
826
     * @throws RestException 405
827
     */
828
    public function reopen($id)
829
    {
830
        if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) {
831
            throw new RestException(403);
832
        }
833
        if (empty($id)) {
834
            throw new RestException(400, 'Order ID is mandatory');
835
        }
836
        $result = $this->commande->fetch($id);
837
        if (!$result) {
838
            throw new RestException(404, 'Order not found');
839
        }
840
841
        $result = $this->commande->set_reopen(DolibarrApiAccess::$user);
842
        if ($result < 0) {
843
            throw new RestException(405, $this->commande->error);
844
        } elseif ($result == 0) {
845
            throw new RestException(304);
846
        }
847
848
        return $result;
849
    }
850
851
    /**
852
     * Classify the order as invoiced. Could be also called setbilled
853
     *
854
     * @param int $id Id of the order
855
     * @return  Object                  Object with cleaned properties
856
     *
857
     * @url     POST {id}/setinvoiced
858
     *
859
     * @throws RestException 400
860
     * @throws RestException 401
861
     * @throws RestException 404
862
     * @throws RestException 405
863
     */
864
    public function setinvoiced($id)
865
    {
866
        if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) {
867
            throw new RestException(403);
868
        }
869
        if (empty($id)) {
870
            throw new RestException(400, 'Order ID is mandatory');
871
        }
872
        $result = $this->commande->fetch($id);
873
        if (!$result) {
874
            throw new RestException(404, 'Order not found');
875
        }
876
877
        $result = $this->commande->classifyBilled(DolibarrApiAccess::$user);
878
        if ($result < 0) {
879
            throw new RestException(400, $this->commande->error);
880
        }
881
882
        $result = $this->commande->fetch($id);
883
        if (!$result) {
884
            throw new RestException(404, 'Order not found');
885
        }
886
887
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
888
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
889
        }
890
891
        $this->commande->fetchObjectLinked();
892
893
        return $this->_cleanObjectDatas($this->commande);
894
    }
895
896
    /**
897
     * Close an order (Classify it as "Delivered")
898
     *
899
     * @param int $id Order ID
900
     * @param int $notrigger Disabled triggers
901
     * @return  Object                  Object with cleaned properties
902
     *
903
     * @url POST    {id}/close
904
     */
905
    public function close($id, $notrigger = 0)
906
    {
907
        if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) {
908
            throw new RestException(403);
909
        }
910
        $result = $this->commande->fetch($id);
911
        if (!$result) {
912
            throw new RestException(404, 'Order not found');
913
        }
914
915
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
916
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
917
        }
918
919
        $result = $this->commande->cloture(DolibarrApiAccess::$user, $notrigger);
920
        if ($result == 0) {
921
            throw new RestException(304, 'Error nothing done. May be object is already closed');
922
        }
923
        if ($result < 0) {
924
            throw new RestException(500, 'Error when closing Order: ' . $this->commande->error);
925
        }
926
927
        $result = $this->commande->fetch($id);
928
        if (!$result) {
929
            throw new RestException(404, 'Order not found');
930
        }
931
932
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
933
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
934
        }
935
936
        $this->commande->fetchObjectLinked();
937
938
        return $this->_cleanObjectDatas($this->commande);
939
    }
940
941
    /**
942
     * Set an order to draft
943
     *
944
     * @param int $id Order ID
945
     * @param int $idwarehouse Warehouse ID to use for stock change (Used only if option STOCK_CALCULATE_ON_VALIDATE_ORDER is on)
946
     * @return  Object                  Object with cleaned properties
947
     *
948
     * @url POST    {id}/settodraft
949
     */
950
    public function settodraft($id, $idwarehouse = -1)
951
    {
952
        if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) {
953
            throw new RestException(403);
954
        }
955
        $result = $this->commande->fetch($id);
956
        if (!$result) {
957
            throw new RestException(404, 'Order not found');
958
        }
959
960
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
961
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
962
        }
963
964
        $result = $this->commande->setDraft(DolibarrApiAccess::$user, $idwarehouse);
965
        if ($result == 0) {
966
            throw new RestException(304, 'Nothing done. May be object is already closed');
967
        }
968
        if ($result < 0) {
969
            throw new RestException(500, 'Error when closing Order: ' . $this->commande->error);
970
        }
971
972
        $result = $this->commande->fetch($id);
973
        if (!$result) {
974
            throw new RestException(404, 'Order not found');
975
        }
976
977
        if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) {
978
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
979
        }
980
981
        $this->commande->fetchObjectLinked();
982
983
        return $this->_cleanObjectDatas($this->commande);
984
    }
985
986
    /**
987
     * Create an order using an existing proposal.
988
     *
989
     * @param int $proposalid Id of the proposal
990
     * @return  Object                  Object with cleaned properties
991
     *
992
     * @url     POST /createfromproposal/{proposalid}
993
     *
994
     * @throws RestException 400
995
     * @throws RestException 401
996
     * @throws RestException 404
997
     * @throws RestException 405
998
     */
999
    public function createOrderFromProposal($proposalid)
1000
    {
1001
        require_once constant('DOL_DOCUMENT_ROOT') . '/comm/propal/class/propal.class.php';
1002
1003
        if (!DolibarrApiAccess::$user->hasRight('propal', 'lire')) {
1004
            throw new RestException(403);
1005
        }
1006
        if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) {
1007
            throw new RestException(403);
1008
        }
1009
        if (empty($proposalid)) {
1010
            throw new RestException(400, 'Proposal ID is mandatory');
1011
        }
1012
1013
        $propal = new Propal($this->db);
1014
        $result = $propal->fetch($proposalid);
1015
        if (!$result) {
1016
            throw new RestException(404, 'Proposal not found');
1017
        }
1018
1019
        $result = $this->commande->createFromProposal($propal, DolibarrApiAccess::$user);
1020
        if ($result < 0) {
1021
            throw new RestException(405, $this->commande->error);
1022
        }
1023
        $this->commande->fetchObjectLinked();
1024
1025
        return $this->_cleanObjectDatas($this->commande);
1026
    }
1027
1028
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1029
1030
    /**
1031
     * Get the shipments of an order
1032
     *
1033
     * @param int $id Id of the order
1034
     *
1035
     * @url     GET {id}/shipment
1036
     *
1037
     * @return array
1038
     *
1039
     * @throws RestException 401
1040
     * @throws RestException 404
1041
     * @throws RestException 500 System error
1042
     */
1043
    public function getOrderShipments($id)
1044
    {
1045
        require_once constant('DOL_DOCUMENT_ROOT') . '/expedition/class/expedition.class.php';
1046
        if (!DolibarrApiAccess::$user->hasRight('expedition', 'lire')) {
1047
            throw new RestException(403);
1048
        }
1049
        $obj_ret = array();
1050
        $sql = "SELECT e.rowid";
1051
        $sql .= " FROM " . MAIN_DB_PREFIX . "expedition as e";
1052
        $sql .= " JOIN " . MAIN_DB_PREFIX . "expeditiondet as edet";
1053
        $sql .= " ON e.rowid = edet.fk_expedition";
1054
        $sql .= " JOIN " . MAIN_DB_PREFIX . "commandedet as cdet";
1055
        $sql .= " ON edet.fk_elementdet = cdet.rowid";
1056
        $sql .= " JOIN " . MAIN_DB_PREFIX . "commande as c";
1057
        $sql .= " ON cdet.fk_commande = c.rowid";
1058
        $sql .= " WHERE c.rowid = " . ((int)$id);
1059
        $sql .= " GROUP BY e.rowid";
1060
        $sql .= $this->db->order("e.rowid", "ASC");
1061
1062
        dol_syslog("API Rest request");
1063
        $result = $this->db->query($sql);
1064
1065
        if ($result) {
1066
            $num = $this->db->num_rows($result);
1067
            if ($num <= 0) {
1068
                throw new RestException(404, 'Shipments not found ');
1069
            }
1070
            $i = 0;
1071
            while ($i < $num) {
1072
                $obj = $this->db->fetch_object($result);
1073
                $shipment_static = new Expedition($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Commande\Api\Expedition was not found. Did you mean Expedition? If so, make sure to prefix the type with \.
Loading history...
1074
                if ($shipment_static->fetch($obj->rowid)) {
1075
                    $obj_ret[] = $this->_cleanObjectDatas($shipment_static);
1076
                }
1077
                $i++;
1078
            }
1079
        } else {
1080
            throw new RestException(500, 'Error when retrieve shipment list : ' . $this->db->lasterror());
1081
        }
1082
        return $obj_ret;
1083
    }
1084
1085
    /**
1086
     * Create the shipment of an order
1087
     *
1088
     * @param int $id Id of the order
1089
     * @param int $warehouse_id Id of a warehouse
1090
     *
1091
     * @url     POST {id}/shipment/{warehouse_id}
1092
     *
1093
     * @return int
1094
     *
1095
     * @throws RestException 401
1096
     * @throws RestException 404
1097
     * @throws RestException 500 System error
1098
     */
1099
    public function createOrderShipment($id, $warehouse_id)
1100
    {
1101
        require_once constant('DOL_DOCUMENT_ROOT') . '/expedition/class/expedition.class.php';
1102
        if (!DolibarrApiAccess::$user->hasRight('expedition', 'creer')) {
1103
            throw new RestException(403);
1104
        }
1105
        if ($warehouse_id <= 0) {
1106
            throw new RestException(404, 'Warehouse not found');
1107
        }
1108
        $result = $this->commande->fetch($id);
1109
        if (!$result) {
1110
            throw new RestException(404, 'Order not found');
1111
        }
1112
        $shipment = new Expedition($this->db);
1113
        $shipment->socid = $this->commande->socid;
1114
        $shipment->origin_id = $this->commande->id;
1115
        $result = $shipment->create(DolibarrApiAccess::$user);
1116
        if ($result <= 0) {
1117
            throw new RestException(500, 'Error on creating expedition :' . $this->db->lasterror());
1118
        }
1119
        foreach ($this->commande->lines as $line) {
1120
            $result = $shipment->create_line($warehouse_id, $line->id, $line->qty);
1121
            if ($result <= 0) {
1122
                throw new RestException(500, 'Error on creating expedition lines:' . $this->db->lasterror());
1123
            }
1124
        }
1125
        return $shipment->id;
1126
    }
1127
}
1128