Passed
Push — EXTRACT_CLASSES ( c25e41...9f3ede )
by Rafael
55:18
created

SupplierInvoices::index()   F

Complexity

Conditions 21
Paths 12801

Size

Total Lines 82
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 21
eloc 51
nc 12801
nop 8
dl 0
loc 82
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) 2023	    Joachim Kueter		        <[email protected]>
6
 * Copyright (C) 2024		MDW							<[email protected]>
7
 * Copyright (C) 2024       Rafael San José             <[email protected]>
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21
 */
22
23
namespace Dolibarr\Code\Fourn\Api;
24
25
use Dolibarr\Core\Base\DolibarrApi;
26
use Luracast\Restler\RestException;
27
28
require_once constant('DOL_DOCUMENT_ROOT') . '/fourn/class/fournisseur.facture.class.php';
29
require_once constant('DOL_DOCUMENT_ROOT') . '/fourn/class/paiementfourn.class.php';
30
31
/**
32
 * API class for supplier invoices
33
 *
34
 * @property DoliDB $db
35
 * @access protected
36
 * @class  DolibarrApiAccess {@requires user,external}
37
 */
38
class SupplierInvoices extends DolibarrApi
39
{
40
    /**
41
     *
42
     * @var array   $FIELDS     Mandatory fields, checked when create and update object
43
     */
44
    public static $FIELDS = array(
45
        'socid',
46
    );
47
48
    /**
49
     * @var FactureFournisseur $invoice {@type FactureFournisseur}
50
     */
51
    public $invoice;
52
53
    /**
54
     * Constructor
55
     */
56
    public function __construct()
57
    {
58
        global $db;
59
        $this->db = $db;
60
        $this->invoice = new FactureFournisseur($this->db);
61
    }
62
63
    /**
64
     * Get properties of a supplier invoice object
65
     *
66
     * Return an array with supplier invoice information
67
     *
68
     * @param   int     $id             ID of supplier invoice
69
     * @return  Object                  Object with cleaned properties
70
     *
71
     * @throws  RestException 403
72
     * @throws  RestException 404
73
     */
74
    public function get($id)
75
    {
76
        if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "lire")) {
77
            throw new RestException(403);
78
        }
79
80
        if (!DolibarrApi::_checkAccessToResource('fournisseur', $id, 'facture_fourn', 'facture')) {
81
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
82
        }
83
84
        $result = $this->invoice->fetch($id);
85
        if (!$result) {
86
            throw new RestException(404, 'Supplier invoice not found');
87
        }
88
89
        $this->invoice->fetchObjectLinked();
90
        return $this->_cleanObjectDatas($this->invoice);
91
    }
92
93
    /**
94
     * List invoices
95
     *
96
     * Get a list of supplier invoices
97
     *
98
     * @param string    $sortfield        Sort field
99
     * @param string    $sortorder        Sort order
100
     * @param int       $limit            Limit for list
101
     * @param int       $page             Page number
102
     * @param string    $thirdparty_ids   Thirdparty ids to filter invoices of (example '1' or '1,2,3') {@pattern /^[0-9,]*$/i}
103
     * @param string    $status           Filter by invoice status : draft | unpaid | paid | cancelled
104
     * @param string    $sqlfilters       Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.datec:<:'20160101')"
105
     * @param string    $properties       Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names
106
     * @return array                      Array of invoice objects
107
     *
108
     * @throws RestException
109
     */
110
    public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $status = '', $sqlfilters = '', $properties = '')
111
    {
112
        if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "lire")) {
113
            throw new RestException(403);
114
        }
115
116
        $obj_ret = array();
117
118
        // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
119
        $socids = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $thirdparty_ids;
120
121
        // If the internal user must only see his customers, force searching by him
122
        $search_sale = 0;
123
        if (!DolibarrApiAccess::$user->hasRight("societe", "client", "voir")) {
124
            $search_sale = DolibarrApiAccess::$user->id;
125
        }
126
127
        $sql = "SELECT t.rowid";
128
        $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn AS t";
129
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "facture_fourn_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
130
        $sql .= ' WHERE t.entity IN (' . getEntity('supplier_invoice') . ')';
131
        if ($socids) {
132
            $sql .= " AND t.fk_soc IN (" . $this->db->sanitize($socids) . ")";
133
        }
134
        // Filter by status
