dolibarr 24.0.1
api_thirdparties.class.php
1<?php
2/* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
3 * Copyright (C) 2018 Pierre Chéné <pierre.chene44@gmail.com>
4 * Copyright (C) 2019 Cedric Ancelin <icedo.anc@gmail.com>
5 * Copyright (C) 2020-2025 Frédéric France <frederic.france@free.fr>
6 * Copyright (C) 2023 Alexandre Janniaux <alexandre.janniaux@gmail.com>
7 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
8 * Copyright (C) 2024 Jon Bendtsen <jon.bendtsen.github@jonb.dk>
9 * Copyright (C) 2025 William Mead <william@m34d.com>
10 * Copyright (C) 2025 Charlene Benke <charlene@patas-monkey.com>
11 * Copyright (C) 2026 Benjamin Falière <benjamin@faliere.com>
12 * Copyright (C) 2026 Noé Cendrier <noe.cendrier@altairis.fr>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27
28use Luracast\Restler\RestException;
29
39{
43 public static $FIELDS = array(
44 'name'
45 );
46
50 public $company;
51
55 public function __construct()
56 {
57 global $db;
58 $this->db = $db;
59
60 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
61 require_once DOL_DOCUMENT_ROOT.'/societe/class/societeaccount.class.php';
62 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
63 require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php';
64 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
65
66 $this->company = new Societe($this->db);
67
68 if (getDolGlobalString('SOCIETE_EMAIL_MANDATORY')) {
69 static::$FIELDS[] = 'email';
70 }
71 }
72
85 public function get($id)
86 {
87 return $this->_fetch($id);
88 }
89
106 public function getByEmail($email)
107 {
108 return $this->_fetch(null, '', '', '', '', '', '', '', '', '', $email);
109 }
110
125 public function getByBarcode($barcode)
126 {
127 return $this->_fetch(null, '', '', $barcode);
128 }
129
156 public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $mode = 0, $category = 0, $sqlfilters = '', $properties = '', $pagination_data = false)
157 {
158 $obj_ret = array();
159
160 if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
161 throw new RestException(403);
162 }
163
164 // case of external user, we force socids
165 $socids = DolibarrApiAccess::$user->socid ? (string) DolibarrApiAccess::$user->socid : '';
166
167 // If the internal user must only see his customers, force searching by him
168 $search_sale = 0;
169 if (!DolibarrApiAccess::$user->hasRight('societe', 'client', 'voir') && !$socids) {
170 $search_sale = DolibarrApiAccess::$user->id;
171 }
172
173 $sql = "SELECT t.rowid";
174 $sql .= " FROM ".MAIN_DB_PREFIX."societe as t";
175 $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
176 if ($category > 0) {
177 if ($mode != 4) {
178 $sql .= ", ".MAIN_DB_PREFIX."categorie_societe as c";
179 }
180 if (!in_array($mode, array(1, 2, 3))) {
181 $sql .= ", ".MAIN_DB_PREFIX."categorie_fournisseur as cc";
182 }
183 }
184 $sql .= " WHERE t.entity IN (".getEntity('societe').")";
185 if ($mode == 1) {
186 $sql .= " AND t.client IN (1, 3)";
187 } elseif ($mode == 2) {
188 $sql .= " AND t.client IN (2, 3)";
189 } elseif ($mode == 3) {
190 $sql .= " AND t.client IN (0)";
191 } elseif ($mode == 4) {
192 $sql .= " AND t.fournisseur IN (1)";
193 }
194 // Select third parties of a given category
195 if ($category > 0) {
196 if (!empty($mode) && $mode != 4) {
197 $sql .= " AND c.fk_categorie = ".((int) $category)." AND c.fk_soc = t.rowid";
198 } elseif (!empty($mode) && $mode == 4) {
199 $sql .= " AND cc.fk_categorie = ".((int) $category)." AND cc.fk_soc = t.rowid";
200 } else {
201 $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))";
202 }
203 }
204 if ($socids) {
205 $sql .= " AND t.rowid IN (".$this->db->sanitize($socids).")";
206 }
207 // Search on sale representative
208 if ($search_sale && $search_sale != '-1') {
209 if ($search_sale == -2) {
210 $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = t.rowid)";
211 } elseif ($search_sale > 0) {
212 $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).")";
213 }
214 }
215 // Add sql filters
216 if ($sqlfilters) {
217 $errormessage = '';
218 $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
219 if ($errormessage) {
220 throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
221 }
222 }
223
224 //this query will return total thirdparties with the filters given
225 $sqlTotals = str_replace('SELECT t.rowid', 'SELECT count(t.rowid) as total', $sql);
226
227 $sql .= $this->db->order($sortfield, $sortorder);
228 if ($limit) {
229 if ($page < 0) {
230 $page = 0;
231 }
232 $offset = $limit * $page;
233
234 $sql .= $this->db->plimit($limit + 1, $offset);
235 }
236
237 $result = $this->db->query($sql);
238 if ($result) {
239 $num = $this->db->num_rows($result);
240 $min = min($num, ($limit <= 0 ? $num : $limit));
241 $i = 0;
242 while ($i < $min) {
243 $obj = $this->db->fetch_object($result);
244 $soc_static = new Societe($this->db);
245 if ($soc_static->fetch($obj->rowid)) {
246 if (isModEnabled('mailing')) {
247 $soc_static->getNoEmail();
248 }
249 $obj_ret[] = $this->_filterObjectProperties($this->_cleanObjectDatas($soc_static), $properties);
250 }
251 $i++;
252 }
253 } else {
254 throw new RestException(503, 'Error when retrieve third parties : '.$this->db->lasterror());
255 }
256 if (!count($obj_ret)) {
257 $message = '';
258 switch ($mode) {
259 case 0:
260 $message = 'No third parties found';
261 break;
262 case 1:
263 $message = 'No customers found';
264 break;
265 case 2:
266 $message = 'No prospects found';
267 break;
268 case 3:
269 $message = 'No other third parties found';
270 break;
271 case 4:
272 $message = 'No suppliers found';
273 }
274 throw new RestException(404, $message);
275 }
276
277 //if $pagination_data is true, the response will contain element data with all values and element pagination with pagination data(total,page,limit)
278 if ($pagination_data) {
279 $totalsResult = $this->db->query($sqlTotals);
280 $total = $this->db->fetch_object($totalsResult)->total;
281
282 $tmp = $obj_ret;
283 $obj_ret = [];
284
285 $obj_ret['data'] = $tmp;
286 $obj_ret['pagination'] = [
287 'total' => (int) $total,
288 'page' => $page, //count starts from 0
289 'page_count' => ceil((int) $total / $limit),
290 'limit' => $limit
291 ];
292 }
293
294 return $obj_ret;
295 }
296
309 public function post($request_data = null)
310 {
311 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
312 throw new RestException(403);
313 }
314
315 // External api user does not know internal country ID
316 if (!isset($request_data['country_id']) && isset($request_data['country_code'])) {
317 $field = strlen($request_data['country_code']) > 2 ? 'code_iso' : 'code';
318 $id = dol_getIdFromCode($this->db, $request_data['country_code'], "c_country", $field, "rowid");
319 if ($id < 0) {
320 throw new RestException(404, 'Country code not found in database: ' . $this->db->error);
321 }
322 $request_data['country_id'] = $id;
323 }
324
325 // Check mandatory fields
326 $result = $this->_validate($request_data);
327
328 foreach ($request_data as $field => $value) {
329 if ($field === 'caller') {
330 // 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
331 $this->company->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
332 continue;
333 }
334 if ($field == 'array_options' && is_array($value)) {
335 $this->company->fetch_optionals(); // To force the load of the extrafields definition by fetch_name_optionals_label()
336
337 foreach ($value as $index => $val) {
338 $this->company->array_options[$index] = $this->_checkValExtrafieldsForAPI($index, $val, $this->company);
339 }
340 continue;
341 }
342
343 $this->company->$field = $this->_checkValForAPI($field, $value, $this->company);
344 }
345
346 if ($this->company->create(DolibarrApiAccess::$user) < 0) {
347 throw new RestException(500, 'Error creating thirdparty', array_merge(array($this->company->error), $this->company->errors));
348 }
349 if (isModEnabled('mailing') && !empty($this->company->email) && isset($this->company->no_email)) {
350 $this->company->setNoEmail($this->company->no_email);
351 }
352
353 return $this->company->id;
354 }
355
373 public function put($id, $request_data = null)
374 {
375 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
376 throw new RestException(403);
377 }
378
379 $result = $this->company->fetch($id);
380 if (!$result) {
381 throw new RestException(404, 'Thirdparty not found');
382 }
383
384 if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
385 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
386 }
387
388 foreach ($request_data as $field => $value) {
389 if ($field == 'id') {
390 continue;
391 }
392 if ($field === 'caller') {
393 // 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
394 $this->company->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
395 continue;
396 }
397 if ($field == 'array_options' && is_array($value)) {
398 foreach ($value as $index => $val) {
399 $this->company->array_options[$index] = $this->_checkValExtrafieldsForAPI($index, $val, $this->company);
400 }
401 continue;
402 }
403 $this->company->$field = $this->_checkValForAPI($field, $value, $this->company);
404 }
405
406 if (isModEnabled('mailing') && !empty($this->company->email) && isset($this->company->no_email)) {
407 $this->company->setNoEmail($this->company->no_email);
408 }
409
410 if ($this->company->update($id, DolibarrApiAccess::$user, 1, 1, 1, 'update', 1) > 0) {
411 return $this->get($id);
412 } else {
413 throw new RestException(500, $this->company->error);
414 }
415 }
416
438 public function merge($id, $idtodelete)
439 {
440 if ($id == $idtodelete) {
441 throw new RestException(400, 'Try to merge a thirdparty into itself');
442 }
443
444 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
445 throw new RestException(403);
446 }
447
448 $result = $this->company->fetch($id); // include the fetch of extra fields
449 if (!$result) {
450 throw new RestException(404, 'Thirdparty not found');
451 }
452
453 if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
454 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
455 }
456
457 $companytoremove = new Societe($this->db);
458 $result = $companytoremove->fetch($idtodelete); // include the fetch of extra fields
459 if (!$result) {
460 throw new RestException(404, 'Thirdparty not found');
461 }
462
463 if (!DolibarrApi::_checkAccessToResource('societe', $companytoremove->id)) {
464 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
465 }
466
467 $user = DolibarrApiAccess::$user;
468 $result = $this->company->mergeCompany($companytoremove->id);
469 if ($result < 0) {
470 throw new RestException(500, 'Error failed to merged thirdparty '.$companytoremove->id.' into '.$id.'. Enable and read log file for more information.');
471 }
472
473 return $this->get($id);
474 }
475
488 public function delete($id)
489 {
490 if (!DolibarrApiAccess::$user->hasRight('societe', 'supprimer')) {
491 throw new RestException(403);
492 }
493 $result = $this->company->fetch($id);
494 if (!$result) {
495 throw new RestException(404, 'Thirdparty not found');
496 }
497 if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
498 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
499 }
500 $this->company->oldcopy = clone $this->company; // @phan-suppress-current-line PhanTypeMismatchProperty
501
502 $res = $this->company->delete($id);
503 if ($res < 0) {
504 throw new RestException(500, "Can't delete, error occurs");
505 } elseif ($res == 0) {
506 throw new RestException(409, "Can't delete, that product is probably used");
507 }
508
509 return array(
510 'success' => array(
511 'code' => 200,
512 'message' => 'Object deleted'
513 )
514 );
515 }
516
534 public function setThirdpartyPriceLevel($id, $priceLevel)
535 {
536 global $conf;
537
538 if (!isModEnabled('societe')) {
539 throw new RestException(501, 'Module "Thirdparties" needed for this request');
540 }
541
542 if (!isModEnabled("product")) {
543 throw new RestException(501, 'Module "Products" needed for this request');
544 }
545
546 if (!getDolGlobalString('PRODUIT_MULTIPRICES') && !getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
547 throw new RestException(501, 'Multiprices features activation needed for this request');
548 }
549
550 if ($priceLevel < 1 || $priceLevel > getDolGlobalString('PRODUIT_MULTIPRICES_LIMIT')) {
551 throw new RestException(400, 'Price level must be between 1 and ' . getDolGlobalString('PRODUIT_MULTIPRICES_LIMIT'));
552 }
553
554 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
555 throw new RestException(403, 'Access to thirdparty '.$id.' not allowed for login '.DolibarrApiAccess::$user->login);
556 }
557
558 $result = $this->company->fetch($id);
559 if ($result < 0) {
560 throw new RestException(404, 'Thirdparty '.$id.' not found');
561 }
562
563 if (empty($result)) {
564 throw new RestException(500, 'Error fetching thirdparty '.$id, array_merge(array($this->company->error), $this->company->errors));
565 }
566
567 if (empty(DolibarrApi::_checkAccessToResource('societe', $this->company->id))) {
568 throw new RestException(403, 'Access to thirdparty '.$id.' not allowed for login '.DolibarrApiAccess::$user->login);
569 }
570
571 $result = $this->company->setPriceLevel($priceLevel, DolibarrApiAccess::$user);
572 if ($result <= 0) {
573 throw new RestException(500, 'Error setting new price level for thirdparty '.$id, array($this->company->db->lasterror()));
574 }
575
576 return $this->_cleanObjectDatas($this->company);
577 }
578
593 public function addRepresentative($id, $representative_id)
594 {
595 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
596 throw new RestException(403);
597 }
598 $result = $this->company->fetch($id);
599 if (!$result) {
600 throw new RestException(404, 'Thirdparty not found');
601 }
602 $usertmp = new User($this->db);
603 $result = $usertmp->fetch($representative_id);
604 if (!$result) {
605 throw new RestException(404, 'User not found');
606 }
607 if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
608 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
609 }
610 $result = $this->company->add_commercial(DolibarrApiAccess::$user, $representative_id);
611
612 return $result;
613 }
614
629 public function deleteRepresentative($id, $representative_id)
630 {
631 if (!DolibarrApiAccess::$user->hasRight('societe', 'supprimer')) {
632 throw new RestException(403);
633 }
634 $result = $this->company->fetch($id);
635 if (!$result) {
636 throw new RestException(404, 'Thirdparty not found');
637 }
638 $usertmp = new User($this->db);
639 $result = $usertmp->fetch($representative_id);
640 if (!$result) {
641 throw new RestException(404, 'User not found');
642 }
643 if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
644 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
645 }
646 $result = $this->company->del_commercial(DolibarrApiAccess::$user, $representative_id);
647
648 return $result;
649 }
650
669 public function getCategories($id, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0)
670 {
671 if (!DolibarrApiAccess::$user->hasRight('categorie', 'lire')) {
672 throw new RestException(403);
673 }
674
675 $result = $this->company->fetch($id);
676 if (!$result) {
677 throw new RestException(404, 'Thirdparty not found');
678 }
679
680 // Check that user has permission on thirdparty ID
681 if (!DolibarrApi::_checkAccessToResource('societe', $this->company)) {
682 throw new RestException(404, 'Third party not allowed for login '.DolibarrApiAccess::$user->login);
683 }
684
685 $categories = new Categorie($this->db);
686
687 $arrayofcateg = $categories->getListForItem($id, 'customer', $sortfield, $sortorder, $limit, $page);
688
689 if (is_numeric($arrayofcateg) && $arrayofcateg < 0) {
690 throw new RestException(503, 'Error when retrieve category list : '.$categories->error);
691 }
692
693 if (is_numeric($arrayofcateg) && $arrayofcateg >= 0) { // To fix a return of 0 instead of empty array of method getListForItem
694 return array();
695 }
696
697 return $arrayofcateg;
698 }
699
716 public function addCategory($id, $category_id)
717 {
718 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
719 throw new RestException(403);
720 }
721
722 $result = $this->company->fetch($id);
723 if (!$result) {
724 throw new RestException(404, 'Third party not found');
725 }
726 $category = new Categorie($this->db);
727 $result = $category->fetch($category_id);
728 if (!$result) {
729 throw new RestException(404, 'category not found');
730 }
731
732 if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
733 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
734 }
735 if (!DolibarrApi::_checkAccessToResource('category', $category->id)) {
736 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
737 }
738
739 $category->add_type($this->company, 'customer');
740
741 return $this->_cleanObjectDatas($this->company);
742 }
743
760 public function deleteCategory($id, $category_id)
761 {
762 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
763 throw new RestException(403);
764 }
765
766 $result = $this->company->fetch($id);
767 if (!$result) {
768 throw new RestException(404, 'Thirdparty not found');
769 }
770 $category = new Categorie($this->db);
771 $result = $category->fetch($category_id);
772 if (!$result) {
773 throw new RestException(404, 'category not found');
774 }
775
776 if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
777 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
778 }
779 if (!DolibarrApi::_checkAccessToResource('category', $category->id)) {
780 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
781 }
782
783 $category->del_type($this->company, 'customer');
784
785 return $this->_cleanObjectDatas($this->company);
786 }
787
807 public function getSupplierCategories($id, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0)
808 {
809 if (!DolibarrApiAccess::$user->hasRight('categorie', 'lire')) {
810 throw new RestException(403);
811 }
812
813 $result = $this->company->fetch($id);
814 if (!$result) {
815 throw new RestException(404, 'Thirdparty not found');
816 }
817
818 // Check that user has permission on thirdparty ID
819 if (!DolibarrApi::_checkAccessToResource('societe', $this->company)) {
820 throw new RestException(404, 'Third party not allowed for login '.DolibarrApiAccess::$user->login);
821 }
822
823 $categories = new Categorie($this->db);
824
825 $result = $categories->getListForItem($id, 'supplier', $sortfield, $sortorder, $limit, $page);
826
827 if (is_numeric($result) && $result < 0) {
828 throw new RestException(503, 'Error when retrieve category list : '.$categories->error);
829 }
830
831 if (is_numeric($result) && $result == 0) { // To fix a return of 0 instead of empty array of method getListForItem
832 return array();
833 }
834
835 return $result;
836 }
837
854 public function addSupplierCategory($id, $category_id)
855 {
856 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
857 throw new RestException(403);
858 }
859
860 $result = $this->company->fetch($id);
861 if (!$result) {
862 throw new RestException(404, 'Thirdparty not found');
863 }
864 $category = new Categorie($this->db);
865 $result = $category->fetch($category_id);
866 if (!$result) {
867 throw new RestException(404, 'category not found');
868 }
869
870 if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
871 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
872 }
873 if (!DolibarrApi::_checkAccessToResource('category', $category->id)) {
874 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
875 }
876
877 $category->add_type($this->company, 'supplier');
878
879 return $this->_cleanObjectDatas($this->company);
880 }
881
898 public function deleteSupplierCategory($id, $category_id)
899 {
900 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
901 throw new RestException(403);
902 }
903
904 $result = $this->company->fetch($id);
905 if (!$result) {
906 throw new RestException(404, 'Thirdparty not found');
907 }
908 $category = new Categorie($this->db);
909 $result = $category->fetch($category_id);
910 if (!$result) {
911 throw new RestException(404, 'category not found');
912 }
913
914 if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
915 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
916 }
917 if (!DolibarrApi::_checkAccessToResource('category', $category->id)) {
918 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
919 }
920
921 $category->del_type($this->company, 'supplier');
922
923 return $this->_cleanObjectDatas($this->company);
924 }
925
926
945 public function getOutStandingProposals($id, $mode = 'customer')
946 {
947 if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
948 throw new RestException(403);
949 }
950
951 if (empty($id)) {
952 throw new RestException(400, 'Thirdparty ID is mandatory');
953 }
954
955 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
956 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
957 }
958
959 $result = $this->company->fetch($id);
960 if (!$result) {
961 throw new RestException(404, 'Thirdparty not found');
962 }
963
964 $result = $this->company->getOutstandingProposals($mode);
965
966 unset($result['total_ht']);
967 unset($result['total_ttc']);
968
969 return $result;
970 }
971
972
991 public function getOutStandingOrder($id, $mode = 'customer')
992 {
993 if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
994 throw new RestException(403);
995 }
996
997 if (empty($id)) {
998 throw new RestException(400, 'Thirdparty ID is mandatory');
999 }
1000
1001 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1002 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1003 }
1004
1005 $result = $this->company->fetch($id);
1006 if (!$result) {
1007 throw new RestException(404, 'Thirdparty not found');
1008 }
1009
1010 $result = $this->company->getOutstandingOrders($mode);
1011
1012 unset($result['total_ht']);
1013 unset($result['total_ttc']);
1014
1015 return $result;
1016 }
1017
1036 public function getOutStandingInvoices($id, $mode = 'customer')
1037 {
1038 if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
1039 throw new RestException(403);
1040 }
1041
1042 if (empty($id)) {
1043 throw new RestException(400, 'Thirdparty ID is mandatory');
1044 }
1045
1046 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1047 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1048 }
1049
1050 $result = $this->company->fetch($id);
1051 if (!$result) {
1052 throw new RestException(404, 'Thirdparty not found');
1053 }
1054
1055 $result = $this->company->getOutstandingBills($mode);
1056
1057 unset($result['total_ht']);
1058 unset($result['total_ttc']);
1059
1060 return $result;
1061 }
1062
1081 public function getSalesRepresentatives($id, $mode = 0)
1082 {
1083 if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
1084 throw new RestException(403);
1085 }
1086
1087 if (empty($id)) {
1088 throw new RestException(400, 'Thirdparty ID is mandatory');
1089 }
1090
1091 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1092 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1093 }
1094
1095 $result = $this->company->fetch($id);
1096 if ($result <= 0) {
1097 throw new RestException(404, 'Thirdparty not found');
1098 }
1099
1100 $result = $this->company->getSalesRepresentatives(DolibarrApiAccess::$user, $mode);
1101
1102 return $result;
1103 }
1104
1129 public function getFixedAmountDiscounts($id, $mode = 'customer', $filter = "none", $sortfield = "f.type", $sortorder = 'ASC')
1130 {
1131 $obj_ret = array();
1132
1133 if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
1134 throw new RestException(403);
1135 }
1136
1137 if (empty($id)) {
1138 throw new RestException(400, 'Thirdparty ID is mandatory');
1139 }
1140
1141 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1142 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1143 }
1144
1145 $result = $this->company->fetch($id);
1146 if (!$result) {
1147 throw new RestException(404, 'Thirdparty not found');
1148 }
1149
1150 $sql = '';
1151 if ($mode === 'customer') {
1152 $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";
1153 $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re";
1154 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = re.fk_facture_source";
1155 $sql .= " WHERE re.fk_soc = ".((int) $id);
1156 if ($filter == "available") {
1157 $sql .= " AND re.fk_facture IS NULL AND re.fk_facture_line IS NULL";
1158 }
1159 if ($filter == "used") {
1160 $sql .= " AND (re.fk_facture IS NOT NULL OR re.fk_facture_line IS NOT NULL)";
1161 }
1162 } elseif ($mode === 'supplier') {
1163 $sql = "SELECT f.ref, f.type as factype, re.fk_invoice_supplier_source, re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc, re.description, re.fk_invoice_supplier, re.fk_invoice_supplier_line";
1164 $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re";
1165 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture_fourn as f ON f.rowid = re.fk_invoice_supplier_source";
1166 $sql .= " WHERE f.rowid = re.fk_invoice_supplier_source AND re.fk_soc = ".((int) $id);
1167 if ($filter == "available") {
1168 $sql .= " AND re.fk_invoice_supplier IS NULL AND re.fk_invoice_supplier_line IS NULL";
1169 }
1170 if ($filter == "used") {
1171 $sql .= " AND (re.fk_invoice_supplier IS NOT NULL OR re.fk_invoice_supplier_line IS NOT NULL)";
1172 }
1173 }
1174
1175 $sql .= $this->db->order($sortfield, $sortorder);
1176
1177 $result = $this->db->query($sql);
1178 if (!$result) {
1179 throw new RestException(503, $this->db->lasterror());
1180 } else {
1181 //$num = $this->db->num_rows($result);
1182 while ($obj = $this->db->fetch_object($result)) {
1183 $obj_ret[] = $obj;
1184 }
1185 }
1186
1187 return $obj_ret;
1188 }
1189
1214 public function createFixedAmountDiscount($id, $request_data = null)
1215 {
1216 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1217 throw new RestException(403);
1218 }
1219
1220 // Check mandatory fields
1221 if (empty($id)) {
1222 throw new RestException(400, 'Thirdparty ID is mandatory');
1223 }
1224 if (!isset($request_data['amount'])) {
1225 throw new RestException(400, 'Missing required field: amount');
1226 }
1227 if (!isset($request_data['description'])) {
1228 throw new RestException(400, 'Missing required field: description');
1229 }
1230
1231 // Check access to resource
1232 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1233 throw new RestException(401, 'Access not allowed for login'.DolibarrApiAccess::$user->login);
1234 }
1235
1236 // Fetch thirdparty to verify it exists
1237 if ($this->company->fetch($id) <= 0) {
1238 throw new RestException(404, 'Error creating discount, thirdparty not found');
1239 }
1240
1241
1242 // Validate amount
1243 if (!is_numeric($request_data['amount']) || $request_data['amount'] <= 0) {
1244 throw new RestException(400, 'Invalid amount_ht: must be a positive number');
1245 }
1246 $amount = (float) $request_data['amount'];
1247
1248 // Validate VAT rate
1249 if (isset($request_data['tva_tx']) && (!is_numeric($request_data['tva_tx']) || $request_data['tva_tx'] < 0)) {
1250 throw new RestException(400, 'Invalid tva_tx: must be a positive number or zero');
1251 }
1252 $tva_tx = isset($request_data['tva_tx']) ? (float) $request_data['tva_tx'] : 0;
1253
1254 // Get price base type (HT or TTC) : HT as default
1255 $price_base_type = 'HT';
1256 if (isset($request_data['price_base_type'])) {
1257 $price_base_type = strtoupper($request_data['price_base_type']);
1258 if ($price_base_type !== 'HT' && $price_base_type !== 'TTC') {
1259 throw new RestException(400, 'Invalid price_base_type: must be "HT" or "TTC"');
1260 }
1261 }
1262
1263 // Get discount type (0 = customer, 1 = supplier): 0 as default
1264 $discount_type = 0;
1265 if (isset($request_data['discount_type'])) {
1266 $discount_type = (int) $request_data['discount_type'];
1267 if ($discount_type !== 0 && $discount_type !== 1) {
1268 throw new RestException(400, 'Invalid discount_type: must be 0 (customer) or 1 (supplier)');
1269 }
1270 }
1271
1272 // Get description
1273 $description = $request_data['description'];
1274 if (empty(trim($description))) {
1275 throw new RestException(400, 'Description cannot be empty');
1276 }
1277
1278 // Prepare VAT rate with code if provided
1279 $vatrate = "";
1280 if (isset($request_data['vat_src_code']) && !empty($request_data['vat_src_code'])) {
1281 $vatrate = $tva_tx . ' (' . $request_data['vat_src_code'] . ')';
1282 }
1283
1284 // Create the discount using Societe::set_remise_except()
1285 $this->db->begin();
1286
1287 $result = $this->company->set_remise_except($amount, DolibarrApiAccess::$user, $description, $vatrate, $discount_type, $price_base_type);
1288
1289 if ($result > 0) {
1290 $this->db->commit();
1291 return $result;
1292 } else {
1293 $this->db->rollback();
1294 throw new RestException(500, 'Error creating discount: '.$this->company->error, array_merge(array($this->company->error), $this->company->errors));
1295 }
1296 }
1297
1321 public function splitdiscount($id, $discountid, $amount_ttc_1, $amount_ttc_2)
1322 {
1323 $obj_ret = array();
1324
1325 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer') || !DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
1326 throw new RestException(403);
1327 }
1328
1329 if (empty($id)) {
1330 throw new RestException(400, 'Thirdparty ID is mandatory');
1331 }
1332 if (empty($discountid)) {
1333 throw new RestException(400, 'Discount ID is mandatory');
1334 }
1335 if (empty($amount_ttc_1) || empty($amount_ttc_2)) {
1336 throw new RestException(400, 'Amount are mandatory');
1337 }
1338
1339 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1340 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1341 }
1342
1343 $result = $this->company->fetch($id);
1344 if (!$result) {
1345 throw new RestException(404, 'Thirdparty not found');
1346 }
1347 require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php';
1348 $discount = new DiscountAbsolute($this->db);
1349 $res = $discount->fetch($discountid);
1350 if (!($res > 0)) {
1351 throw new RestException(404, 'Discount not found');
1352 }
1353 if ($discount->socid != $id) {
1354 throw new RestException(405, 'Discount not owned by this thirdpartie');
1355 }
1356
1357 if (price2num((float) $amount_ttc_1 + (float) $amount_ttc_2) != $discount->amount_ttc) {
1358 throw new RestException(405, 'Sum of the 2 discounts is different that the original discount');
1359 }
1360 if ($discount->fk_facture_line) {
1361 throw new RestException(409, 'Discount is already used');
1362 }
1363
1364 $newdiscount1 = new DiscountAbsolute($this->db);
1365 $newdiscount2 = new DiscountAbsolute($this->db);
1366
1367 $newdiscount1->fk_facture_source = $discount->fk_facture_source;
1368 $newdiscount2->fk_facture_source = $discount->fk_facture_source;
1369 $newdiscount1->fk_facture = $discount->fk_facture;
1370 $newdiscount2->fk_facture = $discount->fk_facture;
1371 $newdiscount1->fk_facture_line = $discount->fk_facture_line;
1372 $newdiscount2->fk_facture_line = $discount->fk_facture_line;
1373 $newdiscount1->fk_invoice_supplier_source = $discount->fk_invoice_supplier_source;
1374 $newdiscount2->fk_invoice_supplier_source = $discount->fk_invoice_supplier_source;
1375 $newdiscount1->fk_invoice_supplier = $discount->fk_invoice_supplier;
1376 $newdiscount2->fk_invoice_supplier = $discount->fk_invoice_supplier;
1377 $newdiscount1->fk_invoice_supplier_line = $discount->fk_invoice_supplier_line;
1378 $newdiscount2->fk_invoice_supplier_line = $discount->fk_invoice_supplier_line;
1379 if ($discount->description == '(CREDIT_NOTE)' || $discount->description == '(DEPOSIT)') {
1380 $newdiscount1->description = $discount->description;
1381 $newdiscount2->description = $discount->description;
1382 } else {
1383 $newdiscount1->description = $discount->description.' (1)';
1384 $newdiscount2->description = $discount->description.' (2)';
1385 }
1386
1387 $newdiscount1->fk_user = $discount->fk_user;
1388 $newdiscount2->fk_user = $discount->fk_user;
1389 $newdiscount1->fk_soc = $discount->fk_soc;
1390 $newdiscount1->socid = $discount->socid;
1391 $newdiscount2->fk_soc = $discount->fk_soc;
1392 $newdiscount2->socid = $discount->socid;
1393 $newdiscount1->discount_type = $discount->discount_type;
1394 $newdiscount2->discount_type = $discount->discount_type;
1395 $newdiscount1->datec = $discount->datec;
1396 $newdiscount2->datec = $discount->datec;
1397 $newdiscount1->tva_tx = $discount->tva_tx;
1398 $newdiscount2->tva_tx = $discount->tva_tx;
1399 $newdiscount1->vat_src_code = $discount->vat_src_code;
1400 $newdiscount2->vat_src_code = $discount->vat_src_code;
1401 $newdiscount1->amount_ttc = $amount_ttc_1;
1402 $newdiscount2->amount_ttc = price2num($discount->amount_ttc - $newdiscount1->amount_ttc);
1403 $newdiscount1->amount_ht = price2num($newdiscount1->amount_ttc / (1 + $newdiscount1->tva_tx / 100), 'MT');
1404 $newdiscount2->amount_ht = price2num($newdiscount2->amount_ttc / (1 + $newdiscount2->tva_tx / 100), 'MT');
1405 $newdiscount1->amount_tva = price2num($newdiscount1->amount_ttc - $newdiscount1->amount_ht);
1406 $newdiscount2->amount_tva = price2num($newdiscount2->amount_ttc - $newdiscount2->amount_ht);
1407
1408 $newdiscount1->multicurrency_amount_ttc = (float) $amount_ttc_1 * ($discount->multicurrency_amount_ttc / $discount->amount_ttc);
1409 $newdiscount2->multicurrency_amount_ttc = price2num($discount->multicurrency_amount_ttc - $newdiscount1->multicurrency_amount_ttc);
1410 $newdiscount1->multicurrency_amount_ht = price2num($newdiscount1->multicurrency_amount_ttc / (1 + $newdiscount1->tva_tx / 100), 'MT');
1411 $newdiscount2->multicurrency_amount_ht = price2num($newdiscount2->multicurrency_amount_ttc / (1 + $newdiscount2->tva_tx / 100), 'MT');
1412 $newdiscount1->multicurrency_amount_tva = price2num($newdiscount1->multicurrency_amount_ttc - $newdiscount1->multicurrency_amount_ht);
1413 $newdiscount2->multicurrency_amount_tva = price2num($newdiscount2->multicurrency_amount_ttc - $newdiscount2->multicurrency_amount_ht);
1414
1415 // DiscountAbsolute->amount_ttc ->amount_ht ->amount_tva are marked as @deprecated but seems to yet be in use so we fill ->amout_xxx and ->total_xxx
1416 // the same for multicurrency_amount_xxx and multicurrency_total_xxx
1417 $newdiscount1->total_ttc = (float) price2num($newdiscount1->amount_ttc);
1418 $newdiscount1->total_ht = (float) price2num($newdiscount1->amount_ht);
1419 $newdiscount1->total_tva = (float) price2num($newdiscount1->amount_tva);
1420 $newdiscount2->total_ttc = (float) price2num($newdiscount2->amount_ttc);
1421 $newdiscount2->total_ht = (float) price2num($newdiscount2->amount_ht);
1422 $newdiscount2->total_tva = (float) price2num($newdiscount2->amount_tva);
1423 $newdiscount1->multicurrency_total_ttc = (float) price2num($newdiscount1->multicurrency_amount_ttc);
1424 $newdiscount1->multicurrency_total_ht = (float) price2num($newdiscount1->multicurrency_amount_ht);
1425 $newdiscount1->multicurrency_total_tva = (float) price2num($newdiscount1->multicurrency_amount_tva);
1426 $newdiscount2->multicurrency_total_ttc = (float) price2num($newdiscount2->multicurrency_amount_ttc);
1427 $newdiscount2->multicurrency_total_ht = (float) price2num($newdiscount2->multicurrency_amount_ht);
1428 $newdiscount2->multicurrency_total_tva = (float) price2num($newdiscount2->multicurrency_amount_tva);
1429
1430 $this->db->begin();
1431
1432 $discount->fk_facture_source = 0; // This is to delete only the require record (that we will recreate with two records) and not all family with same fk_facture_source
1433 // This is to delete only the require record (that we will recreate with two records) and not all family with same fk_invoice_supplier_source
1434 $discount->fk_invoice_supplier_source = 0;
1435 $res = $discount->delete(DolibarrApiAccess::$user);
1436 $newid1 = $newdiscount1->create(DolibarrApiAccess::$user);
1437 $newid2 = $newdiscount2->create(DolibarrApiAccess::$user);
1438 if ($res <= 0 || $newid1 <= 0 || $newid2 <= 0) {
1439 $this->db->rollback();
1440 throw new RestException(500, 'Operation fail');
1441 }
1442
1443 $this->db->commit();
1444
1445 $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";
1446 $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re, ".MAIN_DB_PREFIX."facture as f";
1447 $sql .= " WHERE re.rowid IN (".((int) $newid1).",".((int) $newid2).") AND f.rowid = re.fk_facture_source AND re.fk_soc = ".((int) $id);
1448
1449 $sql .= $this->db->order("f.type", "ASC");
1450
1451 $result = $this->db->query($sql);
1452 if (!$result) {
1453 throw new RestException(503, $this->db->lasterror());
1454 } else {
1455 // $num = $this->db->num_rows($result);
1456 while ($obj = $this->db->fetch_object($result)) {
1457 $obj_ret[] = $obj;
1458 }
1459 }
1460
1461 return $obj_ret;
1462 }
1463
1464
1483 {
1484 if (!DolibarrApiAccess::$user->hasRight('facture', 'lire')) {
1485 throw new RestException(403);
1486 }
1487 if (empty($id)) {
1488 throw new RestException(400, 'Thirdparty ID is mandatory');
1489 }
1490
1491 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1492 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1493 }
1494
1495 /*$result = $this->thirdparty->fetch($id);
1496 if( ! $result ) {
1497 throw new RestException(404, 'Thirdparty not found');
1498 }*/
1499
1500 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
1501 $invoice = new Facture($this->db);
1502 $result = $invoice->list_replacable_invoices($id);
1503 if ($result < 0) {
1504 throw new RestException(405, $invoice->error);
1505 }
1506
1507 return $result;
1508 }
1509
1532 {
1533 if (!DolibarrApiAccess::$user->hasRight('facture', 'lire')) {
1534 throw new RestException(403);
1535 }
1536 if (empty($id)) {
1537 throw new RestException(400, 'Thirdparty ID is mandatory');
1538 }
1539
1540 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1541 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1542 }
1543
1544 /*$result = $this->thirdparty->fetch($id);
1545 if( ! $result ) {
1546 throw new RestException(404, 'Thirdparty not found');
1547 }*/
1548
1549 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
1550 $invoice = new Facture($this->db);
1551 $result = $invoice->list_qualified_avoir_invoices($id);
1552 if (!is_array($result) && $result < 0) {
1553 throw new RestException(405, $invoice->error);
1554 }
1555
1556 return $result;
1557 }
1558
1575 {
1576 if (empty($id)) {
1577 throw new RestException(400, 'Thirdparty ID is mandatory');
1578 }
1579 if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
1580 throw new RestException(403);
1581 }
1582 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1583 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1584 }
1585
1590 $sql = "SELECT rowid as id, fk_action as event, fk_soc as socid, fk_contact as contact_id, type, datec, tms";
1591 $sql .= " FROM ".MAIN_DB_PREFIX."notify_def";
1592 if ($id) {
1593 $sql .= " WHERE fk_soc = ".((int) $id);
1594 }
1595
1596 $result = $this->db->query($sql);
1597 if ($this->db->num_rows($result) == 0) {
1598 throw new RestException(404, 'Notification not found');
1599 }
1600
1601 $i = 0;
1602
1603 $notifications = array();
1604
1605 if ($result) {
1606 $i = 0;
1607 $num = $this->db->num_rows($result);
1608 //$min = min($num, ($limit <= 0 ? $num : $limit));
1609 $min = $num;
1610 while ($i < $min) {
1611 $obj = $this->db->fetch_object($result);
1612 $notifications[] = $obj;
1613 $i++;
1614 }
1615 } else {
1616 throw new RestException(404, 'No notifications found');
1617 }
1618
1619 $fields = array('id', 'socid', 'event', 'contact_id', 'datec', 'tms', 'type');
1620
1621 $returnNotifications = array();
1622
1623 foreach ($notifications as $notification) {
1624 $object = array();
1625 foreach ($notification as $key => $value) {
1626 if (in_array($key, $fields)) {
1627 $object[$key] = $value;
1628 }
1629 }
1630 $returnNotifications[] = $object;
1631 }
1632
1633 // Too complex for phan ?: @phan-suppress-next-line PhanTypeMismatchReturn
1634 return $returnNotifications;
1635 }
1636
1653 public function createCompanyNotification($id, $request_data = null)
1654 {
1655 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1656 throw new RestException(403, "User has no right to update thirdparties");
1657 }
1658
1659 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1660 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1661 }
1662
1663 if ($this->company->fetch($id) <= 0) {
1664 throw new RestException(404, 'Error creating Thirdparty Notification, Thirdparty doesn\'t exists');
1665 }
1666 $notification = new Notify($this->db);
1667
1668 $notification->socid = $id;
1669
1670 foreach ($request_data as $field => $value) {
1671 $notification->$field = $this->_checkValForAPI($field, $value, $notification);
1672 }
1673
1674 $event = $notification->event;
1675 if (!$event) {
1676 throw new RestException(500, 'Error creating Thirdparty Notification, request_data missing event');
1677 }
1678 $socid = $notification->socid;
1679 $contact_id = $notification->contact_id;
1680
1681 $exists_sql = "SELECT rowid, fk_action as event, fk_soc as socid, fk_contact as contact_id, type, datec, tms as datem";
1682 $exists_sql .= " FROM ".MAIN_DB_PREFIX."notify_def";
1683 $exists_sql .= " WHERE fk_action = '".$this->db->escape((string) $event)."'";
1684 $exists_sql .= " AND fk_soc = '".$this->db->escape((string) $socid)."'";
1685 $exists_sql .= " AND fk_contact = '".$this->db->escape((string) $contact_id)."'";
1686
1687 $exists_result = $this->db->query($exists_sql);
1688 if ($this->db->num_rows($exists_result) > 0) {
1689 throw new RestException(403, 'Notification already exists');
1690 }
1691
1692 if ($notification->create(DolibarrApiAccess::$user) < 0) {
1693 throw new RestException(500, 'Error creating Thirdparty Notification');
1694 }
1695
1696 if ($notification->update(DolibarrApiAccess::$user) < 0) {
1697 throw new RestException(500, 'Error updating values');
1698 }
1699
1700 return $this->_cleanObjectDatas($notification);
1701 }
1702
1721 public function createCompanyNotificationByCode($id, $code, $request_data = null)
1722 {
1723 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1724 throw new RestException(403, "User has no right to update thirdparties");
1725 }
1726
1727 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1728 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1729 }
1730
1731 if ($this->company->fetch($id) <= 0) {
1732 throw new RestException(404, 'Error creating Thirdparty Notification, Thirdparty doesn\'t exists');
1733 }
1734 $notification = new Notify($this->db);
1735 $notification->socid = $id;
1736
1737 $sql = "SELECT t.rowid as id FROM ".MAIN_DB_PREFIX."c_action_trigger as t";
1738 $sql .= " WHERE t.code = '".$this->db->escape($code)."'";
1739
1740 $result = $this->db->query($sql);
1741 if ($this->db->num_rows($result) == 0) {
1742 throw new RestException(404, 'Action Trigger code not found');
1743 }
1744
1745 $notification->event = $this->db->fetch_row($result)[0];
1746 foreach ($request_data as $field => $value) {
1747 if ($field === 'event') {
1748 throw new RestException(500, 'Error creating Thirdparty Notification, request_data contains event key');
1749 }
1750 if ($field === 'fk_action') {
1751 throw new RestException(500, 'Error creating Thirdparty Notification, request_data contains fk_action key');
1752 }
1753 $notification->$field = $this->_checkValForAPI($field, $value, $notification);
1754 }
1755
1756 $event = $notification->event;
1757 $socid = $notification->socid;
1758 $contact_id = $notification->contact_id;
1759
1760 $exists_sql = "SELECT rowid, fk_action as event, fk_soc as socid, fk_contact as contact_id, type, datec, tms as datem";
1761 $exists_sql .= " FROM ".MAIN_DB_PREFIX."notify_def";
1762 $exists_sql .= " WHERE fk_action = '".$this->db->escape((string) $event)."'";
1763 $exists_sql .= " AND fk_soc = '".$this->db->escape((string) $socid)."'";
1764 $exists_sql .= " AND fk_contact = '".$this->db->escape((string) $contact_id)."'";
1765
1766 $exists_result = $this->db->query($exists_sql);
1767 if ($this->db->num_rows($exists_result) > 0) {
1768 throw new RestException(403, 'Notification already exists');
1769 }
1770
1771 if ($notification->create(DolibarrApiAccess::$user) < 0) {
1772 throw new RestException(500, 'Error creating Thirdparty Notification, are request_data well formed?');
1773 }
1774
1775 if ($notification->update(DolibarrApiAccess::$user) < 0) {
1776 throw new RestException(500, 'Error updating values');
1777 }
1778
1779 return $this->_cleanObjectDatas($notification);
1780 }
1781
1796 public function deleteCompanyNotification($id, $notification_id)
1797 {
1798 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1799 throw new RestException(403);
1800 }
1801
1802 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1803 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1804 }
1805
1806 $notification = new Notify($this->db);
1807
1808 $notification->fetch($notification_id);
1809
1810 $socid = (int) $notification->socid;
1811
1812 if ($socid == $id) {
1813 return $notification->delete(DolibarrApiAccess::$user);
1814 } else {
1815 throw new RestException(403, "Not allowed due to bad consistency of input data");
1816 }
1817 }
1818
1836 public function updateCompanyNotification($id, $notification_id, $request_data = null)
1837 {
1838 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1839 throw new RestException(403, "User has no right to update thirdparties");
1840 }
1841
1842 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1843 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1844 }
1845
1846 if ($this->company->fetch($id) <= 0) {
1847 throw new RestException(404, 'Error creating Company Notification, Company doesn\'t exists');
1848 }
1849 $notification = new Notify($this->db);
1850
1851 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1852 $notification->fetch($notification_id, $id);
1853
1854 if ($notification->socid != $id) {
1855 throw new RestException(403, "Not allowed due to bad consistency of input data");
1856 }
1857
1858 foreach ($request_data as $field => $value) {
1859 $notification->$field = $this->_checkValForAPI($field, $value, $notification);
1860 }
1861
1862 if ($notification->update(DolibarrApiAccess::$user) < 0) {
1863 throw new RestException(500, 'Error updating values');
1864 }
1865
1866 return $this->_cleanObjectDatas($notification);
1867 }
1868
1885 {
1886 if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
1887 throw new RestException(403);
1888 }
1889 if (empty($id)) {
1890 throw new RestException(400, 'Thirdparty ID is mandatory');
1891 }
1892
1893 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1894 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1895 }
1896
1901 $sql = "SELECT rowid, fk_soc, bank, number, code_banque, code_guichet, cle_rib, bic, iban_prefix as iban, domiciliation as address, proprio,";
1902 $sql .= " owner_address, default_rib, label, datec, tms as datem, rum, frstrecur";
1903 $sql .= " FROM ".MAIN_DB_PREFIX."societe_rib";
1904 if ($id) {
1905 $sql .= " WHERE fk_soc = ".((int) $id);
1906 }
1907
1908 $result = $this->db->query($sql);
1909
1910 if ($this->db->num_rows($result) == 0) {
1911 throw new RestException(404, 'Account not found');
1912 }
1913
1914 $i = 0;
1915
1916 $accounts = array();
1917
1918 if ($result) {
1919 $i = 0;
1920 $num = $this->db->num_rows($result);
1921 //$min = min($num, ($limit <= 0 ? $num : $limit));
1922 $min = $num;
1923 while ($i < $min) {
1924 $obj = $this->db->fetch_object($result);
1925
1926 $account = new CompanyBankAccount($this->db);
1927 if ($account->fetch($obj->rowid)) {
1928 $accounts[] = $account;
1929 }
1930 $i++;
1931 }
1932 } else {
1933 throw new RestException(404, 'Account not found');
1934 }
1935
1936
1937 $fields = array('socid', 'default_rib', 'frstrecur', '1000110000001', 'datec', 'datem', 'label', 'bank', 'bic', 'iban', 'id', 'rum');
1938
1939 $returnAccounts = array();
1940
1941 foreach ($accounts as $account) {
1942 $object = array();
1943 foreach ($account as $key => $value) {
1944 if (in_array($key, $fields)) {
1945 if ($key == 'iban') {
1946 $object[$key] = dolDecrypt($value);
1947 } else {
1948 $object[$key] = $value;
1949 }
1950 }
1951 }
1952 $returnAccounts[] = $object;
1953 }
1954
1955 return $returnAccounts;
1956 }
1957
1974 public function createCompanyBankAccount($id, $request_data = null)
1975 {
1976 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
1977 throw new RestException(403);
1978 }
1979 if ($this->company->fetch($id) <= 0) {
1980 throw new RestException(404, 'Error creating Company Bank account, Company doesn\'t exists');
1981 }
1982
1983 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
1984 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1985 }
1986
1987 $account = new CompanyBankAccount($this->db);
1988
1989 $account->socid = $id;
1990
1991 foreach ($request_data as $field => $value) {
1992 if ($field === 'caller') {
1993 // 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
1994 $this->company->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
1995 continue;
1996 }
1997
1998 $account->$field = $this->_checkValForAPI('extrafields', $value, $account);
1999 }
2000
2001 if ($account->create(DolibarrApiAccess::$user) < 0) {
2002 throw new RestException(500, 'Error creating Company Bank account');
2003 }
2004
2005 if (empty($account->rum)) {
2006 require_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php';
2007 $prelevement = new BonPrelevement($this->db);
2008 $account->rum = $prelevement->buildRumNumber((string) $this->company->code_client, $account->datec, (string) $account->id);
2009 $account->date_rum = dol_now();
2010 }
2011
2012 if ($account->update(DolibarrApiAccess::$user) < 0) {
2013 throw new RestException(500, 'Error updating values');
2014 }
2015
2016 return $this->_cleanObjectDatas($account);
2017 }
2018
2036 public function updateCompanyBankAccount($id, $bankaccount_id, $request_data = null)
2037 {
2038 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
2039 throw new RestException(403);
2040 }
2041 if ($this->company->fetch($id) <= 0) {
2042 throw new RestException(404, 'Error creating Company Bank account, Company doesn\'t exists');
2043 }
2044
2045 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
2046 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
2047 }
2048
2049 $account = new CompanyBankAccount($this->db);
2050
2051 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
2052 $account->fetch($bankaccount_id, '', $id, -1, '');
2053
2054 if ($account->socid != $id) {
2055 throw new RestException(403);
2056 }
2057
2058
2059 foreach ($request_data as $field => $value) {
2060 if ($field === 'caller') {
2061 // 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
2062 $account->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
2063 continue;
2064 }
2065
2066 $account->$field = $this->_checkValForAPI($field, $value, $account);
2067 }
2068
2069 if (empty($account->rum)) {
2070 require_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php';
2071 $prelevement = new BonPrelevement($this->db);
2072 $account->rum = $prelevement->buildRumNumber((string) $this->company->code_client, $account->datec, (string) $account->id);
2073 $account->date_rum = dol_now();
2074 }
2075
2076 if ($account->update(DolibarrApiAccess::$user) < 0) {
2077 throw new RestException(500, 'Error updating values');
2078 }
2079
2080 return $this->_cleanObjectDatas($account);
2081 }
2082
2097 public function deleteCompanyBankAccount($id, $bankaccount_id)
2098 {
2099 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
2100 throw new RestException(403);
2101 }
2102
2103 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
2104 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
2105 }
2106
2107 $account = new CompanyBankAccount($this->db);
2108
2109 $account->fetch($bankaccount_id);
2110
2111 $socid = (int) $account->socid;
2112
2113 if ($socid == $id) {
2114 return $account->delete(DolibarrApiAccess::$user);
2115 } else {
2116 throw new RestException(403, "Not allowed due to bad consistency of input data");
2117 }
2118 }
2119
2138 public function generateBankAccountDocument($id, $companybankid = null, $model = 'sepamandate')
2139 {
2140 global $conf, $langs;
2141
2142 $langs->loadLangs(array("main", "dict", "commercial", "products", "companies", "banks", "bills", "withdrawals"));
2143
2144 if ($this->company->fetch($id) <= 0) {
2145 throw new RestException(404, 'Thirdparty not found');
2146 }
2147
2148 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
2149 throw new RestException(403);
2150 }
2151
2152 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
2153 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
2154 }
2155
2156 $this->company->setDocModel(DolibarrApiAccess::$user, $model);
2157
2158 $this->company->fk_bank = $this->company->fk_account;
2159 // $this->company->fk_account = $this->company->fk_account;
2160
2161 $outputlangs = $langs;
2162 $newlang = '';
2163
2164 //if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09');
2165 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
2166 if (isset($this->company->thirdparty->default_lang)) {
2167 $newlang = $this->company->thirdparty->default_lang; // for proposal, order, invoice, ...
2168 } elseif (isset($this->company->default_lang)) {
2169 $newlang = $this->company->default_lang; // for thirdparty
2170 }
2171 }
2172 if (!empty($newlang)) {
2173 $outputlangs = new Translate("", $conf);
2174 $outputlangs->setDefaultLang($newlang);
2175 }
2176
2177 $sql = "SELECT rowid";
2178 $sql .= " FROM ".MAIN_DB_PREFIX."societe_rib";
2179 if ($id) {
2180 $sql .= " WHERE fk_soc = ".((int) $id);
2181 }
2182 if ($companybankid) {
2183 $sql .= " AND rowid = ".((int) $companybankid);
2184 }
2185
2186 $i = 0;
2187 $accounts = array();
2188
2189 $result = $this->db->query($sql);
2190 if ($result) {
2191 if ($this->db->num_rows($result) == 0) {
2192 throw new RestException(404, 'Bank account not found');
2193 }
2194
2195 $num = $this->db->num_rows($result);
2196 //$min = min($num, ($limit <= 0 ? $num : $limit));
2197 $min = $num;
2198 while ($i < $min) {
2199 $obj = $this->db->fetch_object($result);
2200
2201 $account = new CompanyBankAccount($this->db);
2202 if ($account->fetch($obj->rowid)) {
2203 $accounts[] = $account;
2204 }
2205 $i++;
2206 }
2207 } else {
2208 throw new RestException(500, 'Sql error '.$this->db->lasterror());
2209 }
2210
2211 $moreparams = array(
2212 'use_companybankid' => $accounts[0]->id,
2213 'force_dir_output' => $conf->societe->multidir_output[$this->company->entity].'/'.dol_sanitizeFileName((string) $this->company->id)
2214 );
2215
2216 $result = $this->company->generateDocument($model, $outputlangs, 0, 0, 0, $moreparams);
2217
2218 if ($result > 0) {
2219 return array("success" => $result);
2220 } else {
2221 throw new RestException(500, 'Error generating the document '.$this->company->error);
2222 }
2223 }
2224
2242 public function getSocieteAccounts($id, $site = null)
2243 {
2244 if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
2245 throw new RestException(403);
2246 }
2247
2248 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
2249 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
2250 }
2251
2255 $sql = "SELECT rowid, fk_soc, key_account, site, date_creation, tms FROM ".MAIN_DB_PREFIX."societe_account";
2256 $sql .= " WHERE fk_soc = ".((int) $id);
2257 if ($site) {
2258 $sql .= " AND site ='".$this->db->escape($site)."'";
2259 }
2260
2261 $result = $this->db->query($sql);
2262
2263 if ($result && $this->db->num_rows($result) == 0) {
2264 throw new RestException(404, 'This thirdparty does not have any account attached or does not exist.');
2265 }
2266
2267 $i = 0;
2268
2269 $accounts = array();
2270
2271 $i = 0;
2272 $num = $this->db->num_rows($result);
2273 //$min = min($num, ($limit <= 0 ? $num : $limit));
2274 $min = $num;
2275 while ($i < $min) {
2276 $obj = $this->db->fetch_object($result);
2277 $account = new SocieteAccount($this->db);
2278
2279 if ($account->fetch($obj->rowid)) {
2280 $accounts[] = $account;
2281 }
2282 $i++;
2283 }
2284
2285 $fields = array('id', 'fk_soc', 'key_account', 'site', 'date_creation', 'tms');
2286
2287 $returnAccounts = array();
2288
2289 foreach ($accounts as $account) {
2290 $object = array();
2291 foreach ($account as $key => $value) {
2292 if (in_array($key, $fields)) {
2293 $object[$key] = $value;
2294 }
2295 }
2296 $returnAccounts[] = $object;
2297 }
2298
2299 return $returnAccounts;
2300 }
2301
2319 public function getSocieteByAccounts($site, $key_account)
2320 {
2321 if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
2322 throw new RestException(403);
2323 }
2324
2325 $sql = "SELECT rowid, fk_soc, key_account, site, date_creation, tms FROM ".MAIN_DB_PREFIX."societe_account";
2326 $sql .= " WHERE site = '".$this->db->escape($site)."' AND key_account = '".$this->db->escape($key_account)."'";
2327 $sql .= " AND entity IN (".getEntity('societe').")";
2328
2329 $result = $this->db->query($sql);
2330
2331 if ($result && $this->db->num_rows($result) == 1) {
2332 $obj = $this->db->fetch_object($result);
2333 $returnThirdparty = $this->_fetch($obj->fk_soc);
2334 } else {
2335 throw new RestException(404, 'This account have many thirdparties attached or does not exist.');
2336 }
2337
2338 if (!DolibarrApi::_checkAccessToResource('societe', $returnThirdparty->id)) {
2339 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
2340 }
2341
2342 return $returnThirdparty;
2343 }
2344
2368 public function createSocieteAccount($id, $request_data = null)
2369 {
2370 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
2371 throw new RestException(403);
2372 }
2373
2374 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
2375 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
2376 }
2377
2378 if (!isset($request_data['site'])) {
2379 throw new RestException(422, 'Unprocessable Entity: You must pass the site attribute in your request data !');
2380 }
2381
2382 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."societe_account WHERE fk_soc = ".((int) $id)." AND site = '".$this->db->escape($request_data['site'])."'";
2383 $result = $this->db->query($sql);
2384
2385 if ($result && $this->db->num_rows($result) == 0) {
2386 $account = new SocieteAccount($this->db);
2387 if (!isset($request_data['login'])) {
2388 $account->login = "";
2389 }
2390 $account->fk_soc = $id;
2391
2392 foreach ($request_data as $field => $value) {
2393 if ($field === 'caller') {
2394 // 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
2395 $account->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
2396 continue;
2397 }
2398
2399 $account->$field = $this->_checkValForAPI($field, $value, $account);
2400 }
2401
2402 if ($account->create(DolibarrApiAccess::$user) < 0) {
2403 throw new RestException(500, 'Error creating SocieteAccount entity. Ensure that the ID of thirdparty provided does exist!');
2404 }
2405
2406 $this->_cleanObjectDatas($account);
2407
2408 return $account;
2409 } else {
2410 throw new RestException(409, 'A SocieteAccount entity already exists for this company and site.');
2411 }
2412 }
2413
2440 public function postSocieteAccount($id, $site, $request_data = null)
2441 {
2442 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
2443 throw new RestException(403);
2444 }
2445
2446 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
2447 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
2448 }
2449
2450 $sql = "SELECT rowid, fk_user_creat, date_creation FROM ".MAIN_DB_PREFIX."societe_account WHERE fk_soc = ".((int) $id)." AND site = '".$this->db->escape($site)."'";
2451 $result = $this->db->query($sql);
2452
2453 // We do not found an existing SocieteAccount entity for this fk_soc and site ; we then create a new one.
2454 if ($result && $this->db->num_rows($result) == 0) {
2455 if (!isset($request_data['key_account'])) {
2456 throw new RestException(422, 'Unprocessable Entity: You must pass the key_account attribute in your request data !');
2457 }
2458 $account = new SocieteAccount($this->db);
2459 if (!isset($request_data['login'])) {
2460 $account->login = "";
2461 }
2462
2463 foreach ($request_data as $field => $value) {
2464 if ($field === 'caller') {
2465 // 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
2466 $account->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
2467 continue;
2468 }
2469
2470 $account->$field = $this->_checkValForAPI($field, $value, $account);
2471 }
2472
2473 $account->fk_soc = $id;
2474 $account->site = $site;
2475
2476 if ($account->create(DolibarrApiAccess::$user) < 0) {
2477 throw new RestException(500, 'Error creating SocieteAccount entity.');
2478 }
2479 // We found an existing SocieteAccount entity, we are replacing it
2480 } else {
2481 if (isset($request_data['site']) && $request_data['site'] !== $site) {
2482 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."societe_account WHERE fk_soc = ".((int) $id)." AND site = '".$this->db->escape($request_data['site'])."' ";
2483 $result = $this->db->query($sql);
2484
2485 if ($result && $this->db->num_rows($result) !== 0) {
2486 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.");
2487 }
2488 }
2489
2490 $obj = $this->db->fetch_object($result);
2491
2492 $account = new SocieteAccount($this->db);
2493 $account->id = $obj->rowid;
2494 $account->fk_soc = $id;
2495 $account->site = $site;
2496 if (!isset($request_data['login'])) {
2497 $account->login = "";
2498 }
2499 $account->fk_user_creat = $obj->fk_user_creat;
2500 $account->date_creation = $obj->date_creation;
2501
2502 foreach ($request_data as $field => $value) {
2503 if ($field === 'caller') {
2504 // 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
2505 $account->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
2506 continue;
2507 }
2508
2509 $account->$field = $this->_checkValForAPI($field, $value, $account);
2510 }
2511
2512 if ($account->update(DolibarrApiAccess::$user) < 0) {
2513 throw new RestException(500, 'Error updating SocieteAccount entity.');
2514 }
2515 }
2516
2517 $this->_cleanObjectDatas($account);
2518
2519 return $account;
2520 }
2521
2542 public function putSocieteAccount($id, $site, $request_data = null)
2543 {
2544 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
2545 throw new RestException(403);
2546 }
2547
2548 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
2549 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
2550 }
2551
2552 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."societe_account WHERE fk_soc = ".((int) $id)." AND site = '".$this->db->escape($site)."'";
2553 $result = $this->db->query($sql);
2554
2555 if ($result && $this->db->num_rows($result) == 0) {
2556 throw new RestException(404, "This thirdparty does not have $site account attached or does not exist.");
2557 } else {
2558 // If the user tries to edit the site member, we check first if
2559 if (isset($request_data['site']) && $request_data['site'] !== $site) {
2560 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."societe_account WHERE fk_soc = ".((int) $id)." AND site = '".$this->db->escape($request_data['site'])."' ";
2561 $result = $this->db->query($sql);
2562
2563 if ($result && $this->db->num_rows($result) !== 0) {
2564 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.");
2565 }
2566 }
2567
2568 $obj = $this->db->fetch_object($result);
2569 $account = new SocieteAccount($this->db);
2570 $account->fetch($obj->rowid);
2571
2572 foreach ($request_data as $field => $value) {
2573 if ($field === 'caller') {
2574 // 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
2575 $account->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
2576 continue;
2577 }
2578
2579 $account->$field = $this->_checkValForAPI($field, $value, $account);
2580 }
2581
2582 if ($account->update(DolibarrApiAccess::$user) < 0) {
2583 throw new RestException(500, 'Error updating SocieteAccount account');
2584 }
2585
2586 $this->_cleanObjectDatas($account);
2587
2588 return $account;
2589 }
2590 }
2591
2610 public function deleteSocieteAccount($id, $site)
2611 {
2612 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
2613 throw new RestException(403);
2614 }
2615
2616 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
2617 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
2618 }
2619
2620 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."societe_account WHERE fk_soc = ".((int) $id)." AND site = '".$this->db->escape($site)."'";
2621 $result = $this->db->query($sql);
2622
2623 if ($result && $this->db->num_rows($result) == 0) {
2624 throw new RestException(404);
2625 } else {
2626 $obj = $this->db->fetch_object($result);
2627 $account = new SocieteAccount($this->db);
2628 $account->fetch($obj->rowid);
2629
2630 if ($account->delete(DolibarrApiAccess::$user) < 0) {
2631 throw new RestException(500, "Error while deleting $site account attached to this third party");
2632 }
2633 }
2634 }
2635
2652 {
2653 if (!DolibarrApiAccess::$user->hasRight('societe', 'creer')) {
2654 throw new RestException(403);
2655 }
2656
2657 if (!DolibarrApi::_checkAccessToResource('societe', $id)) {
2658 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
2659 }
2660
2665 $sql = "SELECT rowid, fk_soc, key_account, site, date_creation, tms";
2666 $sql .= " FROM ".MAIN_DB_PREFIX."societe_account WHERE fk_soc = ".((int) $id);
2667
2668 $result = $this->db->query($sql);
2669
2670 if ($result && $this->db->num_rows($result) == 0) {
2671 throw new RestException(404, 'This third party does not have any account attached or does not exist.');
2672 } else {
2673 $i = 0;
2674
2675 $i = 0;
2676 $num = $this->db->num_rows($result);
2677 //$min = min($num, ($limit <= 0 ? $num : $limit));
2678 $min = $num;
2679 while ($i < $min) {
2680 $obj = $this->db->fetch_object($result);
2681 $account = new SocieteAccount($this->db);
2682 $account->fetch($obj->rowid);
2683
2684 if ($account->delete(DolibarrApiAccess::$user) < 0) {
2685 throw new RestException(500, 'Error while deleting account attached to this third party');
2686 }
2687 $i++;
2688 }
2689 }
2690 }
2691
2692 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2702 protected function _cleanObjectDatas($object)
2703 {
2704 // phpcs:enable
2705 $object = parent::_cleanObjectDatas($object);
2706
2707 unset($object->nom); // ->name already defined and nom deprecated
2708 unset($object->name_bis); // ->name_alias already defined
2709 unset($object->note); // ->note_private and note_public already defined
2710 unset($object->departement);
2711 unset($object->departement_code);
2712 unset($object->pays);
2713 unset($object->particulier);
2714 unset($object->prefix_comm);
2715
2716 unset($object->siren);
2717 unset($object->siret);
2718 unset($object->ape);
2719
2720 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.
2721
2722 unset($object->total_ht);
2723 unset($object->total_tva);
2724 unset($object->total_localtax1);
2725 unset($object->total_localtax2);
2726 unset($object->total_ttc);
2727
2728 unset($object->lines);
2729 unset($object->thirdparty);
2730
2731 unset($object->fk_delivery_address); // deprecated feature
2732
2733 return $object;
2734 }
2735
2744 private function _validate($data)
2745 {
2746 if ($data === null) {
2747 $data = array();
2748 }
2749 $thirdparty = array();
2750 foreach (Thirdparties::$FIELDS as $field) {
2751 if (!isset($data[$field])) {
2752 throw new RestException(400, "$field field missing");
2753 }
2754 $thirdparty[$field] = $data[$field];
2755 }
2756 return $thirdparty;
2757 }
2758
2782 private function _fetch($rowid, $ref = '', $ref_ext = '', $barcode = '', $idprof1 = '', $idprof2 = '', $idprof3 = '', $idprof4 = '', $idprof5 = '', $idprof6 = '', $email = '', $ref_alias = '')
2783 {
2784 if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
2785 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login.'. No read permission on thirdparties.');
2786 }
2787
2788 if ($rowid === 0) {
2789 $result = $this->company->initAsSpecimen();
2790 } else {
2791 $result = $this->company->fetch((int) $rowid, $ref, $ref_ext, $barcode, $idprof1, $idprof2, $idprof3, $idprof4, $idprof5, $idprof6, $email, $ref_alias);
2792 }
2793 if (!$result) {
2794 throw new RestException(404, 'Thirdparty not found');
2795 }
2796
2797 if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) {
2798 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login.' on this thirdparty');
2799 }
2800 if (isModEnabled('mailing')) {
2801 $this->company->getNoEmail();
2802 }
2803
2804 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
2805 $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
2806 $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
2807 } else {
2808 $filterabsolutediscount = "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')";
2809 $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')";
2810 }
2811
2812 $absolute_discount = $this->company->getAvailableDiscounts(null, $filterabsolutediscount);
2813 $absolute_creditnote = $this->company->getAvailableDiscounts(null, $filtercreditnote);
2814 $this->company->absolute_discount = price2num($absolute_discount, 'MT');
2815 $this->company->absolute_creditnote = price2num($absolute_creditnote, 'MT');
2816
2817 return $this->_cleanObjectDatas($this->company);
2818 }
2819}
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Class to manage withdrawal receipts.
Class to manage categories.
Class to manage bank accounts description of third parties.
Class to manage absolute discounts.
Class for API REST v1.
Definition api.class.php:35
_checkValExtrafieldsForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
_filterObjectProperties($object, $properties)
Filter properties that will be returned on object.
_checkValForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
static _checkAccessToResource($resource, $resource_id=0, $dbtablename='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $parenttableforentity='')
Check access by user to a given resource.
Class to manage invoices.
Class to manage the table of subscription to notifications.
Class for SocieteAccount.
Class to manage third parties objects (customers, suppliers, prospects...)
updateCompanyNotification($id, $notification_id, $request_data=null)
Update a company notification for a third party.
setThirdpartyPriceLevel($id, $priceLevel)
Set a new price level for the given third party.
_cleanObjectDatas($object)
Clean sensible object datas @phpstan-template T.
getSocieteByAccounts($site, $key_account)
Get a specific third party by account.
getSupplierCategories($id, $sortfield="s.rowid", $sortorder='ASC', $limit=0, $page=0)
Get supplier categories for a third party.
deleteCompanyNotification($id, $notification_id)
Delete a company notification attached to a third party.
getSocieteAccounts($id, $site=null)
Get a specific account attached to a third party.
getOutStandingOrder($id, $mode='customer')
Get outstanding orders for a third party.
addRepresentative($id, $representative_id)
Add a customer representative to a third party.
getByBarcode($barcode)
Get a third party by barcode.
generateBankAccountDocument($id, $companybankid=null, $model='sepamandate')
Generate a document from a bank account record.
createCompanyNotificationByCode($id, $code, $request_data=null)
Create a company notification for a third party using action trigger code.
getCompanyNotification($id)
Get company notifications for a third party.
addCategory($id, $category_id)
Add a customer category to a third party.
getCompanyBankAccount($id)
Get company bank accounts of a third party.
getInvoicesQualifiedForReplacement($id)
Return invoices qualified to be replaced by another invoice.
post($request_data=null)
Create a third party.
put($id, $request_data=null)
Update third party.
getByEmail($email)
Get properties of a third party by email.
_validate($data)
Validate fields before create or update object.
getFixedAmountDiscounts($id, $mode='customer', $filter="none", $sortfield="f.type", $sortorder='ASC')
Get fixed amount discount of a third party.
addSupplierCategory($id, $category_id)
Add a supplier category to a third party.
merge($id, $idtodelete)
Merge a third party into another third party.
deleteSocieteAccounts($id)
Delete all accounts attached to a third party.
__construct()
Constructor.
getCategories($id, $sortfield="s.rowid", $sortorder='ASC', $limit=0, $page=0)
Get customer categories for a third party.
postSocieteAccount($id, $site, $request_data=null)
Create and attach a new (or replace an existing) specific site account for a third party.
deleteSupplierCategory($id, $category_id)
Remove the link between a category and the third party.
createFixedAmountDiscount($id, $request_data=null)
Create a fixed amount discount for a thirdparty.
deleteRepresentative($id, $representative_id)
Remove the link between a customer representative and a third party.
createCompanyNotification($id, $request_data=null)
Create a company notification for a third party.
putSocieteAccount($id, $site, $request_data=null)
Update specified values of a specific account attached to a third party.
updateCompanyBankAccount($id, $bankaccount_id, $request_data=null)
Update a company bank account of a third party.
deleteSocieteAccount($id, $site)
Delete a specific site account attached to a third party.
getInvoicesQualifiedForCreditNote($id)
Return invoices qualified to be corrected by a credit note.
getOutStandingProposals($id, $mode='customer')
Get outstanding proposals for a third party.
_fetch($rowid, $ref='', $ref_ext='', $barcode='', $idprof1='', $idprof2='', $idprof3='', $idprof4='', $idprof5='', $idprof6='', $email='', $ref_alias='')
Fetch properties of a thirdparty object.
getSalesRepresentatives($id, $mode=0)
Get representatives of a third party.
getOutStandingInvoices($id, $mode='customer')
Get outstanding invoices for a third party.
splitdiscount($id, $discountid, $amount_ttc_1, $amount_ttc_2)
Split a discount in 2 smaller discount.
index($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0, $mode=0, $category=0, $sqlfilters='', $properties='', $pagination_data=false)
List third parties.
deleteCompanyBankAccount($id, $bankaccount_id)
Delete a bank account attached to a third party.
createSocieteAccount($id, $request_data=null)
Create and attach a new account to an existing third party.
createCompanyBankAccount($id, $request_data=null)
Create a company bank account for a third party.
deleteCategory($id, $category_id)
Remove the link between a customer category and the third party.
Class to manage translations.
Class to manage Dolibarr users.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0, $forbiddenfields=array())
forgeSQLFromUniversalSearchCriteria
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
sanitizeVal($out='', $check='alphanohtml', $filter=null, $options=null)
Return a sanitized or empty value after checking value against a rule.
isModEnabled($module)
Is Dolibarr module enabled.
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
dolDecrypt($chain, $key='', $patterntotest='')
Decode a string with a symmetric encryption.