Passed
Push — CHECK_API ( 78ffdd...fa4f39 )
by Rafael
41:29
created

Thirdparties   F

Complexity

Total Complexity 313

Size/Duplication

Total Lines 2009
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 784
dl 0
loc 2009
rs 1.816
c 0
b 0
f 0
wmc 313

43 Methods

Rating   Name   Duplication   Size   Complexity  
B getCompanyNotification() 0 57 11
A getOutStandingProposals() 0 25 5
A __construct() 0 9 2
B getCategories() 0 24 7
C put() 0 41 14
A addSupplierCategory() 0 26 6
A get() 0 3 1
A deleteSocieteAccounts() 0 30 6
D generateBankAccountDocument() 0 78 15
A deleteCompanyNotification() 0 16 3
A deleteSocieteAccount() 0 18 5
A deleteCompanyBankAccount() 0 16 3
C putSocieteAccount() 0 76 17
B post() 0 26 8
A addRepresentative() 0 20 5
A addCategory() 0 26 6
A deleteCategory() 0 26 6
B updateCompanyBankAccount() 0 40 8
A _cleanObjectDatas() 0 32 1
A getSalesRepresentatives() 0 22 5
A createCompanyNotification() 0 25 6
A getByEmail() 0 3 1
A _validate() 0 10 3
A updateCompanyNotification() 0 26 6
A deleteSupplierCategory() 0 26 6
B getSocieteAccounts() 0 55 11
A getByBarcode() 0 3 1
B getSupplierCategories() 0 24 7
A getInvoicesQualifiedForReplacement() 0 25 5
A delete() 0 25 6
B setThirdpartyPriceLevel() 0 43 11
B patchSocieteAccount() 0 43 11
B getFixedAmountDiscounts() 0 45 9
A getInvoicesQualifiedForCreditNote() 0 25 5
B createSocieteAccount() 0 39 9
B merge() 0 36 8
A deleteRepresentative() 0 20 5
A getOutStandingInvoices() 0 25 5
F index() 0 104 32
B _fetch() 0 38 7
C getCompanyBankAccount() 0 64 12
A getOutStandingOrder() 0 25 5
B createCompanyBankAccount() 0 38 8

How to fix   Complexity   

Complex Class

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

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

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

1
<?php
2
3
/* Copyright (C) 2015       Jean-François Ferry         <[email protected]>
4
 * Copyright (C) 2018   	Pierre Chéné                <[email protected]>
5
 * Copyright (C) 2019   	Cedric Ancelin              <[email protected]>
6
 * Copyright (C) 2020-2024  Frédéric France     	    <[email protected]>
7
 * Copyright (C) 2023       Alexandre Janniaux  	    <[email protected]>
8
 * Copyright (C) 2024		MDW						    <[email protected]>
9
 * Copyright (C) 2024       Jon Bendtsen                <[email protected]>
10
 * Copyright (C) 2024       Rafael San José             <[email protected]>
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 3 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24
 */
25
26
namespace Dolibarr\Code\Societe\Api;
27
28
use Dolibarr\Code\Api\Classes\DolibarrApiAccess;
29
use Dolibarr\Code\Categories\Classes\Categorie;
30
use Dolibarr\Code\Compta\Classes\BonPrelevement;
31
use Dolibarr\Code\Compta\Classes\Facture;
32
use Dolibarr\Code\Core\Classes\Notify;
33
use Dolibarr\Code\Core\Classes\Translate;
34
use Dolibarr\Code\Societe\Classes\CompanyBankAccount;
35
use Dolibarr\Code\Societe\Classes\Societe;
36
use Dolibarr\Code\Societe\Classes\SocieteAccount;
37
use Dolibarr\Code\User\Classes\User;
38
use Dolibarr\Core\Base\DolibarrApi;
39
use Luracast\Restler\RestException;
40
41
/**
42
 * API class for thirdparties
43
 *
44
 * @access protected
45
 * @class  DolibarrApiAccess {@requires user,external}
46
 *
47
 */
48
class Thirdparties extends DolibarrApi
49
{
50
    /**
51
     *
52
     * @var array   $FIELDS     Mandatory fields, checked when we create and update the object
53
     */
54
    public static $FIELDS = array(
55
        'name'
56
    );
57
58
    /**
59
     * @var Societe $company {@type Societe}
60
     */
61
    public $company;
62
63
    /**
64
     * Constructor
65
     */
66
    public function __construct()
67
    {
68
        global $db;
69
        $this->db = $db;
70
71
        $this->company = new Societe($this->db);
72
73
        if (getDolGlobalString('SOCIETE_EMAIL_MANDATORY')) {
74
            static::$FIELDS[] = 'email';
75
        }
76
    }
77
78
    /**
79
     * Get properties of a thirdparty object
80
     *
81
     * Return an array with thirdparty information
82
     *
83
     * @param   int     $id             Id of third party to load
84
     * @return  Object                  Object with cleaned properties
85
     *
86
     * @throws  RestException
87
     */
88
    public function get($id)
89
    {
90
        return $this->_fetch($id);
91
    }
92
93
    /**
94
     * Get properties of a thirdparty object by email.
95
     *
96
     * Return an array with thirdparty information
97
     *
98
     * @param string    $email  Email of third party to load
99
     * @return array|mixed Cleaned Societe object
100
     *
101
     * @url     GET email/{email}
102
     *
103
     * @throws RestException
104
     */
105
    public function getByEmail($email)
106
    {
107
        return $this->_fetch('', '', '', '', '', '', '', '', '', '', $email);
108
    }
109
110
    /**
111
     * Get properties of a thirdparty object by barcode.
112
     *
113
     * Return an array with thirdparty information
114
     *
115
     * @param string    $barcode  Barcode of third party to load
116
     * @return array|mixed Cleaned Societe object
117
     *
118
     * @url     GET barcode/{barcode}
119
     *
120
     * @throws RestException
121
     */
122
    public function getByBarcode($barcode)
123
    {
124
        return $this->_fetch('', '', '', $barcode);
125
    }
126
127
    /**
128
     * List thirdparties
129
     *
130
     * Get a list of thirdparties
131
     *
132
     * @param   string  $sortfield  Sort field
133
     * @param   string  $sortorder  Sort order
134
     * @param   int     $limit      Limit for list
135
     * @param   int     $page       Page number
136
     * @param   int     $mode       Set to 1 to show only customers
137
     *                              Set to 2 to show only prospects
138
     *                              Set to 3 to show only those are not customer neither prospect
139
     *                              Set to 4 to show only suppliers
140
     * @param   int     $category   Use this param to filter list by category
141
     * @param   string  $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "((t.nom:like:'TheCompany%') or (t.name_alias:like:'TheCompany%')) and (t.datec:<:'20160101')"
142
     * @param string    $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names
143
     * @return  array               Array of thirdparty objects
144
     */
145
    public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $mode = 0, $category = 0, $sqlfilters = '', $properties = '')
146
    {
147
        $obj_ret = array();
148
149
        if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
150
            throw new RestException(403);
151
        }
152
153
        // case of external user, we force socids
154
        $socids = DolibarrApiAccess::$user->socid ? (string) DolibarrApiAccess::$user->socid : '';
155
156
        // If the internal user must only see his customers, force searching by him
157
        $search_sale = 0;
158
        if (!DolibarrApiAccess::$user->hasRight('societe', 'client', 'voir') && !$socids) {
159
            $search_sale = DolibarrApiAccess::$user->id;
160
        }
161
162
        $sql = "SELECT t.rowid";
163
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe as t";
164
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_extrafields AS ef ON ef.fk_object = t.rowid"; // So we will be able to filter on extrafields
165
        if ($category > 0) {
166
            if ($mode != 4) {
167
                $sql .= ", " . MAIN_DB_PREFIX . "categorie_societe as c";
168
            }
169
            if (!in_array($mode, array(1, 2, 3))) {
170
                $sql .= ", " . MAIN_DB_PREFIX . "categorie_fournisseur as cc";
171
            }
172
        }
173
        $sql .= ", " . MAIN_DB_PREFIX . "c_stcomm as st";
174
        $sql .= " WHERE t.entity IN (" . getEntity('societe') . ")";
175
        $sql .= " AND t.fk_stcomm = st.id";
176
        if ($mode == 1) {
177
            $sql .= " AND t.client IN (1, 3)";
178
        } elseif ($mode == 2) {
179
            $sql .= " AND t.client IN (2, 3)";
180
        } elseif ($mode == 3) {
181
            $sql .= " AND t.client IN (0)";
182
        } elseif ($mode == 4) {
183
            $sql .= " AND t.fournisseur IN (1)";
184
        }
185
        // Select thirdparties of given category
186
        if ($category > 0) {
187
            if (!empty($mode) && $mode != 4) {
188
                $sql .= " AND c.fk_categorie = " . ((int) $category) . " AND c.fk_soc = t.rowid";
189
            } elseif (!empty($mode) && $mode == 4) {
190
                $sql .= " AND cc.fk_categorie = " . ((int) $category) . " AND cc.fk_soc = t.rowid";
191
            } else {
192
                $sql .= " AND ((c.fk_categorie = " . ((int) $category) . " AND c.fk_soc = t.rowid) OR (cc.fk_categorie = " . ((int) $category) . " AND cc.fk_soc = t.rowid))";
193
            }
194
        }