135
        if ($status == 'draft') {
136
            $sql .= " AND t.fk_statut IN (0)";
137
        }
138
        if ($status == 'unpaid') {
139
            $sql .= " AND t.fk_statut IN (1)";
140
        }
141
        if ($status == 'paid') {
142
            $sql .= " AND t.fk_statut IN (2)";
143
        }
144
        if ($status == 'cancelled') {
145
            $sql .= " AND t.fk_statut IN (3)";
146
        }
147
        // Search on sale representative
148
        if ($search_sale && $search_sale != '-1') {
149
            if ($search_sale == -2) {
150
                $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc)";
151
            } elseif ($search_sale > 0) {
152
                $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) . ")";
153
            }
154
        }
155
        // Add sql filters
156
        if ($sqlfilters) {
157
            $errormessage = '';
158
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
159
            if ($errormessage) {
160
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
161
            }
162
        }
163
164
        $sql .= $this->db->order($sortfield, $sortorder);
165
        if ($limit) {
166
            if ($page < 0) {
167
                $page = 0;
168
            }
169
            $offset = $limit * $page;
170
171
            $sql .= $this->db->plimit($limit + 1, $offset);
172
        }
173
174
        $result = $this->db->query($sql);
175
        if ($result) {
176
            $i = 0;
177
            $num = $this->db->num_rows($result);
178
            $min = min($num, ($limit <= 0 ? $num : $limit));
179
            while ($i < $min) {
180
                $obj = $this->db->fetch_object($result);
181
                $invoice_static = new FactureFournisseur($this->db);
182
                if ($invoice_static->fetch($obj->rowid)) {
183
                    $obj_ret[] = $this->_filterObjectProperties($this->_cleanObjectDatas($invoice_static), $properties);
184
                }
185
                $i++;
186
            }
187
        } else {
188
            throw new RestException(503, 'Error when retrieve supplier invoice list : ' . $this->db->lasterror());
189
        }
190
191
        return $obj_ret;
192
    }
193
194
    /**
195
     * Create supplier invoice object
196
     *
197
     * Note: soc_id = dolibarr_order_id
198
     *
199
     * Example: {'ref': 'auto', 'ref_supplier': '7985630', 'socid': 1, 'note': 'Inserted with Python', 'order_supplier': 1, 'date': '2021-07-28'}
200
     *
201
     * @param array $request_data Request datas
202
     *
203
     * @return int  ID of supplier invoice
204
     *
205
     * @throws RestException 403
206
     * @throws RestException 500    System error
207
     */
208
    public function post($request_data = null)
209
    {
210
        if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "creer")) {
211
            throw new RestException(403, "Insuffisant rights");
212
        }
213
        // Check mandatory fields
214
        $result = $this->_validate($request_data);
215
216
        foreach ($request_data as $field => $value) {
217
            if ($field === 'caller') {
218
                // 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
219
                $this->invoice->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
220
                continue;
221
            }
222
223
            $this->invoice->$field = $this->_checkValForAPI($field, $value, $this->invoice);
224
        }
225
        if (!array_key_exists('date', $request_data)) {
226
            $this->invoice->date = dol_now();
227
        }
228
229
        if ($this->invoice->create(DolibarrApiAccess::$user) < 0) {
230
            throw new RestException(500, "Error creating invoice ", array_merge(array($this->invoice->error), $this->invoice->errors));
231
        }
232
        return $this->invoice->id;
233
    }
234
235
    /**
236
     * Update supplier invoice
237
     *
238
     * @param   int     $id                 Id of supplier invoice to update
239
     * @param   array   $request_data       Datas
240
     * @return  Object|false                Updated object
241
     *
242
     * @throws RestException 403
243
     * @throws RestException 404
244
     */
245
    public function put($id, $request_data = null)
246
    {
247
        if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "creer")) {
248
            throw new RestException(403);
249
        }
250
251
        if (!DolibarrApi::_checkAccessToResource('fournisseur', $id, 'facture_fourn', 'facture')) {
252
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
253
        }
254
255
        $result = $this->invoice->fetch($id);
256
        if (!$result) {
257
            throw new RestException(404, 'Supplier invoice not found');
258
        }
