dolibarr 25.0.0-alpha
api_expensereports.class.php
1<?php
2/* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
3 * Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2020-2025 Frédéric France <frederic.france@free.fr>
5 * Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
6 * Copyright (C) 2025 William Mead <william@m34d.com>
7 * Copyright (C) 2025 Kowal Jessica <jessicakowal69@gmail.com>
8 * Copyright (C) 2026 Charlene Benke <charlene@patas-monkey.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
24use Luracast\Restler\RestException;
25
26require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
27require_once DOL_DOCUMENT_ROOT.'/expensereport/class/paymentexpensereport.class.php';
28require_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
29
39{
43 public static $FIELDS = array(
44 'fk_user_author',
45 'date_debut',
46 'date_fin',
47 );
48
52 public static $FIELDSLINE = array(
53 'date',
54 'fk_c_type_fees',
55 'qty',
56 'value_unit',
57 'vatrate'
58 );
59
63 public static $FIELDSPAYMENT = array(
64 "fk_typepayment",
65 'datep',
66 'amounts',
67 );
68
72 public $expensereport;
73
74
78 public function __construct()
79 {
80 global $db;
81
82 $this->db = $db;
83 $this->expensereport = new ExpenseReport($this->db);
84 }
85
98 public function get($id)
99 {
100 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'lire')) {
101 throw new RestException(403);
102 }
103
104 $result = $this->expensereport->fetch($id);
105 if (!$result) {
106 throw new RestException(404, 'Expense report not found');
107 }
108
109 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
110 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
111 }
112
113 $this->expensereport->fetchObjectLinked();
114 return $this->_cleanObjectDatas($this->expensereport);
115 }
116
138 public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $user_ids = '', $sqlfilters = '', $properties = '', $pagination_data = false)
139 {
140 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'lire')) {
141 throw new RestException(403);
142 }
143
144 $obj_ret = array();
145
146 // case of external user, $societe param is ignored and replaced by user's socid
147 //$socid = DolibarrApiAccess::$user->socid ?: $societe;
148
149 $sql = "SELECT t.rowid";
150 $sql .= " FROM ".MAIN_DB_PREFIX."expensereport AS t LEFT JOIN ".MAIN_DB_PREFIX."expensereport_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields
151 $sql .= ' WHERE t.entity IN ('.getEntity('expensereport').')';
152 if ($user_ids) {
153 $sql .= " AND t.fk_user_author IN (".$this->db->sanitize($user_ids).")";
154 }
155 // $user_ids is provided by the caller, so it can not be the only owner filter. Narrow the result
156 // set on the hierarchy of the caller, with the same condition as expensereport/list.php.
157 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'readall')
158 && (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || !DolibarrApiAccess::$user->hasRight('expensereport', 'writeall_advance'))) {
159 $childids = DolibarrApiAccess::$user->getAllChildIds(1);
160 $sql .= " AND t.fk_user_author IN (".$this->db->sanitize(implode(',', $childids)).")";
161 }
162
163 // Add sql filters
164 if ($sqlfilters) {
165 $errormessage = '';
166 $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
167 if ($errormessage) {
168 throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
169 }
170 }
171
172 //this query will return total orders with the filters given
173 $sqlTotals = str_replace('SELECT t.rowid', 'SELECT count(t.rowid) as total', $sql);
174
175 $sql .= $this->db->order($sortfield, $sortorder);
176 if ($limit) {
177 if ($page < 0) {
178 $page = 0;
179 }
180 $offset = $limit * $page;
181
182 $sql .= $this->db->plimit($limit + 1, $offset);
183 }
184
185 $result = $this->db->query($sql);
186
187 if ($result) {
188 $num = $this->db->num_rows($result);
189 $min = min($num, ($limit <= 0 ? $num : $limit));
190 $i = 0;
191 while ($i < $min) {
192 $obj = $this->db->fetch_object($result);
193 $expensereport_static = new ExpenseReport($this->db);
194 if ($expensereport_static->fetch($obj->rowid)) {
195 $obj_ret[] = $this->_filterObjectProperties($this->_cleanObjectDatas($expensereport_static), $properties);
196 }
197 $i++;
198 }
199 } else {
200 throw new RestException(503, 'Error when retrieve Expense Report list : '.$this->db->lasterror());
201 }
202
203 //if $pagination_data is true the response will contain element data with all values and element pagination with pagination data(total,page,limit)
204 if ($pagination_data) {
205 $totalsResult = $this->db->query($sqlTotals);
206 $total = $this->db->fetch_object($totalsResult)->total;
207
208 $tmp = $obj_ret;
209 $obj_ret = [];
210
211 $obj_ret['data'] = $tmp;
212 $obj_ret['pagination'] = [
213 'total' => (int) $total,
214 'page' => $page, //count starts from 0
215 'page_count' => ceil((int) $total / $limit),
216 'limit' => $limit
217 ];
218 }
219
220 return $obj_ret;
221 }
222
235 public function post($request_data = null)
236 {
237 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'creer')) {
238 throw new RestException(403, "Insufficiant rights");
239 }
240
241 // Check mandatory fields
242 $result = $this->_validate($request_data);
243
244 foreach ($request_data as $field => $value) {
245 if ($field === 'caller') {
246 // 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
247 $this->expensereport->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
248 continue;
249 }
250
251 if ($field == 'array_options' && is_array($value)) {
252 foreach ($value as $index => $val) {
253 $this->expensereport->array_options[$index] = $this->_checkValExtrafieldsForAPI($index, $val, $this->expensereport);
254 }
255 continue;
256 }
257
258 if (!in_array($field, array('fk_statut', 'fk_user_approve'))) { // Exclude properties that must be set by other workflow methods
259 $this->expensereport->$field = $this->_checkValForAPI($field, $value, $this->expensereport);
260 }
261 }
262 /*if (isset($request_data["lines"])) {
263 $lines = array();
264 foreach ($request_data["lines"] as $line) {
265 array_push($lines, (object) $line);
266 }
267 $this->expensereport->lines = $lines;
268 }*/
269 if ($this->expensereport->create(DolibarrApiAccess::$user) < 0) {
270 throw new RestException(500, "Error creating expensereport", array_merge(array($this->expensereport->error), $this->expensereport->errors));
271 }
272
273 return $this->expensereport->id;
274 }
275
292 public function getLines($id)
293 {
294 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'lire')) {
295 throw new RestException(403);
296 }
297
298 $result = $this->expensereport->fetch($id);
299 if (!$result) {
300 throw new RestException(404, 'Expense report not found');
301 }
302
303 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
304 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
305 }
306 $this->expensereport->fetch_lines();
307 $result = array();
308 foreach ($this->expensereport->lines as $line) {
309 $result[] = $this->_cleanObjectDatas($line);
310 }
311 return $result;
312 }
313
330 public function postLine($id, $request_data = null)
331 {
332 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'creer')) {
333 throw new RestException(403);
334 }
335
336 $result = $this->_validateLine($request_data);
337
338 $result = $this->expensereport->fetch($id);
339 if (!$result) {
340 throw new RestException(404, 'Expense report not found');
341 }
342
343 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
344 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
345 }
346
347 if ($this->expensereport->status != ExpenseReport::STATUS_DRAFT) {
348 throw new RestException(403, 'Expense report must be in draft status to add lines');
349 }
350
351 $request_data = (object) $request_data;
352
353 $request_data->comments = sanitizeVal($request_data->comments, 'restricthtml');
354
355 $result = $this->expensereport->addline(
356 $request_data->qty,
357 $request_data->value_unit,
358 (int) $request_data->fk_c_type_fees,
359 $request_data->vatrate,
360 $request_data->date,
361 $request_data->comments,
362 $request_data->fk_project,
363 (int) $request_data->fk_c_exp_tax_cat,
364 $request_data->type,
365 $request_data->fk_ecm_files
366 );
367
368 if ($result > 0) {
369 return $result;
370 } else {
371 throw new RestException(500, 'Error adding line to expense report: '.$this->expensereport->errorsToString());
372 }
373 }
374
394 public function putLine($id, $lineid, $request_data = null)
395 {
396 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'creer')) {
397 throw new RestException(403);
398 }
399
400 $result = $this->expensereport->fetch($id);
401 if (!$result) {
402 throw new RestException(404, 'Expense report not found');
403 }
404
405 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
406 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
407 }
408
409 if ($this->expensereport->status != ExpenseReport::STATUS_DRAFT) {
410 throw new RestException(403, 'Expense report must be in draft status to update lines');
411 }
412
413 $line = new ExpenseReportLine($this->db);
414 $result = $line->fetch($lineid);
415 if ($result <= 0) {
416 throw new RestException(404, 'Expense report line not found');
417 }
418
419 $request_data = (object) $request_data;
420
421 $request_data->comments = sanitizeVal($request_data->comments, 'restricthtml');
422
423 $updateRes = $this->expensereport->updateline(
424 $lineid,
425 (int) $request_data->fk_c_type_fees,
426 $request_data->fk_project,
427 $request_data->vatrate,
428 $request_data->comments,
429 $request_data->qty,
430 $request_data->value_unit,
431 $request_data->date,
432 $id,
433 (int) $request_data->fk_c_exp_tax_cat,
434 $request_data->fk_ecm_files
435 );
436
437 if ($updateRes > 0) {
438 $result = $this->get($id);
439 unset($result->line);
440 return $this->_cleanObjectDatas($result);
441 } else {
442 throw new RestException(500, 'Error updating line: '.$this->expensereport->errorsToString());
443 }
444 }
445
462 public function deleteLine($id, $lineid)
463 {
464 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'creer')) {
465 throw new RestException(403);
466 }
467
468 $result = $this->expensereport->fetch($id);
469 if (!$result) {
470 throw new RestException(404, 'Expense report not found');
471 }
472
473 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
474 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
475 }
476
477 // Check if line exists
478 $lineExists = false;
479 $this->expensereport->fetch_lines();
480 foreach ($this->expensereport->lines as $line) {
481 if ($line->id == $lineid) {
482 $lineExists = true;
483 break;
484 }
485 }
486
487 if (!$lineExists) {
488 throw new RestException(404, 'Line not found');
489 }
490
491 if ($this->expensereport->status != ExpenseReport::STATUS_DRAFT) {
492 throw new RestException(403, 'Expense report must be in draft status to delete lines');
493 }
494
495 $result = $this->expensereport->deleteLine($lineid);
496 if ($result > 0) {
497 return $this->get($id);
498 } else {
499 throw new RestException(500, 'Error deleting line: '.$this->expensereport->errorsToString());
500 }
501 }
502
520 public function put($id, $request_data = null)
521 {
522 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'creer')) {
523 throw new RestException(403);
524 }
525
526 $result = $this->expensereport->fetch($id);
527 if (!$result) {
528 throw new RestException(404, 'Expense report not found');
529 }
530
531 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
532 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
533 }
534 foreach ($request_data as $field => $value) {
535 if ($field == 'id') {
536 continue;
537 }
538 if ($field === 'caller') {
539 // 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
540 $this->expensereport->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
541 continue;
542 }
543
544 if ($field == 'array_options' && is_array($value)) {
545 foreach ($value as $index => $val) {
546 $this->expensereport->array_options[$index] = $this->_checkValExtrafieldsForAPI($index, $val, $this->expensereport);
547 }
548 continue;
549 }
550
551 if (!in_array($field, array('fk_statut', 'fk_user_approve'))) { // Exclude properties that must be set by other workflow methods
552 $this->expensereport->$field = $this->_checkValForAPI($field, $value, $this->expensereport);
553 }
554 }
555
556 if ($this->expensereport->update(DolibarrApiAccess::$user) > 0) {
557 return $this->get($id);
558 } else {
559 throw new RestException(500, $this->expensereport->errorsToString());
560 }
561 }
562
575 public function delete($id)
576 {
577 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'supprimer')) {
578 throw new RestException(403);
579 }
580
581 $result = $this->expensereport->fetch($id);
582 if (!$result) {
583 throw new RestException(404, 'Expense report not found');
584 }
585
586 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
587 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
588 }
589
590 if (!$this->expensereport->delete(DolibarrApiAccess::$user)) {
591 throw new RestException(500, 'Error when delete Expense Report : '.$this->expensereport->errorsToString());
592 }
593
594 return array(
595 'success' => array(
596 'code' => 200,
597 'message' => 'Expense Report deleted'
598 )
599 );
600 }
601
617 public function setToDraft($id)
618 {
619 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'creer')) {
620 throw new RestException(403, "Insufficiant rights");
621 }
622 $result = $this->expensereport->fetch($id);
623 if (!$result) {
624 throw new RestException(404, 'Expense report not found');
625 }
626
627 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
628 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
629 }
630
631 $result = $this->expensereport->setStatut(ExpenseReport::STATUS_DRAFT);
632 if ($result == 0) {
633 throw new RestException(304, 'Error nothing done. May be object is already draft');
634 }
635 if ($result < 0) {
636 throw new RestException(500, 'Error when setting to draft expense report: '.$this->expensereport->errorsToString());
637 }
638
639 return $this->_cleanObjectDatas($this->expensereport);
640 }
641
661 public function validate($id, $notrigger = 0)
662 {
663 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'creer')) {
664 throw new RestException(403, "Insufficiant rights");
665 }
666 $result = $this->expensereport->fetch($id);
667 if (!$result) {
668 throw new RestException(404, 'Expense report not found');
669 }
670
671 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
672 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
673 }
674
675 $result = $this->expensereport->setValidate(DolibarrApiAccess::$user, $notrigger);
676 if ($result == 0) {
677 throw new RestException(304, 'Error nothing done. May be object is already validated');
678 }
679 if ($result < 0) {
680 throw new RestException(500, 'Error when validating expense report: '.$this->expensereport->errorsToString());
681 }
682
683 return $this->_cleanObjectDatas($this->expensereport);
684 }
685
686
706 public function approve($id, $notrigger = 0)
707 {
708 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'approve')) {
709 throw new RestException(403, "Insufficiant rights");
710 }
711 $result = $this->expensereport->fetch($id);
712 if (!$result) {
713 throw new RestException(404, 'Expense report not found');
714 }
715
716 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
717 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
718 }
719
720 $result = $this->expensereport->setApproved(DolibarrApiAccess::$user, $notrigger);
721 if ($result == 0) {
722 throw new RestException(304, 'Error nothing done. May be object is already approved');
723 }
724 if ($result < 0) {
725 throw new RestException(500, 'Error when approving expense report: '.$this->expensereport->errorsToString());
726 }
727
728 return $this->_cleanObjectDatas($this->expensereport);
729 }
730
731
752 public function deny($id, $details, $notrigger = 0)
753 {
754 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'approve')) {
755 throw new RestException(403, "Insufficiant rights");
756 }
757 $result = $this->expensereport->fetch($id);
758 if (!$result) {
759 throw new RestException(404, 'Expense report not found');
760 }
761
762 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
763 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
764 }
765
766 $result = $this->expensereport->setDeny(DolibarrApiAccess::$user, $details, $notrigger);
767 if ($result == 0) {
768 throw new RestException(304, 'Error nothing done. May be object is already denied');
769 }
770 if ($result < 0) {
771 throw new RestException(500, 'Error when denying expense report: '.$this->expensereport->errorsToString());
772 }
773
774
775
776 return $this->_cleanObjectDatas($this->expensereport);
777 }
778
798 public function setPaid($id, $notrigger = 0)
799 {
800 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'to_paid')) {
801 throw new RestException(403, "Insufficiant rights");
802 }
803 $result = $this->expensereport->fetch($id);
804 if (!$result) {
805 throw new RestException(404, 'Expense report not found');
806 }
807
808 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
809 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
810 }
811
812 $result = $this->expensereport->setPaid($id, DolibarrApiAccess::$user, $notrigger);
813 if ($result == 0) {
814 throw new RestException(304, 'Error nothing done. May be object is already approved');
815 }
816 if ($result < 0) {
817 throw new RestException(500, 'Error when approving expense report: '.$this->expensereport->errorsToString());
818 }
819
820 return $this->_cleanObjectDatas($this->expensereport);
821 }
822
840 public function cancel($id, $detail, $notrigger = 0)
841 {
842 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'creer')) {
843 throw new RestException(403, "Insufficiant rights");
844 }
845 $result = $this->expensereport->fetch($id);
846 if (!$result) {
847 throw new RestException(404, 'Expense report not found');
848 }
849
850 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
851 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
852 }
853
854 if ($this->expensereport->status == ExpenseReport::STATUS_CANCELED) {
855 throw new RestException(403, 'Expense report already canceled');
856 }
857 $result = $this->expensereport->set_cancel(DolibarrApiAccess::$user, $detail, $notrigger);
858 if ($result < 0) {
859 throw new RestException(500, 'Error when cancelling expense report: '.$this->expensereport->errorsToString());
860 }
861
862 $result = $this->expensereport->fetch($id);
863 return $this->_cleanObjectDatas($this->expensereport);
864 }
865
883 public function getAllPayments($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0)
884 {
885 $list = array();
886
887 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'lire')) {
888 throw new RestException(403);
889 }
890
891 $sql = "SELECT t.rowid FROM " . MAIN_DB_PREFIX . "payment_expensereport as t, ".MAIN_DB_PREFIX."expensereport as e";
892 $sql .= " WHERE e.rowid = t.fk_expensereport";
893 $sql .= ' AND e.entity IN ('.getEntity('expensereport').')';
894
895 // Restrict to payments of expense reports the user is allowed to see
896 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'readall')) {
897 $childids = DolibarrApiAccess::$user->getAllChildIds(1);
898 $sql .= " AND e.fk_user_author IN (".$this->db->sanitize(implode(',', $childids)).")";
899 }
900
901 $sql .= $this->db->order($sortfield, $sortorder);
902 if ($limit) {
903 if ($page < 0) {
904 $page = 0;
905 }
906 $offset = $limit * $page;
907
908 $sql .= $this->db->plimit($limit + 1, $offset);
909 }
910
911 dol_syslog("API Rest request");
912 $result = $this->db->query($sql);
913
914 if ($result) {
915 $num = $this->db->num_rows($result);
916 $min = min($num, ($limit <= 0 ? $num : $limit));
917 for ($i = 0; $i < $min; $i++) {
918 $obj = $this->db->fetch_object($result);
919 $paymentExpenseReport = new PaymentExpenseReport($this->db);
920 if ($paymentExpenseReport->fetch($obj->rowid) > 0) {
921 $list[] = $this->_cleanObjectDatas($paymentExpenseReport);
922 }
923 }
924 } else {
925 throw new RestException(503, 'Error when retrieving list of paymentexpensereport: ' . $this->db->lasterror());
926 }
927
928 return $list;
929 }
930
943 public function getPayment($pid)
944 {
945 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'lire')) {
946 throw new RestException(403);
947 }
948
949 $paymentExpenseReport = new PaymentExpenseReport($this->db);
950 $result = $paymentExpenseReport->fetch($pid);
951 if (!$result) {
952 throw new RestException(404, 'paymentExpenseReport not found');
953 }
954
955 // Check access to the parent expense report
956 $result = $this->expensereport->fetch($paymentExpenseReport->fk_expensereport);
957 if (!$result) {
958 throw new RestException(404, 'Expense report not found');
959 }
960
961 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
962 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
963 }
964
965 return $this->_cleanObjectDatas($paymentExpenseReport);
966 }
967
982 public function addPayment($id, $request_data = null)
983 {
984 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'creer')) {
985 throw new RestException(403);
986 }
987 // Check mandatory fields
988 $result = $this->_validatepayment($request_data);
989
990 if (isModEnabled("bank") && !((int) ($request_data['accountid'] ?? 0) > 0)) {
991 throw new RestException(400, "accountid field missing");
992 }
993
994 // Check access to the parent expense report
995 $result = $this->expensereport->fetch($id);
996 if ($result <= 0) {
997 throw new RestException(404, 'Expense report not found');
998 }
999
1000 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
1001 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1002 }
1003
1004 $paymentExpenseReport = new PaymentExpenseReport($this->db);
1005 $paymentExpenseReport->fk_expensereport = $id;
1006 foreach ($request_data as $field => $value) {
1007 $paymentExpenseReport->$field = $this->_checkValForAPI($field, $value, $paymentExpenseReport);
1008 }
1009
1010 // Same sequence as expensereport/payment/payment.php: all or nothing
1011 $this->db->begin();
1012
1013 if ($paymentExpenseReport->create(DolibarrApiAccess::$user) < 0) {
1014 $this->db->rollback();
1015 throw new RestException(400, 'Payment error : '.$paymentExpenseReport->errorsToString());
1016 }
1017 if (isModEnabled("bank")) {
1018 $result = $paymentExpenseReport->addPaymentToBank(
1019 DolibarrApiAccess::$user,
1020 'payment_expensereport',
1021 '(ExpenseReportPayment)',
1022 (int) $request_data['accountid'],
1023 '',
1024 ''
1025 );
1026 if ($result <= 0) {
1027 $this->db->rollback();
1028 throw new RestException(400, 'Add payment to bank error : '.$paymentExpenseReport->errorsToString());
1029 }
1030 }
1031
1032 $remaintopay = price2num($this->expensereport->total_ttc - $this->expensereport->getSumPayments(), 'MT');
1033 if ($remaintopay == 0 && $this->expensereport->setPaid($this->expensereport->id, DolibarrApiAccess::$user) < 0) {
1034 $this->db->rollback();
1035 throw new RestException(400, 'Set paid error : '.$this->expensereport->errorsToString());
1036 }
1037
1038 $this->db->commit();
1039
1040 return $paymentExpenseReport->id;
1041 }
1042
1058 public function updatePayment($id, $idp, $request_data = null)
1059 {
1060 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'creer')) {
1061 throw new RestException(403);
1062 }
1063
1064 $paymentExpenseReport = new PaymentExpenseReport($this->db);
1065 $result = $paymentExpenseReport->fetch($idp);
1066 if (!$result) {
1067 throw new RestException(404, 'Payment of expense report not found');
1068 }
1069
1070 // Check ids
1071 if ($id != $paymentExpenseReport->fk_expensereport) {
1072 throw new RestException(404, 'Payment id does not belongs to the Expense id');
1073 }
1074
1075 // Check access to the parent expense report
1076 $result = $this->expensereport->fetch($paymentExpenseReport->fk_expensereport);
1077 if (!$result) {
1078 throw new RestException(404, 'Expense report not found');
1079 }
1080
1081 if (!DolibarrApi::_checkAccessToResource('expensereport', $this->expensereport)) {
1082 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1083 }
1084
1085 foreach ($request_data as $field => $value) {
1086 if ($field == 'id') {
1087 continue;
1088 }
1089 $paymentExpenseReport->$field = $this->_checkValForAPI($field, $value, $paymentExpenseReport);
1090 }
1091
1092 if ($paymentExpenseReport->update(DolibarrApiAccess::$user) > 0) {
1093 return $this->getPayment($idp);
1094 } else {
1095 throw new RestException(500, $paymentExpenseReport->errorsToString());
1096 }
1097 }
1098
1107 /*public function delete($id, $idp)
1108 {
1109 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'creer') {
1110 throw new RestException(403);
1111 }
1112 $paymentExpenseReport = new PaymentExpenseReport($this->db);
1113 $result = $paymentExpenseReport->fetch($idp);
1114 if (!$result) {
1115 throw new RestException(404, 'paymentExpenseReport not found');
1116 }
1117
1118 if ($paymentExpenseReport->delete(DolibarrApiAccess::$user) < 0) {
1119 throw new RestException(403, 'error when deleting paymentExpenseReport');
1120 }
1121
1122 return array(
1123 'success' => array(
1124 'code' => 200,
1125 'message' => 'paymentExpenseReport deleted'
1126 )
1127 );
1128 }*/
1129
1130
1131
1132 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1142 protected function _cleanObjectDatas($object)
1143 {
1144 // phpcs:enable
1145 $object = parent::_cleanObjectDatas($object);
1146
1147 unset($object->fk_statut);
1148 unset($object->statut);
1149 unset($object->user);
1150 unset($object->thirdparty);
1151
1152 unset($object->cond_reglement);
1153 unset($object->shipping_method_id);
1154
1155 unset($object->barcode_type);
1156 unset($object->barcode_type_code);
1157 unset($object->barcode_type_label);
1158 unset($object->barcode_type_coder);
1159
1160 unset($object->code_paiement);
1161 unset($object->code_statut);
1162 unset($object->fk_c_paiement);
1163 unset($object->fk_incoterms);
1164 unset($object->label_incoterms);
1165 unset($object->location_incoterms);
1166 unset($object->mode_reglement_id);
1167 unset($object->cond_reglement_id);
1168
1169 unset($object->name);
1170 unset($object->lastname);
1171 unset($object->firstname);
1172 unset($object->civility_id);
1173 unset($object->cond_reglement_id);
1174 unset($object->contact);
1175 unset($object->contact_id);
1176
1177 unset($object->state);
1178 unset($object->state_id);
1179 unset($object->state_code);
1180 unset($object->country);
1181 unset($object->country_id);
1182 unset($object->country_code);
1183
1184 unset($object->note); // We already use note_public and note_pricate
1185
1186 return $object;
1187 }
1188
1196 private function _validate($data)
1197 {
1198 if ($data === null) {
1199 $data = array();
1200 }
1201 $expensereport = array();
1202 foreach (ExpenseReports::$FIELDS as $field) {
1203 if (!isset($data[$field])) {
1204 throw new RestException(400, "$field field missing");
1205 }
1206 $expensereport[$field] = $data[$field];
1207 }
1208 return $expensereport;
1209 }
1210
1218 private function _validatepayment($data)
1219 {
1220 if ($data === null) {
1221 $data = array();
1222 }
1223 $expensereport = array();
1224 foreach (ExpenseReports::$FIELDSPAYMENT as $field) {
1225 if (!isset($data[$field])) {
1226 throw new RestException(400, "$field field missing");
1227 }
1228 $expensereport[$field] = $data[$field];
1229 }
1230 return $expensereport;
1231 }
1232
1241 private function _validateLine($data)
1242 {
1243 if ($data === null) {
1244 $data = array();
1245 }
1246 $expenseReport = array();
1247 foreach (ExpenseReports::$FIELDSLINE as $field) {
1248 if (!isset($data[$field])) {
1249 throw new RestException(400, "$field field missing");
1250 }
1251 $expenseReport[$field] = $data[$field];
1252 }
1253 return $expenseReport;
1254 }
1255}
$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 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 Trips and Expenses.
const STATUS_DRAFT
Draft status.
const STATUS_CANCELED
Classified canceled.
Class of expense report details lines.
deny($id, $details, $notrigger=0)
Deny an expense report.
_cleanObjectDatas($object)
Delete paymentExpenseReport.
_validate($data)
Validate fields before create or update object.
updatePayment($id, $idp, $request_data=null)
Update a payment of an expense report.
setPaid($id, $notrigger=0)
Set to paid an expense report.
validate($id, $notrigger=0)
Validate an expense report.
deleteLine($id, $lineid)
Delete a line from an expense report.
getLines($id)
Get lines of an expense report.
approve($id, $notrigger=0)
Approve an expense report.
put($id, $request_data=null)
Update expense report general fields.
cancel($id, $detail, $notrigger=0)
Cancel an expense report.
getPayment($pid)
Get an expense report payment.
addPayment($id, $request_data=null)
Create a payment for an expense report.
getAllPayments($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0)
Get the list of payments of an expense report.
post($request_data=null)
Create an expense report.
_validatepayment($data)
Validate fields before create or update object.
_validateLine($data)
Validate fields before create or update object.
setToDraft($id)
Set an expense report to draft.
putLine($id, $lineid, $request_data=null)
Update a line of an expense report.
index($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0, $user_ids='', $sqlfilters='', $properties='', $pagination_data=false)
List expense reports.
postLine($id, $request_data=null)
Add a line to an expense report.
Class to manage payments of expense report.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
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.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.