195
        if ($socids) {
196
            $sql .= " AND t.rowid IN (" . $this->db->sanitize($socids) . ")";
197
        }
198
        // Search on sale representative
199
        if ($search_sale && $search_sale != '-1') {
200
            if ($search_sale == -2) {
201
                $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = t.rowid)";
202
            } elseif ($search_sale > 0) {
203
                $sql .= " AND EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = t.rowid AND sc.fk_user = " . ((int) $search_sale) . ")";
204
            }
205
        }
206
        // Add sql filters
207
        if ($sqlfilters) {
208
            $errormessage = '';
209
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
210
            if ($errormessage) {
211
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
212
            }
213
        }
214
215
        $sql .= $this->db->order($sortfield, $sortorder);
216
217
        if ($limit) {
218
            if ($page < 0) {
219
                $page = 0;
220
            }
221
            $offset = $limit * $page;
222
223
            $sql .= $this->db->plimit($limit + 1, $offset);
224
        }
225
226
        $result = $this->db->query($sql);
227
        if ($result) {
228
            $num = $this->db->num_rows($result);
229
            $min = min($num, ($limit <= 0 ? $num : $limit));
230
            $i = 0;
231
            while ($i < $min) {
232
                $obj = $this->db->fetch_object($result);
233
                $soc_static = new Societe($this->db);
234
                if ($soc_static->fetch($obj->rowid)) {
235
                    if (isModEnabled('mailing')) {
236
                        $soc_static->getNoEmail();
237
                    }
238
                    $obj_ret[] = $this->_filterObjectProperties($this->_cleanObjectDatas($soc_static), $properties);
239
                }
240
                $i++;
241
            }
242
        } else {
243
            throw new RestException(503, 'Error when retrieve thirdparties : ' . $this->db->lasterror());
244
        }
245
        if (!count($obj_ret)) {
246
            throw new RestException(404, 'Thirdparties not found');
247
        }
248
        return $obj_ret;
249
    }
250
251
    /**
252
     * Create thirdparty object
253
     *
254
     * @param array $request_data   Request datas
255
     * @return int  ID of thirdparty
256
     */
257
    public function post($request_data = null)
258
    {
259
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
260
            throw new RestException(403);
261
        }
262
        // Check mandatory fields
263
        $result = $this->_validate($request_data);
264
265
        foreach ($request_data as $field => $value) {
266
            if ($field === 'caller') {
267
                // 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
268
                $this->company->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
269
                continue;
270
            }
271
272
            $this->company->$field = $this->_checkValForAPI($field, $value, $this->company);
273
        }
274
275
        if ($this->company->create(DolibarrApiAccess::$user) < 0) {
276
            throw new RestException(500, 'Error creating thirdparty', array_merge(array($this->company->error), $this->company->errors));
277
        }
278
        if (isModEnabled('mailing') && !empty($this->company->email) && isset($this->company->no_email)) {
279
            $this->company->setNoEmail($this->company->no_email);
280
        }
281
282
        return $this->company->id;
283
    }
284
285
    /**
286
     * Update thirdparty
287
     *
288
     * @param   int             $id             Id of thirdparty to update
289
     * @param   array           $request_data   Datas
290
     * @return  Object|false                    Updated object
291
     *
292
     * @throws RestException 401
293
     * @throws RestException 404
294
     * @throws RestException 500
295
     */
296
    public function put($id, $request_data = null)
297
    {
298
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
299
            throw new RestException(403);
300
        }
301
302
        $result = $this->company->fetch($id);
303
        if (!$result) {
304
            throw new RestException(404, 'Thirdparty not found');
305
        }
306
307
        if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
308
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
309
        }
310
311
        foreach ($request_data as $field => $value) {
312
            if ($field == 'id') {
313
                continue;
314
            }
315
            if ($field === 'caller') {
316
                // 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
317
                $this->company->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
318
                continue;
319
            }
320
            if ($field == 'array_options' && is_array($value)) {
321
                foreach ($value as $index => $val) {
322
                    $this->company->array_options[$index] = $val;
323
                }
324
                continue;
325
            }
326
            $this->company->$field = $this->_checkValForAPI($field, $value, $this->company);
327
        }
328
329
        if (isModEnabled('mailing') && !empty($this->company->email) && isset($this->company->no_email)) {
330
            $this->company->setNoEmail($this->company->no_email);
331
        }
332
333
        if ($this->company->update($id, DolibarrApiAccess::$user, 1, '', '', 'update', 1) > 0) {
334
            return $this->get($id);
335
        } else {
336
            throw new RestException(500, $this->company->error);
337
        }
338
    }
339
340
    /**
341
     * Merge a third party into another one.
342
     *
343
     * Merge content (properties, notes) and objects (like invoices, events, orders, proposals, ...) of a thirdparty into a target third party,
344
     * then delete the merged third party.
345
     * If a property has a defined value both in third party to delete and third party to keep, the value into the third party to
346
     * delete will be ignored, the value of target thirdparty will remain, except for notes (content is concatenated).
347
     *
348
     * @param int   $id             ID of thirdparty to keep (the target third party)
349
     * @param int   $idtodelete     ID of thirdparty to remove (the thirdparty to delete), once data has been merged into the target third party.
350
     * @return Object               Return the resulted third party.
351
     *
352
     * @url PUT {id}/merge/{idtodelete}
353
     */
354
    public function merge($id, $idtodelete)
355
    {
356
        if ($id == $idtodelete) {
357
            throw new RestException(400, 'Try to merge a thirdparty into itself');
358
        }
359
360
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
361
            throw new RestException(403);
362
        }
363
364
        $result = $this->company->fetch($id); // include the fetch of extra fields
365
        if (!$result) {
366
            throw new RestException(404, 'Thirdparty not found');
367
        }
368
369
        if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
370
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
371
        }
372
373
        $companytoremove = new Societe($this->db);
374
        $result = $companytoremove->fetch($idtodelete); // include the fetch of extra fields
375
        if (!$result) {
376
            throw new RestException(404, 'Thirdparty not found');
377
        }
378
379
        if (!DolibarrApi::_checkAccessToResource('societe', $companytoremove->id)) {
380
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
381
        }
382
383
        $user = DolibarrApiAccess::$user;
384
        $result = $this->company->mergeCompany($companytoremove->id);
385
        if ($result < 0) {
386
            throw new RestException(500, 'Error failed to merged thirdparty ' . $companytoremove->id . ' into ' . $id . '. Enable and read log file for more information.');
387
        }
388
389
        return $this->get($id);
390
    }
391
392
    /**
393
     * Delete thirdparty
394
     *
395
     * @param int $id   Thirdparty ID
396
     * @return array
397
     */
398
    public function delete($id)
399
    {
400
        if (!DolibarrApiAccess::$user->hasRight('societe', 'supprimer')) {
401
            throw new RestException(403);
402
        }
403
        $result = $this->company->fetch($id);
404
        if (!$result) {
405
            throw new RestException(404, 'Thirdparty not found');
406
        }
407
        if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
408
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
409
        }
410
        $this->company->oldcopy = clone $this->company;
411
412
        $res = $this->company->delete($id);
413
        if ($res < 0) {
414
            throw new RestException(500, "Can't delete, error occurs");
415
        } elseif ($res == 0) {
416
            throw new RestException(409, "Can't delete, that product is probably used");
417
        }
418
419
        return array(
420
            'success' => array(
421
                'code' => 200,
422
                'message' => 'Object deleted'
423
            )
424
        );
425
    }
426
427
    /**
428
     * Set new price level for the given thirdparty
429
     *
430
     * @param   int     $id             ID of thirdparty
431
     * @param   int     $priceLevel     Price level to apply to thirdparty
432
     * @return  Object                  Thirdparty data without useless information
433
     *
434
     * @url PUT {id}/setpricelevel/{priceLevel}
435
     *
436
     * @throws RestException 400 Price level out of bounds
437
     * @throws RestException 401 Access not allowed for your login
438
     * @throws RestException 404 Thirdparty not found
439
     * @throws RestException 500 Error fetching/setting price level
440
     * @throws RestException 501 Request needs modules "Thirdparties" and "Products" and setting Multiprices activated
441
     */
442
    public function setThirdpartyPriceLevel($id, $priceLevel)
443
    {
444
        global $conf;
445
446
        if (!isModEnabled('societe')) {
447
            throw new RestException(501, 'Module "Thirdparties" needed for this request');
448
        }
449
450
        if (!isModEnabled("product")) {
451
            throw new RestException(501, 'Module "Products" needed for this request');
452
        }
453
454
        if (!getDolGlobalString('PRODUIT_MULTIPRICES')) {
455
            throw new RestException(501, 'Multiprices features activation needed for this request');
456
        }
457
458
        if ($priceLevel < 1 || $priceLevel > getDolGlobalString('PRODUIT_MULTIPRICES_LIMIT')) {
459
            throw new RestException(400, 'Price level must be between 1 and ' . getDolGlobalString('PRODUIT_MULTIPRICES_LIMIT'));
460
        }
461
462
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
463
            throw new RestException(403, 'Access to thirdparty ' . $id . ' not allowed for login ' . DolibarrApiAccess::$user->login);
464
        }
465
466
        $result = $this->company->fetch($id);
467
        if ($result < 0) {
468
            throw new RestException(404, 'Thirdparty ' . $id . ' not found');
469
        }