259
260
        foreach ($request_data as $field => $value) {
261
            if ($field == 'id') {
262
                continue;
263
            }
264
            if ($field === 'caller') {
265
                // 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
266
                $this->invoice->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
267
                continue;
268
            }
269
            if ($field == 'array_options' && is_array($value)) {
270
                foreach ($value as $index => $val) {
271
                    $this->invoice->array_options[$index] = $this->_checkValForAPI($field, $val, $this->invoice);
272
                }
273
                continue;
274
            }
275
            $this->invoice->$field = $this->_checkValForAPI($field, $value, $this->invoice);
276
        }
277
278
        if ($this->invoice->update(DolibarrApiAccess::$user)) {
279
            return $this->get($id);
280
        }
281
282
        return false;
283
    }
284
285
    /**
286
     * Delete supplier invoice
287
     *
288
     * @param int   $id Supplier invoice ID
289
     *
290
     * @return array
291
     *
292
     * @throws RestException 403
293
     * @throws RestException 404
294
     * @throws RestException 500    System error
295
     */
296
    public function delete($id)
297
    {
298
        if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "supprimer")) {
299
            throw new RestException(403);
300
        }
301
        if (!DolibarrApi::_checkAccessToResource('fournisseur', $id, 'facture_fourn', 'facture')) {
302
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
303
        }
304
        $result = $this->invoice->fetch($id);
305
        if (!$result) {
306
            throw new RestException(404, 'Supplier invoice not found');
307
        }
308
309
        if ($this->invoice->delete(DolibarrApiAccess::$user) < 0) {
310
            throw new RestException(500, 'Error when deleting invoice');
311
        }
312
313
        return array(
314
            'success' => array(
315
                'code' => 200,
316
                'message' => 'Supplier invoice deleted'
317
            )
318
        );
319
    }
320
321
    /**
322
     * Validate an invoice
323
     *
324
     * @param   int $id             Invoice ID
325
     * @param   int $idwarehouse    Warehouse ID
326
     * @param   int $notrigger      1=Does not execute triggers, 0= execute triggers
327
     *
328
     * @url POST    {id}/validate
329
     *
330
     * @return  array
331
     *
332
     * @throws RestException 304
333
     * @throws RestException 403
334
     * @throws RestException 404
335
     * @throws RestException 405
336
     * @throws RestException 500    System error
337
     */
338
    public function validate($id, $idwarehouse = 0, $notrigger = 0)
339
    {
340
        if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "creer")) {
341
            throw new RestException(403);
342
        }
343
344
        if (!DolibarrApi::_checkAccessToResource('fournisseur', $id, 'facture_fourn', 'facture')) {
345
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
346
        }
347
348
        $result = $this->invoice->fetch($id);
349
        if (!$result) {
350
            throw new RestException(404, 'Invoice not found');
351
        }
352
353
        $result = $this->invoice->validate(DolibarrApiAccess::$user, '', $idwarehouse, $notrigger);
354
        if ($result == 0) {
355
            throw new RestException(304, 'Error nothing done. The invoice is already validated');
356
        }
357
        if ($result < 0) {
358
            throw new RestException(500, 'Error when validating Invoice: ' . $this->invoice->error);
359
        }
360
361
        return array(
362
            'success' => array(
363
                'code' => 200,
364
                'message' => 'Invoice validated (Ref=' . $this->invoice->ref . ')'
365
            )
366
        );
367
    }
368
369
    /**
370
     * Get list of payments of a given supplier invoice
371
     *
372
     * @param int   $id             Id of SupplierInvoice
373
     *
374
     * @url     GET {id}/payments
375
     *
376
     * @return array
377
     * @throws RestException 400
378
     * @throws RestException 403
379
     * @throws RestException 404
380
     * @throws RestException 405
381
     */
382
    public function getPayments($id)
383
    {
384
        if (empty($id)) {
385
            throw new RestException(400, 'Invoice ID is mandatory');
386
        }
387
388
        if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "lire")) {
389
            throw new RestException(403);
390
        }
391
        if (!DolibarrApi::_checkAccessToResource('fournisseur', $id, 'facture_fourn', 'facture')) {
392
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
393
        }
394
395
        $result = $this->invoice->fetch($id);
396
        if (!$result) {
397
            throw new RestException(404, 'Invoice not found');
398
        }
399
400
        $result = $this->invoice->getListOfPayments();
401
        if ($this->invoice->error !== '') {
402
            throw new RestException(405, $this->invoice->error);
403
        }
404
405
        return $result;
406
    }
