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

Orders::putLine()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 54
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 39
nc 5
nop 3
dl 0
loc 54
rs 8.6737
c 0
b 0
f 0

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/* Copyright (C) 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