470
471
        if (empty($result)) {
472
            throw new RestException(500, 'Error fetching thirdparty ' . $id, array_merge(array($this->company->error), $this->company->errors));
473
        }
474
475
        if (empty(DolibarrApi::_checkAccessToResource('societe', $this->company->id))) {
476
            throw new RestException(403, 'Access to thirdparty ' . $id . ' not allowed for login ' . DolibarrApiAccess::$user->login);
477
        }
478
479
        $result = $this->company->setPriceLevel($priceLevel, DolibarrApiAccess::$user);
480
        if ($result <= 0) {
481
            throw new RestException(500, 'Error setting new price level for thirdparty ' . $id, array($this->company->db->lasterror()));
482
        }
483
484
        return $this->_cleanObjectDatas($this->company);
485
    }
486
487
    /**
488
     * Add a customer representative to a thirdparty
489
     *
490
     * @param int       $id                 Id of thirdparty
491
     * @param int       $representative_id  Id of representative
492
     * @return int                          Return integer <=0 if KO, >0 if OK
493
     *
494
     * @url POST {id}/representative/{representative_id}
495
     *
496
     * @throws RestException 401 Access not allowed for your login
497
     * @throws RestException 404 User or Thirdparty not found
498
     */
499
    public function addRepresentative($id, $representative_id)
500
    {
501
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
502
            throw new RestException(403);
503
        }
504
        $result = $this->company->fetch($id);
505
        if (!$result) {
506
            throw new RestException(404, 'Thirdparty not found');
507
        }
508
        $usertmp = new User($this->db);
509
        $result = $usertmp->fetch($representative_id);
510
        if (!$result) {
511
            throw new RestException(404, 'User not found');
512
        }
513
        if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
514
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
515
        }
516
        $result = $this->company->add_commercial(DolibarrApiAccess::$user, $representative_id);
517
518
        return $result;
519
    }
520
521
    /**
522
     * Delete a customer representative to a thirdparty
523
     *
524
     * @param int       $id                 Id of thirdparty
525
     * @param int       $representative_id  Id of representative
526
     * @return int                          Return integer <=0 if KO, >0 if OK
527
     *
528
     * @url DELETE {id}/representative/{representative_id}
529
     *
530
     * @throws RestException 401 Access not allowed for your login
531
     * @throws RestException 404 User or Thirdparty not found
532
     */
533
    public function deleteRepresentative($id, $representative_id)
534
    {
535
        if (!DolibarrApiAccess::$user->hasRight('societe', 'supprimer')) {
536
            throw new RestException(403);
537
        }
538
        $result = $this->company->fetch($id);
539
        if (!$result) {
540
            throw new RestException(404, 'Thirdparty not found');
541
        }
542
        $usertmp = new User($this->db);
543
        $result = $usertmp->fetch($representative_id);
544
        if (!$result) {
545
            throw new RestException(404, 'User not found');
546
        }
547
        if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
548
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
549
        }
550
        $result = $this->company->del_commercial(DolibarrApiAccess::$user, $representative_id);
551
552
        return $result;
553
    }
554
555
    /**
556
     * Get customer categories for a thirdparty
557
     *
558
     * @param int       $id         ID of thirdparty
559
     * @param string    $sortfield  Sort field
560
     * @param string    $sortorder  Sort order
561
     * @param int       $limit      Limit for list
562
     * @param int       $page       Page number
563
     * @return array|void
564
     *
565
     * @url GET {id}/categories
566
     */
567
    public function getCategories($id, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0)
568
    {
569
        if (!DolibarrApiAccess::$user->hasRight('categorie', 'lire')) {
570
            throw new RestException(403);
571
        }
572
573
        $result = $this->company->fetch($id);
574
        if (!$result) {
575
            throw new RestException(404, 'Thirdparty not found');
576
        }
577
578
        $categories = new Categorie($this->db);
579
580
        $arrayofcateg = $categories->getListForItem($id, 'customer', $sortfield, $sortorder, $limit, $page);
581
582
        if (is_numeric($arrayofcateg) && $arrayofcateg < 0) {
583
            throw new RestException(503, 'Error when retrieve category list : ' . $categories->error);
584
        }
585
586
        if (is_numeric($arrayofcateg) && $arrayofcateg >= 0) {  // To fix a return of 0 instead of empty array of method getListForItem
587
            return array();
588
        }
589
590
        return $arrayofcateg;
591
    }
592
593
    /**
594
     * Add a customer category to a thirdparty
595
     *
596
     * @param int       $id             Id of thirdparty
597
     * @param int       $category_id    Id of category
598
     * @return Object|void
599
     *
600
     * @url PUT {id}/categories/{category_id}
601
     */
602
    public function addCategory($id, $category_id)
603
    {
604
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
605
            throw new RestException(403);
606
        }
607
608
        $result = $this->company->fetch($id);
609
        if (!$result) {
610
            throw new RestException(404, 'Thirdparty not found');
611
        }
612
        $category = new Categorie($this->db);
613
        $result = $category->fetch($category_id);
614
        if (!$result) {
615
            throw new RestException(404, 'category not found');
616
        }
617
618
        if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
619
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
620
        }
621
        if (!DolibarrApi::_checkAccessToResource('category', $category->id)) {
622
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
623
        }
624
625
        $category->add_type($this->company, 'customer');
626
627
        return $this->_cleanObjectDatas($this->company);
628
    }
629
630
    /**
631
     * Remove the link between a customer category and the thirdparty
632
     *
633
     * @param int       $id             Id of thirdparty
634
     * @param int       $category_id    Id of category
635
     *
636
     * @return Object|void
637
     *
638
     * @url DELETE {id}/categories/{category_id}
639
     */
640
    public function deleteCategory($id, $category_id)
641
    {
642
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
643
            throw new RestException(403);
644
        }
645
646
        $result = $this->company->fetch($id);
647
        if (!$result) {
648
            throw new RestException(404, 'Thirdparty not found');
649
        }
650
        $category = new Categorie($this->db);
651
        $result = $category->fetch($category_id);
652
        if (!$result) {
653
            throw new RestException(404, 'category not found');
654
        }
655
656
        if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
657
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
658
        }
659
        if (!DolibarrApi::_checkAccessToResource('category', $category->id)) {
660
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
661
        }
662
663
        $category->del_type($this->company, 'customer');
664
665
        return $this->_cleanObjectDatas($this->company);
666
    }
667
668
    /**
669
     * Get supplier categories for a thirdparty
670
     *
671
     * @param int       $id         ID of thirdparty
672
     * @param string    $sortfield  Sort field
673
     * @param string    $sortorder  Sort order
674
     * @param int       $limit      Limit for list
675
     * @param int       $page       Page number
676
     *
677
     * @return mixed
678
     *
679
     * @url GET {id}/supplier_categories
680
     */
681
    public function getSupplierCategories($id, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0)
682
    {
683
        if (!DolibarrApiAccess::$user->hasRight('categorie', 'lire')) {
684
            throw new RestException(403);
685
        }
686
687
        $result = $this->company->fetch($id);
688
        if (!$result) {
689
            throw new RestException(404, 'Thirdparty not found');
690
        }
691
692
        $categories = new Categorie($this->db);
693
694
        $result = $categories->getListForItem($id, 'supplier', $sortfield, $sortorder, $limit, $page);
695
696
        if (is_numeric($result) && $result < 0) {
697
            throw new RestException(503, 'Error when retrieve category list : ' . $categories->error);
698
        }
699
700
        if (is_numeric($result) && $result == 0) {  // To fix a return of 0 instead of empty array of method getListForItem
701
            return array();
702
        }
703
704
        return $result;
705
    }
706
707
    /**
708
     * Add a supplier category to a thirdparty
709
     *
710
     * @param int       $id             Id of thirdparty
711
     * @param int       $category_id    Id of category
712
     *
713
     * @return mixed
714
     *
715
     * @url PUT {id}/supplier_categories/{category_id}
716
     */
717
    public function addSupplierCategory($id, $category_id)
718
    {
719
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
720
            throw new RestException(403);
721
        }
722
723
        $result = $this->company->fetch($id);
724
        if (!$result) {
725
            throw new RestException(404, 'Thirdparty not found');
726
        }
727
        $category = new Categorie($this->db);
728
        $result = $category->fetch($category_id);
729
        if (!$result) {
730
            throw new RestException(404, 'category not found');
731
        }
732
733
        if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
734
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
735
        }
736
        if (!DolibarrApi::_checkAccessToResource('category', $category->id)) {
737
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
738
        }
739
740
        $category->add_type($this->company, 'supplier');
741
742
        return $this->_cleanObjectDatas($this->company);
743
    }
744
745
    /**
746
     * Remove the link between a category and the thirdparty
747
     *
748
     * @param int       $id             Id of thirdparty
749
     * @param int       $category_id    Id of category
750
     *
751
     * @return mixed
752
     *
753
     * @url DELETE {id}/supplier_categories/{category_id}
754
     */
755
    public function deleteSupplierCategory($id, $category_id)
756
    {
757
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
758
            throw new RestException(403);
759
        }
760
761
        $result = $this->company->fetch($id);
762
        if (!$result) {
763
            throw new RestException(404, 'Thirdparty not found');
764
        }
765
        $category = new Categorie($this->db);
766
        $result = $category->fetch($category_id);