407
408
409
    /**
410
     * Add payment line to a specific supplier invoice with the remain to pay as amount.
411
     *
412
     * @param int     $id                               Id of invoice
413
     * @param int     $datepaye           {@from body}  Payment date        {@type timestamp}
414
     * @param int     $payment_mode_id    {@from body}  Payment mode ID (look it up via REST GET to /setup/dictionary/payment_types) {@min 1}
415
     * @param string  $closepaidinvoices  {@from body}  Close paid invoices {@choice yes,no}
416
     * @param int     $accountid          {@from body}  Bank account ID (look it up via REST GET to /bankaccounts) {@min 1}
417
     * @param string  $num_payment        {@from body}  Payment number (optional)
418
     * @param string  $comment            {@from body}  Note (optional)
419
     * @param string  $chqemetteur        {@from body}  Payment issuer (mandatory if payment_mode_id corresponds to 'CHQ'-payment type)
420
     * @param string  $chqbank            {@from body}  Issuer bank name (optional)
421
     * @param float   $amount             {@from body}  Amount of payment if we don't want to use the remain to pay
422
     *
423
     * @url     POST {id}/payments
424
     *
425
     * @return int  Payment ID
426
     *
427
     * @throws RestException 400
428
     * @throws RestException 403
429
     * @throws RestException 404
430
     */
431
    public function addPayment($id, $datepaye, $payment_mode_id, $closepaidinvoices, $accountid, $num_payment = '', $comment = '', $chqemetteur = '', $chqbank = '', $amount = null)
432
    {
433
        if (empty($id)) {
434
            throw new RestException(400, 'Invoice ID is mandatory');
435
        }
436
437
        if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "creer")) {
438
            throw new RestException(403);
439
        }
440
        if (!DolibarrApi::_checkAccessToResource('fournisseur', $id, 'facture_fourn', 'facture')) {
441
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
442
        }
443
444
        $result = $this->invoice->fetch($id);
445
        if (!$result) {
446
            throw new RestException(404, 'Invoice not found');
447
        }
448
449
        if (isModEnabled("bank")) {
450
            if (empty($accountid)) {
451
                throw new RestException(400, 'Bank account ID is mandatory');
452
            }
453
        }
454
455
        if (empty($payment_mode_id)) {
456
            throw new RestException(400, 'Payment mode ID is mandatory');
457
        }
458
459
        if (null !== $amount && $amount > 0) {
460
            // We use the amount given in parameter
461
            $paymentamount = $amount;
462
        } else {
463
            // We calculate the remain to pay, and use it as amount
464
            $totalpaid = $this->invoice->getSommePaiement();
465
            $totaldeposits = $this->invoice->getSumDepositsUsed();
466
            $paymentamount = price2num($this->invoice->total_ttc - $totalpaid - $totaldeposits, 'MT');
467
        }
468
469
        $this->db->begin();
470
471
        $amounts = array();
472
        $multicurrency_amounts = array();
473
474
        $paymentamount = (float) price2num($paymentamount, 'MT');
475
476
        $amounts[$id] = $paymentamount;
477
478
        // Multicurrency
479
        $newvalue = (float) price2num($this->invoice->multicurrency_total_ttc, 'MT');
480
        $multicurrency_amounts[$id] = $newvalue;
481
482
        // Creation of payment line
483
        $paiement = new PaiementFourn($this->db);
484
        $paiement->datepaye     = $datepaye;
485
        $paiement->amounts      = $amounts; // Array with all payments dispatching with invoice id
486
        $paiement->multicurrency_amounts = $multicurrency_amounts; // Array with all payments dispatching
487
        $paiement->paiementid = $payment_mode_id;
488
        $paiement->paiementcode = (string) dol_getIdFromCode($this->db, $payment_mode_id, 'c_paiement', 'id', 'code', 1);
489
        $paiement->num_payment = $num_payment;
490
        $paiement->note_public = $comment;
491
492
        $paiement_id = $paiement->create(DolibarrApiAccess::$user, ($closepaidinvoices == 'yes' ? 1 : 0)); // This include closing invoices
493
        if ($paiement_id < 0) {
494
            $this->db->rollback();
495
            throw new RestException(400, 'Payment error : ' . $paiement->error);
496
        }
