24use Luracast\Restler\RestException;
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';
43 public static $FIELDS = array(
52 public static $FIELDSLINE = array(
63 public static $FIELDSPAYMENT = array(
72 public $expensereport;
77 public static $FIELDSNOTUPDATABLE = array(
78 'fk_statut',
'status',
'statut',
'paid',
79 'fk_user_valid',
'fk_user_approve',
'fk_user_refuse',
'fk_user_cancel',
'fk_user_creat',
'fk_user_modif',
80 'date_valid',
'date_approve',
'date_refuse',
'date_cancel',
'detail_refuse',
'detail_cancel',
81 'total_ht',
'total_tva',
'total_ttc',
'total_localtax1',
'total_localtax2',
111 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'lire')) {
112 throw new RestException(403);
115 $result = $this->expensereport->fetch(
$id);
117 throw new RestException(404,
'Expense report not found');
121 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
124 $this->expensereport->fetchObjectLinked();
149 public function index($sortfield =
"t.rowid", $sortorder =
'ASC', $limit = 100, $page = 0, $user_ids =
'', $sqlfilters =
'', $properties =
'', $pagination_data =
false)
151 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'lire')) {
152 throw new RestException(403);
160 $sql =
"SELECT t.rowid";
161 $sql .=
" FROM ".MAIN_DB_PREFIX.
"expensereport AS t LEFT JOIN ".MAIN_DB_PREFIX.
"expensereport_extrafields AS ef ON (ef.fk_object = t.rowid)";
162 $sql .=
' WHERE t.entity IN ('.getEntity(
'expensereport').
')';
164 $sql .=
" AND t.fk_user_author IN (".$this->db->sanitize($user_ids).
")";
168 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'readall')
169 && (!
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') || !DolibarrApiAccess::$user->hasRight(
'expensereport',
'writeall_advance'))) {
170 $childids = DolibarrApiAccess::$user->getAllChildIds(1);
171 $sql .=
" AND t.fk_user_author IN (".$this->db->sanitize(implode(
',', $childids)).
")";
179 throw new RestException(400,
'Error when validating parameter sqlfilters -> '.$errormessage);
184 $sqlTotals = str_replace(
'SELECT t.rowid',
'SELECT count(t.rowid) as total', $sql);
186 $sql .= $this->db->order($sortfield, $sortorder);
191 $offset = $limit * $page;
193 $sql .= $this->db->plimit($limit + 1, $offset);
196 $result = $this->db->query($sql);
199 $num = $this->db->num_rows($result);
200 $min = min($num, ($limit <= 0 ? $num : $limit));
203 $obj = $this->db->fetch_object($result);
205 if ($expensereport_static->fetch($obj->rowid)) {
211 throw new RestException(503,
'Error when retrieve Expense Report list : '.$this->db->lasterror());
215 if ($pagination_data) {
216 $totalsResult = $this->db->query($sqlTotals);
217 $total = $this->db->fetch_object($totalsResult)->total;
222 $obj_ret[
'data'] = $tmp;
223 $obj_ret[
'pagination'] = [
224 'total' => (int) $total,
226 'page_count' => ceil((
int) $total / $limit),
246 public function post($request_data =
null)
248 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'creer')) {
249 throw new RestException(403,
"Insufficiant rights");
253 $result = $this->
_validate($request_data);
256 $fk_user_author = (int) ($request_data[
'fk_user_author'] ?? 0);
257 if ($fk_user_author > 0 && $fk_user_author != DolibarrApiAccess::$user->
id
258 && (!
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') || !DolibarrApiAccess::$user->hasRight(
'expensereport',
'writeall_advance'))
259 && !in_array($fk_user_author, DolibarrApiAccess::$user->getAllChildIds(1))) {
260 throw new RestException(403,
'User '.$fk_user_author.
' is not in the hierarchy of login '.DolibarrApiAccess::$user->login);
263 foreach (ExpenseReports::$FIELDSNOTUPDATABLE as $field) {
264 unset($request_data[$field]);
267 foreach ($request_data as $field => $value) {
268 if ($field ===
'caller') {
270 $this->expensereport->context[
'caller'] =
sanitizeVal($request_data[
'caller'],
'aZ09');
274 if ($field ==
'array_options' && is_array($value)) {
275 foreach ($value as $index => $val) {
281 if (!in_array($field, array(
'fk_statut',
'fk_user_approve'))) {
282 $this->expensereport->$field = $this->
_checkValForAPI($field, $value, $this->expensereport);
292 if ($this->expensereport->create(DolibarrApiAccess::$user) < 0) {
293 throw new RestException(500,
"Error creating expensereport", array_merge(array($this->expensereport->error), $this->expensereport->errors));
296 return $this->expensereport->id;
317 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'lire')) {
318 throw new RestException(403);
321 $result = $this->expensereport->fetch(
$id);
323 throw new RestException(404,
'Expense report not found');
327 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
329 $this->expensereport->fetch_lines();
331 foreach ($this->expensereport->lines as $line) {
355 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'creer')) {
356 throw new RestException(403);
361 $result = $this->expensereport->fetch(
$id);
363 throw new RestException(404,
'Expense report not found');
367 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
371 throw new RestException(403,
'Expense report must be in draft status to add lines');
374 $request_data = (object) $request_data;
376 $request_data->comments =
sanitizeVal($request_data->comments,
'restricthtml');
378 $result = $this->expensereport->addline(
380 $request_data->value_unit,
381 (
int) $request_data->fk_c_type_fees,
382 $request_data->vatrate,
384 $request_data->comments,
385 $request_data->fk_project,
386 (
int) $request_data->fk_c_exp_tax_cat,
388 $request_data->fk_ecm_files
394 throw new RestException(500,
'Error adding line to expense report: '.$this->expensereport->error);
419 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'creer')) {
420 throw new RestException(403);
423 $result = $this->expensereport->fetch(
$id);
425 throw new RestException(404,
'Expense report not found');
429 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
433 throw new RestException(403,
'Expense report must be in draft status to update lines');
437 $result = $line->fetch($lineid);
439 throw new RestException(404,
'Expense report line not found');
442 $request_data = (object) $request_data;
444 $request_data->comments =
sanitizeVal($request_data->comments,
'restricthtml');
446 $updateRes = $this->expensereport->updateline(
448 (
int) $request_data->fk_c_type_fees,
449 $request_data->fk_project,
450 $request_data->vatrate,
451 $request_data->comments,
453 $request_data->value_unit,
456 (
int) $request_data->fk_c_exp_tax_cat,
457 $request_data->fk_ecm_files
460 if ($updateRes > 0) {
461 $result = $this->
get(
$id);
462 unset($result->line);
465 throw new RestException(500,
'Error updating line: '.$this->expensereport->error);
487 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'creer')) {
488 throw new RestException(403);
491 $result = $this->expensereport->fetch(
$id);
493 throw new RestException(404,
'Expense report not found');
497 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
502 $this->expensereport->fetch_lines();
503 foreach ($this->expensereport->lines as $line) {
504 if ($line->id == $lineid) {
511 throw new RestException(404,
'Line not found');
515 throw new RestException(403,
'Expense report must be in draft status to delete lines');
518 $result = $this->expensereport->deleteLine($lineid);
520 return $this->
get(
$id);
522 throw new RestException(500,
'Error deleting line: '.$this->expensereport->error);
543 public function put(
$id, $request_data =
null)
545 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'creer')) {
546 throw new RestException(403);
549 $result = $this->expensereport->fetch(
$id);
551 throw new RestException(404,
'Expense report not found');
555 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
559 throw new RestException(403,
'Only a draft or refused expense report can be modified');
562 foreach (ExpenseReports::$FIELDSNOTUPDATABLE as $field) {
563 unset($request_data[$field]);
565 foreach ($request_data as $field => $value) {
566 if ($field ==
'id') {
569 if ($field ===
'caller') {
571 $this->expensereport->context[
'caller'] =
sanitizeVal($request_data[
'caller'],
'aZ09');
575 if ($field ==
'array_options' && is_array($value)) {
576 foreach ($value as $index => $val) {
582 if (!in_array($field, array(
'fk_statut',
'fk_user_approve'))) {
583 $this->expensereport->$field = $this->
_checkValForAPI($field, $value, $this->expensereport);
587 if ($this->expensereport->update(DolibarrApiAccess::$user) > 0) {
588 return $this->
get(
$id);
590 throw new RestException(500, $this->expensereport->error);
606 public function delete(
$id)
608 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'supprimer')) {
609 throw new RestException(403);
612 $result = $this->expensereport->fetch(
$id);
614 throw new RestException(404,
'Expense report not found');
618 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
621 if ($this->expensereport->delete(DolibarrApiAccess::$user) <= 0) {
622 throw new RestException(500,
'Error when delete Expense Report : '.$this->expensereport->error);
628 'message' =>
'Expense Report deleted'
650 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'creer')) {
651 throw new RestException(403,
"Insufficiant rights");
653 $result = $this->expensereport->fetch(
$id);
655 throw new RestException(404,
'Expense report not found');
659 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
664 throw new RestException(304,
'Error nothing done. May be object is already draft');
667 throw new RestException(500,
'Error when setting to draft expense report: '.$this->expensereport->error);
694 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'creer')) {
695 throw new RestException(403,
"Insufficiant rights");
697 $result = $this->expensereport->fetch(
$id);
699 throw new RestException(404,
'Expense report not found');
703 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
706 $result = $this->expensereport->setValidate(DolibarrApiAccess::$user, $notrigger);
708 throw new RestException(304,
'Error nothing done. May be object is already validated');
711 throw new RestException(500,
'Error when validating expense report: '.$this->expensereport->error);
739 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'approve')) {
740 throw new RestException(403,
"Insufficiant rights");
742 $result = $this->expensereport->fetch(
$id);
744 throw new RestException(404,
'Expense report not found');
748 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
751 $result = $this->expensereport->setApproved(DolibarrApiAccess::$user, $notrigger);
753 throw new RestException(304,
'Error nothing done. May be object is already approved');
756 throw new RestException(500,
'Error when approving expense report: '.$this->expensereport->error);
783 public function deny(
$id, $details, $notrigger = 0)
785 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'approve')) {
786 throw new RestException(403,
"Insufficiant rights");
788 $result = $this->expensereport->fetch(
$id);
790 throw new RestException(404,
'Expense report not found');
794 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
797 $result = $this->expensereport->setDeny(DolibarrApiAccess::$user, $details, $notrigger);
799 throw new RestException(304,
'Error nothing done. May be object is already denied');
802 throw new RestException(500,
'Error when denying expense report: '.$this->expensereport->error);
831 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'to_paid')) {
832 throw new RestException(403,
"Insufficiant rights");
834 $result = $this->expensereport->fetch(
$id);
836 throw new RestException(404,
'Expense report not found');
840 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
843 $result = $this->expensereport->setPaid(
$id, DolibarrApiAccess::$user, $notrigger);
845 throw new RestException(304,
'Error nothing done. May be object is already approved');
848 throw new RestException(500,
'Error when approving expense report: '.$this->expensereport->error);
873 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'creer')) {
874 throw new RestException(403,
"Insufficiant rights");
876 $result = $this->expensereport->fetch(
$id);
878 throw new RestException(404,
'Expense report not found');
882 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
886 throw new RestException(403,
'Expense report already canceled');
888 $result = $this->expensereport->set_cancel(DolibarrApiAccess::$user, $detail, $notrigger);
890 throw new RestException(500,
'Error when cancelling expense report: '.$this->expensereport->error);
893 $result = $this->expensereport->fetch(
$id);
914 public function getAllPayments($sortfield =
"t.rowid", $sortorder =
'ASC', $limit = 100, $page = 0)
918 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'lire')) {
919 throw new RestException(403);
922 $sql =
"SELECT t.rowid FROM " . MAIN_DB_PREFIX .
"payment_expensereport as t, ".MAIN_DB_PREFIX.
"expensereport as e";
923 $sql .=
" WHERE e.rowid = t.fk_expensereport";
924 $sql .=
' AND e.entity IN ('.getEntity(
'expensereport').
')';
927 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'readall')) {
928 $childids = DolibarrApiAccess::$user->getAllChildIds(1);
929 $sql .=
" AND e.fk_user_author IN (".$this->db->sanitize(implode(
',', $childids)).
")";
932 $sql .= $this->db->order($sortfield, $sortorder);
937 $offset = $limit * $page;
939 $sql .= $this->db->plimit($limit + 1, $offset);
943 $result = $this->db->query($sql);
946 $num = $this->db->num_rows($result);
947 $min = min($num, ($limit <= 0 ? $num : $limit));
948 for ($i = 0; $i < $min; $i++) {
949 $obj = $this->db->fetch_object($result);
951 if ($paymentExpenseReport->fetch($obj->rowid) > 0) {
956 throw new RestException(503,
'Error when retrieving list of paymentexpensereport: ' . $this->db->lasterror());
976 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'lire')) {
977 throw new RestException(403);
981 $result = $paymentExpenseReport->fetch($pid);
983 throw new RestException(404,
'paymentExpenseReport not found');
987 $result = $this->expensereport->fetch($paymentExpenseReport->fk_expensereport);
989 throw new RestException(404,
'Expense report not found');
993 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
1015 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'to_paid')) {
1016 throw new RestException(403);
1021 if (
isModEnabled(
"bank") && !((
int) ($request_data[
'accountid'] ?? 0) > 0)) {
1022 throw new RestException(400,
"accountid field missing");
1026 $result = $this->expensereport->fetch(
$id);
1028 throw new RestException(404,
'Expense report not found');
1032 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
1036 $paymentExpenseReport->fk_expensereport =
$id;
1037 foreach ($request_data as $field => $value) {
1038 $paymentExpenseReport->$field = $this->
_checkValForAPI($field, $value, $paymentExpenseReport);
1043 throw new RestException(400,
'Expense report must be approved to be paid');
1046 foreach ((array) $paymentExpenseReport->amounts as $value) {
1047 $totalpayment += (float)
price2num($value,
'MT');
1049 $remaintopay = (float)
price2num($this->expensereport->total_ttc - $this->expensereport->getSumPayments(),
'MT');
1050 if ((
float)
price2num($totalpayment,
'MT') > $remaintopay) {
1051 throw new RestException(400,
'Payment higher than remainder to pay ('.$remaintopay.
')');
1057 if ($paymentExpenseReport->create(DolibarrApiAccess::$user) < 0) {
1058 $this->db->rollback();
1059 throw new RestException(400,
'Payment error : '.$paymentExpenseReport->errorsToString());
1062 $result = $paymentExpenseReport->addPaymentToBank(
1063 DolibarrApiAccess::$user,
1064 'payment_expensereport',
1065 '(ExpenseReportPayment)',
1066 (
int) $request_data[
'accountid'],
1071 $this->db->rollback();
1072 throw new RestException(400,
'Add payment to bank error : '.$paymentExpenseReport->errorsToString());
1076 $remaintopay =
price2num($this->expensereport->total_ttc - $this->expensereport->getSumPayments(),
'MT');
1077 if ($remaintopay == 0 && $this->expensereport->setPaid($this->expensereport->id, DolibarrApiAccess::$user) < 0) {
1078 $this->db->rollback();
1079 throw new RestException(400,
'Set paid error : '.$this->expensereport->errorsToString());
1082 $this->db->commit();
1084 return $paymentExpenseReport->id;
1104 if (!DolibarrApiAccess::$user->hasRight(
'expensereport',
'to_paid')) {
1105 throw new RestException(403);
1109 $result = $paymentExpenseReport->fetch($idp);
1111 throw new RestException(404,
'Payment of expense report not found');
1115 if (
$id != $paymentExpenseReport->fk_expensereport) {
1116 throw new RestException(404,
'Payment id does not belongs to the Expense id');
1120 $result = $this->expensereport->fetch($paymentExpenseReport->fk_expensereport);
1122 throw new RestException(404,
'Expense report not found');
1126 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
1130 $result = $this->expensereport->fetch($paymentExpenseReport->fk_expensereport);
1132 throw new RestException(404,
'Expense report not found');
1136 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
1139 foreach ($request_data as $field => $value) {
1140 if ($field ==
'id' || $field ==
'fk_expensereport') {
1143 $paymentExpenseReport->$field = $this->
_checkValForAPI($field, $value, $paymentExpenseReport);
1148 $oldpayment->fetch($paymentExpenseReport->id);
1149 $remaintopay = (float)
price2num($this->expensereport->total_ttc - $this->expensereport->getSumPayments() + (float) $oldpayment->amount,
'MT');
1150 if ((
float)
price2num($paymentExpenseReport->amount,
'MT') > $remaintopay) {
1151 throw new RestException(400,
'Payment higher than remainder to pay ('.$remaintopay.
')');
1154 if ($paymentExpenseReport->update(DolibarrApiAccess::$user) > 0) {
1157 throw new RestException(500, $paymentExpenseReport->error);
1214 unset(
$object->cond_reglement);
1215 unset(
$object->shipping_method_id);
1218 unset(
$object->barcode_type_code);
1219 unset(
$object->barcode_type_label);
1220 unset(
$object->barcode_type_coder);
1222 unset(
$object->code_paiement);
1224 unset(
$object->fk_c_paiement);
1226 unset(
$object->label_incoterms);
1227 unset(
$object->location_incoterms);
1228 unset(
$object->mode_reglement_id);
1229 unset(
$object->cond_reglement_id);
1235 unset(
$object->cond_reglement_id);
1260 if ($data ===
null) {
1263 $expensereport = array();
1264 foreach (ExpenseReports::$FIELDS as $field) {
1265 if (!isset($data[$field])) {
1266 throw new RestException(400,
"$field field missing");
1268 $expensereport[$field] = $data[$field];
1270 return $expensereport;
1282 if ($data ===
null) {
1285 $expensereport = array();
1286 foreach (ExpenseReports::$FIELDSPAYMENT as $field) {
1287 if (!isset($data[$field])) {
1288 throw new RestException(400,
"$field field missing");
1290 $expensereport[$field] = $data[$field];
1292 return $expensereport;
1305 if ($data ===
null) {
1308 $expenseReport = array();
1309 foreach (ExpenseReports::$FIELDSLINE as $field) {
1310 if (!isset($data[$field])) {
1311 throw new RestException(400,
"$field field missing");
1313 $expenseReport[$field] = $data[$field];
1315 return $expenseReport;
$id
Support class for third parties, contacts, members, users or resources.
if(! $sortfield) if(! $sortorder) $object
_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_APPROVED
Classified approved.
const STATUS_CANCELED
Classified canceled.
const STATUS_REFUSED
Classified refused.
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.
__construct()
Constructor.
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.