767
        if (!$result) {
768
            throw new RestException(404, 'category not found');
769
        }
770
771
        if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
772
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
773
        }
774
        if (!DolibarrApi::_checkAccessToResource('category', $category->id)) {
775
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
776
        }
777
778
        $category->del_type($this->company, 'supplier');
779
780
        return $this->_cleanObjectDatas($this->company);
781
    }
782
783
784
    /**
785
     * Get outstanding proposals of thirdparty
786
     *
787
     * @param   int     $id         ID of the thirdparty
788
     * @param   string  $mode       'customer' or 'supplier'
789
     *
790
     * @url     GET {id}/outstandingproposals
791
     *
792
     * @return array                List of outstandings proposals of thirdparty
793
     *
794
     * @throws RestException 400
795
     * @throws RestException 401
796
     * @throws RestException 404
797
     */
798
    public function getOutStandingProposals($id, $mode = 'customer')
799
    {
800
        if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
801
            throw new RestException(403);
802
        }
803
804
        if (empty($id)) {
805
            throw new RestException(400, 'Thirdparty ID is mandatory');
806
        }
807
808
        if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
809
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
810
        }
811
812
        $result = $this->company->fetch($id);
813
        if (!$result) {
814
            throw new RestException(404, 'Thirdparty not found');
815
        }
816
817
        $result = $this->company->getOutstandingProposals($mode);
818
819
        unset($result['total_ht']);
820
        unset($result['total_ttc']);
821
822
        return $result;
823
    }
824
825
826
    /**
827
     * Get outstanding orders of thirdparty
828
     *
829
     * @param   int     $id         ID of the thirdparty
830
     * @param   string  $mode       'customer' or 'supplier'
831
     *
832
     * @url     GET {id}/outstandingorders
833
     *
834
     * @return array                List of outstandings orders of thirdparty
835
     *
836
     * @throws RestException 400
837
     * @throws RestException 401
838
     * @throws RestException 404
839
     */
840
    public function getOutStandingOrder($id, $mode = 'customer')
841
    {
842
        if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
843
            throw new RestException(403);
844
        }
845
846
        if (empty($id)) {
847
            throw new RestException(400, 'Thirdparty ID is mandatory');
848
        }
849
850
        if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
851
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
852
        }
853
854
        $result = $this->company->fetch($id);
855
        if (!$result) {
856
            throw new RestException(404, 'Thirdparty not found');
857
        }
858
859
        $result = $this->company->getOutstandingOrders($mode);
860
861
        unset($result['total_ht']);
862
        unset($result['total_ttc']);
863
864
        return $result;
865
    }
866
867
    /**
868
     * Get outstanding invoices of thirdparty
869
     *
870
     * @param   int     $id         ID of the thirdparty
871
     * @param   string  $mode       'customer' or 'supplier'
872
     *
873
     * @url     GET {id}/outstandinginvoices
874
     *
875
     * @return array                List of outstandings invoices of thirdparty
876
     *
877
     * @throws RestException 400
878
     * @throws RestException 401
879
     * @throws RestException 404
880
     */
881
    public function getOutStandingInvoices($id, $mode = 'customer')
882
    {
883
        if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
884
            throw new RestException(403);
885
        }
886
887
        if (empty($id)) {
888
            throw new RestException(400, 'Thirdparty ID is mandatory');
889
        }
890
891
        if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
892
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
893
        }
894
895
        $result = $this->company->fetch($id);
896
        if (!$result) {
897
            throw new RestException(404, 'Thirdparty not found');
898
        }
899
900
        $result = $this->company->getOutstandingBills($mode);
901
902
        unset($result['total_ht']);
903
        unset($result['total_ttc']);
904
905
        return $result;
906
    }
907
908
    /**
909
     * Get representatives of thirdparty
910
     *
911
     * @param   int     $id         ID of the thirdparty
912
     * @param   int     $mode       0=Array with properties, 1=Array of id.
913
     *
914
     * @url     GET {id}/representatives
915
     *
916
     * @return array                List of representatives of thirdparty
917
     *
918
     * @throws RestException 400
919
     * @throws RestException 401
920
     * @throws RestException 404
921
     */
922
    public function getSalesRepresentatives($id, $mode = 0)
923
    {
924
        if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
925
            throw new RestException(403);
926
        }
927
928
        if (empty($id)) {
929
            throw new RestException(400, 'Thirdparty ID is mandatory');
930
        }
931
932
        if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
933
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
934
        }
935
936
        $result = $this->company->fetch($id);
937
        if (!$result) {
938
            throw new RestException(404, 'Thirdparty not found');
939
        }
940
941
        $result = $this->company->getSalesRepresentatives(DolibarrApiAccess::$user, $mode);
942
943
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result also could return the type integer which is incompatible with the documented return type array.
Loading history...
944
    }
945
946
    /**
947
     * Get fixed amount discount of a thirdparty (all sources: deposit, credit note, commercial offers...)
948
     *
949
     * @param   int     $id             ID of the thirdparty
950
     * @param   string  $filter     Filter exceptional discount. "none" will return every discount, "available" returns unapplied discounts, "used" returns applied discounts   {@choice none,available,used}
951
     * @param   string  $sortfield      Sort field
952
     * @param   string  $sortorder      Sort order
953
     *
954
     * @url     GET {id}/fixedamountdiscounts
955
     *
956
     * @return array  List of fixed discount of thirdparty
957
     *
958
     * @throws RestException 400
959
     * @throws RestException 401
960
     * @throws RestException 404
961
     * @throws RestException 503
962
     */
963
    public function getFixedAmountDiscounts($id, $filter = "none", $sortfield = "f.type", $sortorder = 'ASC')
964
    {
965
        $obj_ret = array();
966
967
        if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
968
            throw new RestException(403);
969
        }
970
971
        if (empty($id)) {
972
            throw new RestException(400, 'Thirdparty ID is mandatory');
973
        }
974
975
        if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
976
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
977
        }
978
979
        $result = $this->company->fetch($id);
980
        if (!$result) {
981
            throw new RestException(404, 'Thirdparty not found');
982
        }
983
984
985
        $sql = "SELECT f.ref, f.type as factype, re.fk_facture_source, re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc, re.description, re.fk_facture, re.fk_facture_line";
986
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_remise_except as re, " . MAIN_DB_PREFIX . "facture as f";
987
        $sql .= " WHERE f.rowid = re.fk_facture_source AND re.fk_soc = " . ((int) $id);
988
        if ($filter == "available") {
989
            $sql .= " AND re.fk_facture IS NULL AND re.fk_facture_line IS NULL";
990
        }
991
        if ($filter == "used") {
992
            $sql .= " AND (re.fk_facture IS NOT NULL OR re.fk_facture_line IS NOT NULL)";
993
        }
994
995
        $sql .= $this->db->order($sortfield, $sortorder);
996
997
        $result = $this->db->query($sql);
998
        if (!$result) {
999
            throw new RestException(503, $this->db->lasterror());
1000
        } else {
1001
            $num = $this->db->num_rows($result);
1002
            while ($obj = $this->db->fetch_object($result)) {
1003
                $obj_ret[] = $obj;
1004
            }
1005
        }
1006
1007
        return $obj_ret;
1008
    }
1009
1010
1011
1012
    /**
1013
     * Return list of invoices qualified to be replaced by another invoice.
1014
     *
1015
     * @param int   $id             Id of thirdparty
1016
     *
1017
     * @url     GET {id}/getinvoicesqualifiedforreplacement
1018
     *
1019
     * @return array
1020
     * @throws RestException 400
1021
     * @throws RestException 401
1022
     * @throws RestException 404
1023
     * @throws RestException 405
1024
     */
1025
    public function getInvoicesQualifiedForReplacement($id)
1026
    {
1027
        if (!DolibarrApiAccess::$user->hasRight('facture', 'lire')) {
1028
            throw new RestException(403);
1029
        }
1030
        if (empty($id)) {
1031
            throw new RestException(400, 'Thirdparty ID is mandatory');
1032
        }
1033
1034
        if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1035
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
1036
        }
1037
1038
        /*$result = $this->thirdparty->fetch($id);
1039
         if( ! $result ) {
1040
         throw new RestException(404, 'Thirdparty not found');
1041
         }*/
1042
1043
        $invoice = new Facture($this->db);
1044
        $result = $invoice->list_replacable_invoices($id);
1045
        if ($result < 0) {
1046
            throw new RestException(405, $invoice->error);
1047
        }
1048
1049
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result also could return the type integer which is incompatible with the documented return type array.
Loading history...
1050
    }
1051
1052
    /**
1053
     * Return list of invoices qualified to be corrected by a credit note.
1054
     * Invoices matching the following rules are returned
1055
     * (validated + payment on process) or classified (paid completely or paid partially) + not already replaced + not already a credit note
1056
     *
1057
     * @param int   $id             Id of thirdparty
1058
     *
1059
     * @url     GET {id}/getinvoicesqualifiedforcreditnote
1060
     *
1061
     * @return array
1062
     *
1063
     * @throws RestException 400
1064
     * @throws RestException 401
1065
     * @throws RestException 404
1066
     * @throws RestException 405
1067
     */
1068
    public function getInvoicesQualifiedForCreditNote($id)