497
498
        if (isModEnabled("bank")) {
499
            $result = $paiement->addPaymentToBank(DolibarrApiAccess::$user, 'payment_supplier', '(SupplierInvoicePayment)', $accountid, $chqemetteur, $chqbank);
500
            if ($result < 0) {
501
                $this->db->rollback();
502
                throw new RestException(400, 'Add payment to bank error : ' . $paiement->error);
503
            }
504
        }
505
506
        $this->db->commit();
507
508
        return $paiement_id;
509
    }
510
511
    /**
512
     * Get lines of a supplier invoice
513
     *
514
     * @param int   $id             Id of supplier invoice
515
     *
516
     * @url GET {id}/lines
517
     *
518
     * @return array
519
     *
520
     * @throws RestException 403
521
     * @throws RestException 404
522
     */
523
    public function getLines($id)
524
    {
525
        if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "creer")) {
526
            throw new RestException(403);
527
        }
528
        if (!DolibarrApi::_checkAccessToResource('fournisseur', $id, 'facture_fourn', 'facture')) {
529
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
530
        }
531
532
        $result = $this->invoice->fetch($id);
533
        if (!$result) {
534
            throw new RestException(404, 'Supplier invoice not found');
535
        }
536
537
        $this->invoice->fetch_lines();
538
        $result = array();
539
        foreach ($this->invoice->lines as $line) {
540
            array_push($result, $this->_cleanObjectDatas($line));
541
        }
542
        return $result;
543
    }
544
545
    /**
546
     * Add a line to given supplier invoice
547
     *
548
     * Note: socid = dolibarr_order_id, pu_ht = net price, remise = discount
549
     *
550
     * Example: {'socid': 1, 'qty': 1, 'pu_ht': 21.0, 'tva_tx': 25.0, 'fk_product': '1189', 'product_type': 0, 'remise_percent': 1.0, 'vat_src_code': None}
551
     *
552
     * @param int   $id             Id of supplier invoice to update
553
     * @param array $request_data   supplier invoice line data
554
     *
555
     * @url POST {id}/lines
556
     *
557
     * @return int|bool
558
     *
559
     * @throws RestException 403
560
     * @throws RestException 404
561
     */
562
    public function postLine($id, $request_data = null)
563
    {
564
        if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "creer")) {
565
            throw new RestException(403);
566
        }
567
568
        if (!DolibarrApi::_checkAccessToResource('fournisseur', $id, 'facture_fourn', 'facture')) {
569
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
570
        }
571
572
        $result = $this->invoice->fetch($id);
573
        if (!$result) {
574
            throw new RestException(404, 'Supplier invoice not found');
575
        }
576
577
        $request_data = (object) $request_data;
578
579
        $request_data->description = sanitizeVal($request_data->description, 'restricthtml');
580
        $request_data->ref_supplier = sanitizeVal($request_data->ref_supplier);
581
582
        $updateRes = $this->invoice->addline(
583
            $request_data->description,
584
            $request_data->pu_ht,
585
            $request_data->tva_tx,
586
            $request_data->localtax1_tx,
587
            $request_data->localtax2_tx,
588
            $request_data->qty,
589
            $request_data->fk_product,
590
            $request_data->remise_percent,
591
            $request_data->date_start,
592
            $request_data->date_end,
593
            $request_data->fk_code_ventilation,
594
            $request_data->info_bits,
595
            $request_data->price_base_type ? $request_data->price_base_type : 'HT',
596
            $request_data->product_type,
597
            $request_data->rang,
598
            false,
599
            $request_data->array_options,
600
            $request_data->fk_unit,
601
            $request_data->origin_id,
602
            $request_data->multicurrency_subprice,
603
            $request_data->ref_supplier,
604
            $request_data->special_code
605
        );
606
607
        if ($updateRes < 0) {
608
            throw new RestException(400, 'Unable to insert the new line. Check your inputs. ' . $this->invoice->error);
609
        }
610
611
        return $updateRes;
612
    }
613
614
    /**
615
     * Update a line to a given supplier invoice
616
     *
617
     * @param int   $id             Id of supplier invoice to update
618
     * @param int   $lineid         Id of line to update
619
     * @param array $request_data   InvoiceLine data
620
     *
621
     * @url PUT {id}/lines/{lineid}
622
     *
623
     * @return object
624
     *
625
     * @throws RestException 403 Not allowed
626
     * @throws RestException 404 Not found
627
     * @throws RestException 304 Error
628
     */