1069
    {
1070
        if (!DolibarrApiAccess::$user->hasRight('facture', 'lire')) {
1071
            throw new RestException(403);
1072
        }
1073
        if (empty($id)) {
1074
            throw new RestException(400, 'Thirdparty ID is mandatory');
1075
        }
1076
1077
        if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1078
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
1079
        }
1080
1081
        /*$result = $this->thirdparty->fetch($id);
1082
         if( ! $result ) {
1083
         throw new RestException(404, 'Thirdparty not found');
1084
         }*/
1085
1086
        $invoice = new Facture($this->db);
1087
        $result = $invoice->list_qualified_avoir_invoices($id);
1088
        if ($result < 0) {
1089
            throw new RestException(405, $invoice->error);
1090
        }
1091
1092
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result also could return the type integer which is incompatible with the documented return type array.
Loading history...
1093
    }
1094
1095
    /**
1096
     * Get CompanyNotification objects for thirdparty
1097
     *
1098
     * @param int $id ID of thirdparty
1099
     *
1100
     * @return array
1101
     *
1102
     * @url GET {id}/notifications
1103
     */
1104
    public function getCompanyNotification($id)
1105
    {
1106
        if (empty($id)) {
1107
            throw new RestException(400, 'Thirdparty ID is mandatory');
1108
        }
1109
        if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
1110
            throw new RestException(403);
1111
        }
1112
        if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1113
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
1114
        }
1115
1116
        /**
1117
         * We select all the records that match the socid
1118
         */
1119
1120
        $sql = "SELECT rowid as id, fk_action, fk_action as event, fk_soc, fk_soc as socid, fk_contact, fk_contact as target, type, datec, tms";
1121
        $sql .= " FROM " . MAIN_DB_PREFIX . "notify_def";
1122
        if ($id) {
1123
            $sql .= " WHERE fk_soc  = " . ((int) $id);
1124
        }
1125
1126
        $result = $this->db->query($sql);
1127
        if ($this->db->num_rows($result) == 0) {
1128
            throw new RestException(404, 'Notification not found');
1129
        }
1130
1131
        $i = 0;
1132
1133
        $notifications = array();
1134
1135
        if ($result) {
1136
            $num = $this->db->num_rows($result);
1137
            while ($i < $num) {
1138
                $obj = $this->db->fetch_object($result);
1139
                $notifications[] = $obj;
1140
                $i++;
1141
            }
1142
        } else {
1143
            throw new RestException(404, 'No notifications found');
1144
        }
1145
1146
        $fields = array('id', 'socid', 'fk_soc', 'fk_action', 'event', 'fk_contact', 'target', 'datec', 'tms', 'type');
1147
1148
        $returnNotifications = array();
1149
1150
        foreach ($notifications as $notification) {
1151
            $object = array();
1152
            foreach ($notification as $key => $value) {
1153
                if (in_array($key, $fields)) {
1154
                    $object[$key] = $value;
1155
                }
1156
            }
1157
            $returnNotifications[] = $object;
1158
        }
1159
1160
        return $returnNotifications;
1161
    }
1162
1163
    /**
1164
     * Create CompanyNotification object for thirdparty
1165
     * @param int  $id ID of thirdparty
1166
     * @param array $request_data Request data
1167
     *
1168
     * @return array|mixed  Notification of thirdparty
1169
     *
1170
     * @url POST {id}/notifications
1171
     */
1172
    public function createCompanyNotification($id, $request_data = null)
1173
    {
1174
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1175
            throw new RestException(403, "User has no right to update thirdparties");
1176
        }
1177
        if ($this->company->fetch($id) <= 0) {
1178
            throw new RestException(404, 'Error creating Thirdparty Notification, Thirdparty doesn\'t exists');
1179
        }
1180
        $notification = new Notify($this->db);
1181
1182
        $notification->socid = $id;
1183
1184
        foreach ($request_data as $field => $value) {
1185
            $notification->$field = $value;
1186
        }
1187
1188
        if ($notification->create(DolibarrApiAccess::$user) < 0) {
1189
            throw new RestException(500, 'Error creating Thirdparty Notification');
1190
        }
1191
1192
        if ($notification->update(DolibarrApiAccess::$user) < 0) {
1193
            throw new RestException(500, 'Error updating values');
1194
        }
1195
1196
        return $this->_cleanObjectDatas($notification);
1197
    }
1198
1199
    /**
1200
     * Delete a CompanyNotification attached to a thirdparty
1201
     *
1202
     * @param int $id ID of thirdparty
1203
     * @param int $notification_id ID of CompanyNotification
1204
     *
1205
     * @return int -1 if error 1 if correct deletion
1206
     *
1207
     * @url DELETE {id}/notifications/{notification_id}
1208
     */
1209
    public function deleteCompanyNotification($id, $notification_id)
1210
    {
1211
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1212
            throw new RestException(403);
1213
        }
1214
1215
        $notification = new Notify($this->db);
1216
1217
        $notification->fetch($notification_id);
1218
1219
        $socid = (int) $notification->socid;
1220
1221
        if ($socid == $id) {
1222
            return $notification->delete(DolibarrApiAccess::$user);
1223
        } else {
1224
            throw new RestException(403, "Not allowed due to bad consistency of input data");
1225
        }
1226
    }
1227
1228
    /**
1229
     * Update CompanyNotification object for thirdparty
1230
     *
1231
     * @param int $id ID of thirdparty
1232
     * @param int  $notification_id ID of CompanyNotification
1233
     * @param array $request_data Request data
1234
     *
1235
     * @return array|mixed  Notification of thirdparty
1236
     *
1237
     * @url PUT {id}/notifications/{notification_id}
1238
     */
1239
    public function updateCompanyNotification($id, $notification_id, $request_data = null)
1240
    {
1241
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1242
            throw new RestException(403, "User has no right to update thirdparties");
1243
        }
1244
        if ($this->company->fetch($id) <= 0) {
1245
            throw new RestException(404, 'Error creating Company Notification, Company doesn\'t exists');
1246
        }
1247
        $notification = new Notify($this->db);
1248
1249
        // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1250
        $notification->fetch($notification_id, $id);
1251
1252
        if ($notification->socid != $id) {
1253
            throw new RestException(403, "Not allowed due to bad consistency of input data");
1254
        }
1255
1256
        foreach ($request_data as $field => $value) {
1257
            $notification->$field = $value;
1258
        }
1259
1260
        if ($notification->update(DolibarrApiAccess::$user) < 0) {
1261
            throw new RestException(500, 'Error updating values');
1262
        }
1263
1264
        return $this->_cleanObjectDatas($notification);
1265
    }
1266
1267
    /**
1268
     * Get CompanyBankAccount objects for thirdparty
1269
     *
1270
     * @param int $id ID of thirdparty
1271
     *
1272
     * @return array
1273
     *
1274
     * @url GET {id}/bankaccounts
1275
     */
1276
    public function getCompanyBankAccount($id)
1277
    {
1278
        if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
1279
            throw new RestException(403);
1280
        }
1281
        if (empty($id)) {
1282
            throw new RestException(400, 'Thirdparty ID is mandatory');
1283
        }
1284
1285
        if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1286
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
1287
        }
1288
1289
        /**
1290
         * We select all the records that match the socid
1291
         */
1292
1293
        $sql = "SELECT rowid, fk_soc, bank, number, code_banque, code_guichet, cle_rib, bic, iban_prefix as iban, domiciliation as address, proprio,";
1294
        $sql .= " owner_address, default_rib, label, datec, tms as datem, rum, frstrecur";
1295
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_rib";
1296
        if ($id) {
1297
            $sql .= " WHERE fk_soc  = " . ((int) $id);
1298
        }
1299
1300
        $result = $this->db->query($sql);
1301
1302
        if ($this->db->num_rows($result) == 0) {
1303
            throw new RestException(404, 'Account not found');
1304
        }
1305
1306
        $i = 0;
1307
1308
        $accounts = array();
1309
1310
        if ($result) {
1311
            $num = $this->db->num_rows($result);
1312
            while ($i < $num) {
1313
                $obj = $this->db->fetch_object($result);
1314
                $account = new CompanyBankAccount($this->db);
1315
                if ($account->fetch($obj->rowid)) {
1316
                    $accounts[] = $account;
1317
                }
1318
                $i++;
1319
            }
1320
        } else {
1321
            throw new RestException(404, 'Account not found');
1322
        }
1323
1324
1325
        $fields = array('socid', 'default_rib', 'frstrecur', '1000110000001', 'datec', 'datem', 'label', 'bank', 'bic', 'iban', 'id', 'rum');
1326
1327
        $returnAccounts = array();
1328
1329
        foreach ($accounts as $account) {
1330
            $object = array();
1331
            foreach ($account as $key => $value) {
1332
                if (in_array($key, $fields)) {
1333
                    $object[$key] = $value;
1334
                }
1335
            }
1336
            $returnAccounts[] = $object;
1337
        }
1338
1339
        return $returnAccounts;
1340
    }
1341
1342
    /**
1343
     * Create CompanyBankAccount object for thirdparty
1344
     * @param int  $id ID of thirdparty
1345
     * @param array $request_data Request data
1346
     *
1347
     * @return array|mixed  BankAccount of thirdparty
1348
     *
1349
     * @url POST {id}/bankaccounts
1350
     */
1351
    public function createCompanyBankAccount($id, $request_data = null)
1352
    {
1353
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1354
            throw new RestException(403);
1355
        }
1356
        if ($this->company->fetch($id) <= 0) {
1357
            throw new RestException(404, 'Error creating Company Bank account, Company doesn\'t exists');
1358
        }
1359
        $account = new CompanyBankAccount($this->db);
1360
1361
        $account->socid = $id;
1362
1363
        foreach ($request_data as $field => $value) {
1364
            if ($field === 'caller') {
1365
                // 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
1366
                $this->company->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
1367
                continue;
1368
            }
1369
1370
            $account->$field = $this->_checkValForAPI('extrafields', $value, $account);
1371
        }
1372
1373
        if ($account->create(DolibarrApiAccess::$user) < 0) {
1374
            throw new RestException(500, 'Error creating Company Bank account');
1375
        }
1376
1377
        if (empty($account->rum)) {
1378
            require_once constant('DOL_DOCUMENT_ROOT') . '/compta/prelevement/class/bonprelevement.class.php';
1379
            $prelevement = new BonPrelevement($this->db);
1380
            $account->rum = $prelevement->buildRumNumber($this->company->code_client, $account->datec, $account->id);
1381
            $account->date_rum = dol_now();
1382
        }
1383
1384
        if ($account->update(DolibarrApiAccess::$user) < 0) {
1385
            throw new RestException(500, 'Error updating values');
1386
        }
1387
1388
        return $this->_cleanObjectDatas($account);
1389
    }
1390
1391
    /**
1392
     * Update CompanyBankAccount object for thirdparty
1393
     *
1394
     * @param int $id ID of thirdparty
1395
     * @param int  $bankaccount_id ID of CompanyBankAccount
1396
     * @param array $request_data Request data
1397
     *
1398
     * @return array|mixed  BankAccount of thirdparty
1399
     *
1400
     * @url PUT {id}/bankaccounts/{bankaccount_id}
1401
     */
1402
    public function updateCompanyBankAccount($id, $bankaccount_id, $request_data = null)
1403
    {
1404
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1405
            throw new RestException(403);
1406
        }
1407
        if ($this->company->fetch($id) <= 0) {
1408
            throw new RestException(404, 'Error creating Company Bank account, Company doesn\'t exists');
1409
        }
1410
        $account = new CompanyBankAccount($this->db);
1411
1412
        // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1413
        $account->fetch($bankaccount_id, '', $id, -1, '');
1414
1415
        if ($account->socid != $id) {
1416
            throw new RestException(403);
1417
        }
1418
1419
1420
        foreach ($request_data as $field => $value) {
1421
            if ($field === 'caller') {
1422
                // 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
1423
                $account->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
1424
                continue;
1425
            }
1426
1427
            $account->$field = $this->_checkValForAPI($field, $value, $account);
1428
        }
1429
1430
        if (empty($account->rum)) {
1431
            require_once constant('DOL_DOCUMENT_ROOT') . '/compta/prelevement/class/bonprelevement.class.php';
1432
            $prelevement = new BonPrelevement($this->db);
1433
            $account->rum = $prelevement->buildRumNumber($this->company->code_client, $account->datec, $account->id);
1434
            $account->date_rum = dol_now();
1435
        }
1436
1437
        if ($account->update(DolibarrApiAccess::$user) < 0) {
1438
            throw new RestException(500, 'Error updating values');
1439
        }
1440
1441
        return $this->_cleanObjectDatas($account);
1442
    }
1443
1444
    /**
1445
     * Delete a bank account attached to a thirdparty
1446
     *
1447
     * @param int $id ID of thirdparty
1448
     * @param int $bankaccount_id ID of CompanyBankAccount
1449
     *
1450
     * @return int -1 if error 1 if correct deletion
1451
     *
1452
     * @url DELETE {id}/bankaccounts/{bankaccount_id}
1453
     */
1454
    public function deleteCompanyBankAccount($id, $bankaccount_id)
1455
    {
1456
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1457
            throw new RestException(403);
1458
        }
1459
1460
        $account = new CompanyBankAccount($this->db);
1461
1462
        $account->fetch($bankaccount_id);
1463
1464
        $socid = (int) $account->socid;
1465
1466
        if ($socid == $id) {
1467
            return $account->delete(DolibarrApiAccess::$user);
1468
        } else {
1469
            throw new RestException(403, "Not allowed due to bad consistency of input data");
1470
        }
1471
    }
1472
1473
    /**
1474
     * Generate a Document from a bank account record (like SEPA mandate)
1475
     *
1476
     * @param int       $id             Thirdparty id
1477
     * @param int       $companybankid  Companybank id
1478
     * @param string    $model          Model of document to generate
1479
     * @return array
1480
     *
1481
     * @url GET {id}/generateBankAccountDocument/{companybankid}/{model}
1482
     */
1483
    public function generateBankAccountDocument($id, $companybankid = null, $model = 'sepamandate')
1484
    {
1485
        global $conf, $langs;
1486
1487
        $langs->loadLangs(array("main", "dict", "commercial", "products", "companies", "banks", "bills", "withdrawals"));
1488
1489
        if ($this->company->fetch($id) <= 0) {
1490
            throw new RestException(404, 'Thirdparty not found');
1491
        }
1492
1493
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1494
            throw new RestException(403);
1495
        }
1496
1497
        $this->company->setDocModel(DolibarrApiAccess::$user, $model);
1498
1499
        $this->company->fk_bank = $this->company->fk_account;
1500
        // $this->company->fk_account = $this->company->fk_account;
1501
1502
        $outputlangs = $langs;
1503
        $newlang = '';
1504
1505
        //if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09');
1506
        if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1507
            if (isset($this->company->thirdparty->default_lang)) {
1508
                $newlang = $this->company->thirdparty->default_lang; // for proposal, order, invoice, ...
1509
            } elseif (isset($this->company->default_lang)) {
1510
                $newlang = $this->company->default_lang; // for thirdparty
1511
            }
1512
        }
1513
        if (!empty($newlang)) {
1514
            $outputlangs = new Translate("", $conf);
1515
            $outputlangs->setDefaultLang($newlang);
1516
        }
1517
1518
        $sql = "SELECT rowid";
1519
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_rib";
1520
        if ($id) {
1521
            $sql .= " WHERE fk_soc = " . ((int) $id);
1522
        }
1523
        if ($companybankid) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $companybankid of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1524
            $sql .= " AND rowid = " . ((int) $companybankid);
1525
        }
1526
1527
        $i = 0;
1528
        $accounts = array();
1529
1530
        $result = $this->db->query($sql);
1531
        if ($result) {
1532
            if ($this->db->num_rows($result) == 0) {
1533
                throw new RestException(404, 'Bank account not found');
1534
            }
1535
1536
            $num = $this->db->num_rows($result);
1537
            while ($i < $num) {
1538
                $obj = $this->db->fetch_object($result);
1539
1540
                $account = new CompanyBankAccount($this->db);
1541
                if ($account->fetch($obj->rowid)) {
1542
                    $accounts[] = $account;
1543
                }
1544
                $i++;
1545
            }
1546
        } else {
1547
            throw new RestException(500, 'Sql error ' . $this->db->lasterror());
1548
        }
1549
1550
        $moreparams = array(
1551
            'use_companybankid' => $accounts[0]->id,
1552
            'force_dir_output' => $conf->societe->multidir_output[$this->company->entity] . '/' . dol_sanitizeFileName($this->company->id)
1553
        );
1554
1555
        $result = $this->company->generateDocument($model, $outputlangs, 0, 0, 0, $moreparams);
1556
1557
        if ($result > 0) {
1558
            return array("success" => $result);
1559
        } else {
1560
            throw new RestException(500, 'Error generating the document ' . $this->company->error);
1561
        }
1562
    }
1563
1564
    /**
1565
     * Get a specific account attached to a thirdparty (by specifying the site key)
1566
     *
1567
     * @param int $id ID of thirdparty
1568
     * @param string $site Site key
1569
     *
1570
     * @return array|mixed
1571
     * @throws RestException 401 Unauthorized: User does not have permission to read thirdparties
1572
     * @throws RestException 404 Not Found: Specified thirdparty ID does not belongs to an existing thirdparty
1573
     *
1574
     * @url GET {id}/accounts/
1575
     */
1576
    public function getSocieteAccounts($id, $site = null)
1577
    {
1578
        if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
1579
            throw new RestException(403);
1580
        }
1581
1582
        if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1583
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
1584
        }
1585
1586
        /**
1587
         * We select all the records that match the socid
1588
         */
1589
        $sql = "SELECT rowid, fk_soc, key_account, site, date_creation, tms FROM " . MAIN_DB_PREFIX . "societe_account";
1590
        $sql .= " WHERE fk_soc = " . ((int) $id);
1591
        if ($site) {
1592
            $sql .= " AND site ='" . $this->db->escape($site) . "'";
1593
        }
1594
1595
        $result = $this->db->query($sql);
1596
1597
        if ($result && $this->db->num_rows($result) == 0) {
1598
            throw new RestException(404, 'This thirdparty does not have any account attached or does not exist.');
1599
        }
1600
1601
        $i = 0;
1602
1603
        $accounts = array();
1604
1605
        $num = $this->db->num_rows($result);
1606
        while ($i < $num) {
1607
            $obj = $this->db->fetch_object($result);
1608
            $account = new SocieteAccount($this->db);
1609
1610
            if ($account->fetch($obj->rowid)) {
1611
                $accounts[] = $account;
1612
            }
1613
            $i++;
1614
        }