629
    public function putLine($id, $lineid, $request_data = null)
630
    {
631
        if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "creer")) {
632
            throw new RestException(403);
633
        }
634
635
        if (!DolibarrApi::_checkAccessToResource('fournisseur', $id, 'facture_fourn', 'facture')) {
636
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
637
        }
638
639
        $result = $this->invoice->fetch($id);
640
        if (!$result) {
641
            throw new RestException(404, 'Supplier invoice not found');
642
        }
643
644
        $request_data = (object) $request_data;
645
646
        $request_data->description = sanitizeVal($request_data->description, 'restricthtml');
647
        $request_data->ref_supplier = sanitizeVal($request_data->ref_supplier);
648
649
        $updateRes = $this->invoice->updateline(
650
            $lineid,
651
            $request_data->description,
652
            $request_data->pu_ht,
653
            $request_data->tva_tx,
654
            $request_data->localtax1_tx,
655
            $request_data->localtax2_tx,
656
            $request_data->qty,
657
            $request_data->fk_product,
658
            $request_data->price_base_type ? $request_data->price_base_type : 'HT',
659
            $request_data->info_bits,
660
            $request_data->product_type,
661
            $request_data->remise_percent,
662
            false,
663
            $request_data->date_start,
664
            $request_data->date_end,
665
            $request_data->array_options,
666
            $request_data->fk_unit,
667
            $request_data->multicurrency_subprice,
668
            $request_data->ref_supplier,
669
            $request_data->rang
670
        );
671
672
        if ($updateRes > 0) {
673
            $result = $this->get($id);
674
            unset($result->line);
675
            return $this->_cleanObjectDatas($result);
676
        } else {
677
            throw new RestException(304, $this->invoice->error);
678
        }
679
    }
680
681
    /**
682
     * Deletes a line of a given supplier invoice
683
     *
684
     * @param int   $id             Id of supplier invoice
685
     * @param int   $lineid         Id of the line to delete
686
     *
687
     * @url     DELETE {id}/lines/{lineid}
688
     *
689
     * @return array
690
     *
691
     * @throws RestException 400 Bad parameters
692
     * @throws RestException 403 Not allowed
693
     * @throws RestException 404 Not found
694
     * @throws RestException 405 Error
695
     */
696
    public function deleteLine($id, $lineid)
697
    {
698
        if (empty($lineid)) {
699
            throw new RestException(400, 'Line ID is mandatory');
700
        }
701
702
        if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "creer")) {
703
            throw new RestException(403);
704
        }
705
        if (!DolibarrApi::_checkAccessToResource('fournisseur', $id, 'facture_fourn', 'facture')) {
706
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
707
        }
708
709
        $result = $this->invoice->fetch($id);
710
        if (!$result) {
711
            throw new RestException(404, 'Supplier invoice not found');
712
        }
713
714
        // TODO Check the lineid $lineid is a line of object
715
716
        $updateRes = $this->invoice->deleteLine($lineid);
717
        if ($updateRes > 0) {
718
            return array(
719
                'success' => array(
720
                    'code' => 200,
721
                    'message' => 'line ' . $lineid . ' deleted'
722
                )
723
            );
724
        } else {
725
            throw new RestException(405, $this->invoice->error);
726
        }
727
    }
728
729
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
730
    /**
731
     * Clean sensible object datas
732
     *
733
     * @param   Object  $object     Object to clean
734
     * @return  Object              Object with cleaned properties
735
     */
736
    protected function _cleanObjectDatas($object)
737
    {
738
		// phpcs:enable
739
        $object = parent::_cleanObjectDatas($object);
740
741
        unset($object->rowid);
742
        unset($object->barcode_type);
743
        unset($object->barcode_type_code);
744
        unset($object->barcode_type_label);
745
        unset($object->barcode_type_coder);
746
747
        return $object;
748
    }
749
750
    /**
751
     * Validate fields before create or update object
752
     *
753
     * @param array $data   Datas to validate
754
     * @return array
755
     *
756
     * @throws RestException
757
     */
758
    private function _validate($data)
759
    {
760
        $invoice = array();
761
        foreach (SupplierInvoices::$FIELDS as $field) {
762
            if (!isset($data[$field])) {
763
                throw new RestException(400, "$field field missing");
764
            }
765
            $invoice[$field] = $data[$field];
766
        }
767
        return $invoice;
768
    }
769
}
770