1615
1616
        $fields = array('id', 'fk_soc', 'key_account', 'site', 'date_creation', 'tms');
1617
1618
        $returnAccounts = array();
1619
1620
        foreach ($accounts as $account) {
1621
            $object = array();
1622
            foreach ($account as $key => $value) {
1623
                if (in_array($key, $fields)) {
1624
                    $object[$key] = $value;
1625
                }
1626
            }
1627
            $returnAccounts[] = $object;
1628
        }
1629
1630
        return $returnAccounts;
1631
    }
1632
1633
    /**
1634
     * Create and attach a new account to an existing thirdparty
1635
     *
1636
     * Possible fields for request_data (request body) are specified in <code>llx_societe_account</code> table.<br>
1637
     * See <a href="https://wiki.dolibarr.org/index.php/Table_llx_societe_account">Table llx_societe_account</a> wiki page for more information<br><br>
1638
     * <u>Example body payload :</u> <pre>{"key_account": "cus_DAVkLSs1LYyYI", "site": "stripe"}</pre>
1639
     *
1640
     * @param int $id ID of thirdparty
1641
     * @param array $request_data Request data
1642
     *
1643
     * @return array|mixed
1644
     *
1645
     * @throws RestException 401 Unauthorized: User does not have permission to read thirdparties
1646
     * @throws RestException 409 Conflict: An Account already exists for this company and site.
1647
     * @throws RestException 422 Unprocessable Entity: You must pass the site attribute in your request data !
1648
     * @throws RestException 500 Internal Server Error: Error creating SocieteAccount account
1649
     *
1650
     * @url POST {id}/accounts
1651
     */
1652
    public function createSocieteAccount($id, $request_data = null)
1653
    {
1654
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1655
            throw new RestException(403);
1656
        }
1657
1658
        if (!isset($request_data['site'])) {
1659
            throw new RestException(422, 'Unprocessable Entity: You must pass the site attribute in your request data !');
1660
        }
1661
1662
        $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "societe_account WHERE fk_soc  = " . ((int) $id) . " AND site = '" . $this->db->escape($request_data['site']) . "'";
1663
        $result = $this->db->query($sql);
1664
1665
        if ($result && $this->db->num_rows($result) == 0) {
1666
            $account = new SocieteAccount($this->db);
1667
            if (!isset($request_data['login'])) {
1668
                $account->login = "";
1669
            }
1670
            $account->fk_soc = $id;
1671
1672
            foreach ($request_data as $field => $value) {
1673
                if ($field === 'caller') {
1674
                    // 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
1675
                    $account->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
1676
                    continue;
1677
                }
1678
1679
                $account->$field = $this->_checkValForAPI($field, $value, $account);
1680
            }
1681
1682
            if ($account->create(DolibarrApiAccess::$user) < 0) {
1683
                throw new RestException(500, 'Error creating SocieteAccount entity. Ensure that the ID of thirdparty provided does exist!');
1684
            }
1685
1686
            $this->_cleanObjectDatas($account);
1687
1688
            return $account;
1689
        } else {
1690
            throw new RestException(409, 'A SocieteAccount entity already exists for this company and site.');
1691
        }
1692
    }
1693
1694
    /**
1695
     * Create and attach a new (or replace an existing) specific site account to a thirdparty
1696
     *
1697
     * You <strong>MUST</strong> pass all values to keep (otherwise, they will be deleted) !<br>
1698
     * If you just need to update specific fields prefer <code>PATCH /thirdparties/{id}/accounts/{site}</code> endpoint.<br><br>
1699
     * When a <strong>SocieteAccount</strong> entity does not exist for the <code>id</code> and <code>site</code>
1700
     * supplied, a new one will be created. In that case <code>fk_soc</code> and <code>site</code> members form
1701
     * request body payload will be ignored and <code>id</code> and <code>site</code> query strings parameters
1702
     * will be used instead.
1703
     *
1704
     * @param int $id ID of thirdparty
1705
     * @param string $site Site key
1706
     * @param array $request_data Request data
1707
     *
1708
     * @return array|mixed
1709
     *
1710
     * @throws RestException 401 Unauthorized: User does not have permission to read thirdparties
1711
     * @throws RestException 422 Unprocessable Entity: You must pass the site attribute in your request data !
1712
     * @throws RestException 500 Internal Server Error: Error updating SocieteAccount entity
1713
     *
1714
     * @url PUT {id}/accounts/{site}
1715
     */
1716
    public function putSocieteAccount($id, $site, $request_data = null)
1717
    {
1718
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1719
            throw new RestException(403);
1720
        }
1721
1722
        $sql = "SELECT rowid, fk_user_creat, date_creation FROM " . MAIN_DB_PREFIX . "societe_account WHERE fk_soc = $id AND site = '" . $this->db->escape($site) . "'";
1723
        $result = $this->db->query($sql);
1724
1725
        // We do not found an existing SocieteAccount entity for this fk_soc and site ; we then create a new one.
1726
        if ($result && $this->db->num_rows == 0) {
1727
            if (!isset($request_data['key_account'])) {
1728
                throw new RestException(422, 'Unprocessable Entity: You must pass the key_account attribute in your request data !');
1729
            }
1730
            $account = new SocieteAccount($this->db);
1731
            if (!isset($request_data['login'])) {
1732
                $account->login = "";
1733
            }
1734
1735
            foreach ($request_data as $field => $value) {
1736
                if ($field === 'caller') {
1737
                    // 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
1738
                    $account->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
1739
                    continue;
1740
                }
1741
1742
                $account->$field = $this->_checkValForAPI($field, $value, $account);
1743
            }
1744
1745
            $account->fk_soc = $id;
1746
            $account->site = $site;
1747
1748
            if ($account->create(DolibarrApiAccess::$user) < 0) {
1749
                throw new RestException(500, 'Error creating SocieteAccount entity.');
1750
            }
1751
            // We found an existing SocieteAccount entity, we are replacing it
1752
        } else {
1753
            if (isset($request_data['site']) && $request_data['site'] !== $site) {
1754
                $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "societe_account WHERE fk_soc  = " . ((int) $id) . " AND site = '" . $this->db->escape($request_data['site']) . "' ";
1755
                $result = $this->db->query($sql);
1756
1757
                if ($result && $this->db->num_rows($result) !== 0) {
1758
                    throw new RestException(409, "You are trying to update this thirdparty Account for $site to " . $request_data['site'] . " but another Account already exists with this site key.");
1759
                }
1760
            }
1761
1762
            $obj = $this->db->fetch_object($result);
1763
1764
            $account = new SocieteAccount($this->db);
1765
            $account->id = $obj->rowid;
1766
            $account->fk_soc = $id;
1767
            $account->site = $site;
1768
            if (!isset($request_data['login'])) {
1769
                $account->login = "";
1770
            }
1771
            $account->fk_user_creat = $obj->fk_user_creat;
1772
            $account->date_creation = $obj->date_creation;
1773
1774
            foreach ($request_data as $field => $value) {
1775
                if ($field === 'caller') {
1776
                    // 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
1777
                    $account->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
1778
                    continue;
1779
                }
1780
1781
                $account->$field = $this->_checkValForAPI($field, $value, $account);
1782
            }
1783
1784
            if ($account->update(DolibarrApiAccess::$user) < 0) {
1785
                throw new RestException(500, 'Error updating SocieteAccount entity.');
1786
            }
1787
        }
1788
1789
        $this->_cleanObjectDatas($account);
1790
1791
        return $account;
1792
    }
1793
1794
    /**
1795
     * Update specified values of a specific account attached to a thirdparty
1796
     *
1797
     * @param int       $id             Id of thirdparty
1798
     * @param string    $site           Site key
1799
     * @param array     $request_data   Request data
1800
     *
1801
     * @return array|mixed
1802
     *
1803
     * @throws RestException 401 Unauthorized: User does not have permission to read thirdparties
1804
     * @throws RestException 404 Not Found: Specified thirdparty ID does not belongs to an existing thirdparty
1805
     * @throws RestException 409 Conflict: Another SocieteAccount entity already exists for this thirdparty with this site key.
1806
     * @throws RestException 500 Internal Server Error: Error updating SocieteAccount entity
1807
     *
1808
     * @url PATCH {id}/accounts/{site}
1809
     */
1810
    public function patchSocieteAccount($id, $site, $request_data = null)
1811
    {
1812
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1813
            throw new RestException(403);
1814
        }
1815
1816
        $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "societe_account WHERE fk_soc = " . ((int) $id) . " AND site = '" . $this->db->escape($site) . "'";
1817
        $result = $this->db->query($sql);
1818
1819
        if ($result && $this->db->num_rows($result) == 0) {
1820
            throw new RestException(404, "This thirdparty does not have $site account attached or does not exist.");
1821
        } else {
1822
            // If the user tries to edit the site member, we check first if
1823
            if (isset($request_data['site']) && $request_data['site'] !== $site) {
1824
                $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "societe_account WHERE fk_soc  = " . ((int) $id) . " AND site = '" . $this->db->escape($request_data['site']) . "' ";
1825
                $result = $this->db->query($sql);
1826
1827
                if ($result && $this->db->num_rows($result) !== 0) {
1828
                    throw new RestException(409, "You are trying to update this thirdparty Account for " . $site . " to " . $request_data['site'] . " but another Account already exists for this thirdparty with this site key.");
1829
                }
1830
            }
1831
1832
            $obj = $this->db->fetch_object($result);
1833
            $account = new SocieteAccount($this->db);
1834
            $account->fetch($obj->rowid);
1835
1836
            foreach ($request_data as $field => $value) {
1837
                if ($field === 'caller') {
1838
                    // 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
1839
                    $account->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
1840
                    continue;
1841
                }
1842
1843
                $account->$field = $this->_checkValForAPI($field, $value, $account);
1844
            }
1845
1846
            if ($account->update(DolibarrApiAccess::$user) < 0) {
1847
                throw new RestException(500, 'Error updating SocieteAccount account');
1848
            }
1849
1850
            $this->_cleanObjectDatas($account);
1851
1852
            return $account;
1853
        }
1854
    }
1855
1856
    /**
1857
     * Delete a specific site account attached to a thirdparty (by account id)
1858
     *
1859
     * @param int $id ID of thirdparty
1860
     * @param int $site Site key
1861
     *
1862
     * @return void
1863
     * @throws RestException 401 Unauthorized: User does not have permission to delete thirdparties accounts
1864
     * @throws RestException 404 Not Found: Specified thirdparty ID does not belongs to an existing thirdparty
1865
     * @throws RestException 500 Internal Server Error: Error deleting SocieteAccount entity
1866
     *
1867
     * @url DELETE {id}/accounts/{site}
1868
     */
1869
    public function deleteSocieteAccount($id, $site)
1870
    {
1871
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1872
            throw new RestException(403);
1873
        }
1874
1875
        $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "societe_account WHERE fk_soc  = $id AND site = '" . $this->db->escape($site) . "'";
1876
        $result = $this->db->query($sql);
1877
1878
        if ($result && $this->db->num_rows($result) == 0) {
1879
            throw new RestException(404);
1880
        } else {
1881
            $obj = $this->db->fetch_object($result);
1882
            $account = new SocieteAccount($this->db);
1883
            $account->fetch($obj->rowid);
1884
1885
            if ($account->delete(DolibarrApiAccess::$user) < 0) {
1886
                throw new RestException(500, "Error while deleting $site account attached to this third party");
1887
            }
1888
        }
1889
    }
1890
1891
    /**
1892
     * Delete all accounts attached to a thirdparty
1893
     *
1894
     * @param int $id ID of thirdparty
1895
     *
1896
     * @return void
1897
     * @throws RestException 401 Unauthorized: User does not have permission to delete thirdparties accounts
1898
     * @throws RestException 404 Not Found: Specified thirdparty ID does not belongs to an existing thirdparty
1899
     * @throws RestException 500 Internal Server Error: Error deleting SocieteAccount entity
1900
     *
1901
     * @url DELETE {id}/accounts
1902
     */
1903
    public function deleteSocieteAccounts($id)
1904
    {
1905
        if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1906
            throw new RestException(403);
1907
        }
1908
1909
        /**
1910
         * We select all the records that match the socid
1911
         */
1912
1913
        $sql = "SELECT rowid, fk_soc, key_account, site, date_creation, tms";
1914
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_account WHERE fk_soc = " . ((int) $id);
1915
1916
        $result = $this->db->query($sql);
1917
1918
        if ($result && $this->db->num_rows($result) == 0) {
1919
            throw new RestException(404, 'This third party does not have any account attached or does not exist.');
1920
        } else {
1921
            $i = 0;
1922
1923
            $num = $this->db->num_rows($result);
1924
            while ($i < $num) {
1925
                $obj = $this->db->fetch_object($result);
1926
                $account = new SocieteAccount($this->db);
1927
                $account->fetch($obj->rowid);
1928
1929
                if ($account->delete(DolibarrApiAccess::$user) < 0) {
1930
                    throw new RestException(500, 'Error while deleting account attached to this third party');
1931
                }
1932
                $i++;
1933
            }
1934
        }
1935
    }
1936
1937
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1938
    /**
1939
     * Clean sensible object datas
1940
     *
1941
     * @param   Object  $object     Object to clean
1942
     * @return  Object              Object with cleaned properties
1943
     */
1944
    protected function _cleanObjectDatas($object)
1945
    {
1946
		// phpcs:enable
1947
        $object = parent::_cleanObjectDatas($object);
1948
1949
        unset($object->nom); // ->name already defined and nom deprecated
1950
        unset($object->name_bis); // ->name_alias already defined
1951
        unset($object->note); // ->note_private and note_public already defined
1952
        unset($object->departement);
1953
        unset($object->departement_code);
1954
        unset($object->pays);
1955
        unset($object->particulier);
1956
        unset($object->prefix_comm);
1957
1958
        unset($object->siren);
1959
        unset($object->siret);
1960
        unset($object->ape);
1961
1962
        unset($object->commercial_id); // This property is used in create/update only. It does not exists in read mode because there is several sales representatives.
1963
1964
        unset($object->total_ht);
1965
        unset($object->total_tva);
1966
        unset($object->total_localtax1);
1967
        unset($object->total_localtax2);
1968
        unset($object->total_ttc);
1969
1970
        unset($object->lines);
1971
        unset($object->thirdparty);
1972
1973
        unset($object->fk_delivery_address); // deprecated feature
1974
1975
        return $object;
1976
    }
1977
1978
    /**
1979
     * Validate fields before create or update object
1980
     *
1981
     * @param array $data   Datas to validate
1982
     * @return array
1983
     *
1984
     * @throws RestException
1985
     */
1986
    private function _validate($data)
1987
    {
1988
        $thirdparty = array();
1989
        foreach (Thirdparties::$FIELDS as $field) {
1990
            if (!isset($data[$field])) {
1991
                throw new RestException(400, "$field field missing");
1992
            }
1993
            $thirdparty[$field] = $data[$field];
1994
        }
1995
        return $thirdparty;
1996
    }
1997
1998
    /**
1999
     * Fetch properties of a thirdparty object.
2000
     *
2001
     * Return an array with thirdparty information
2002
     *
2003
     * @param    int    $rowid      Id of third party to load (Use 0 to get a specimen record, use null to use other search criteria)
2004
     * @param    string $ref        Reference of third party, name (Warning, this can return several records)
2005
     * @param    string $ref_ext    External reference of third party (Warning, this information is a free field not provided by Dolibarr)
2006
     * @param    string $barcode    Barcode of third party to load
2007
     * @param    string $idprof1        Prof id 1 of third party (Warning, this can return several records)
2008
     * @param    string $idprof2        Prof id 2 of third party (Warning, this can return several records)
2009
     * @param    string $idprof3        Prof id 3 of third party (Warning, this can return several records)
2010
     * @param    string $idprof4        Prof id 4 of third party (Warning, this can return several records)
2011
     * @param    string $idprof5        Prof id 5 of third party (Warning, this can return several records)
2012
     * @param    string $idprof6        Prof id 6 of third party (Warning, this can return several records)
2013
     * @param    string $email          Email of third party (Warning, this can return several records)
2014
     * @param    string $ref_alias  Name_alias of third party (Warning, this can return several records)
2015
     * @return object cleaned Societe object
2016
     *
2017
     * @throws RestException
2018
     */
2019
    private function _fetch($rowid, $ref = '', $ref_ext = '', $barcode = '', $idprof1 = '', $idprof2 = '', $idprof3 = '', $idprof4 = '', $idprof5 = '', $idprof6 = '', $email = '', $ref_alias = '')
2020
    {
2021
        global $conf;
2022
2023
        if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
2024
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login . '. No read permission on thirdparties.');
2025
        }
2026
2027
        if ($rowid === 0) {
2028
            $result = $this->company->initAsSpecimen();
2029
        } else {
2030
            $result = $this->company->fetch($rowid, $ref, $ref_ext, $barcode, $idprof1, $idprof2, $idprof3, $idprof4, $idprof5, $idprof6, $email, $ref_alias);
2031
        }
2032
        if (!$result) {
2033
            throw new RestException(404, 'Thirdparty not found');
2034
        }
2035
2036
        if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
2037
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login . ' on this thirdparty');
2038
        }
2039
        if (isModEnabled('mailing')) {
2040
            $this->company->getNoEmail();
2041
        }
2042
2043
        if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
2044
            $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
2045
            $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
2046
        } else {
2047
            $filterabsolutediscount = "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')";
2048
            $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')";
2049
        }
2050
2051
        $absolute_discount = $this->company->getAvailableDiscounts('', $filterabsolutediscount);
2052
        $absolute_creditnote = $this->company->getAvailableDiscounts('', $filtercreditnote);
2053
        $this->company->absolute_discount = price2num($absolute_discount, 'MT');
0 ignored issues
show
Bug Best Practice introduced by
The property absolute_discount does not exist on Dolibarr\Code\Societe\Classes\Societe. Since you implemented __set, consider adding a @property annotation.
Loading history...
2054
        $this->company->absolute_creditnote = price2num($absolute_creditnote, 'MT');
0 ignored issues
show
Bug Best Practice introduced by
The property absolute_creditnote does not exist on Dolibarr\Code\Societe\Classes\Societe. Since you implemented __set, consider adding a @property annotation.
Loading history...
2055
2056
        return $this->_cleanObjectDatas($this->company);
2057
    }
2058
}
2059