dolibarr 25.0.0-alpha
api_salaries.class.php
1<?php
2/*
3 * Copyright (C) 2023 Marc Chenebaux <marc.chenebaux@maj44.com>
4 * Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
5 * Copyright (C) 2025-2026 Frédéric France <frederic.france@free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21use Luracast\Restler\RestException;
22
23require_once DOL_DOCUMENT_ROOT.'/salaries/class/salary.class.php';
24require_once DOL_DOCUMENT_ROOT.'/salaries/class/paymentsalary.class.php';
25
26
33class Salaries extends DolibarrApi
34{
38 public static $FIELDS = array(
39 'fk_user',
40 'label',
41 'amount',
42 );
43
47 public static $FIELDSPAYMENT = array(
48 "paiementtype",
49 'datepaye',
50 'chid',
51 'amounts',
52 );
53
54
58 public function __construct()
59 {
60 global $db;
61 $this->db = $db;
62 }
63
78 public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '')
79 {
80 $list = array();
81
82 if (!DolibarrApiAccess::$user->hasRight('salaries', 'read')
83 && !DolibarrApiAccess::$user->hasRight('salaries', 'readchild')
84 && !DolibarrApiAccess::$user->hasRight('salaries', 'readall')) {
85 throw new RestException(403);
86 }
87
88 $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "salary as t";
89 $sql .= ' WHERE t.entity IN ('.getEntity('user').')';
90 if (!DolibarrApiAccess::$user->hasRight('salaries', 'readall')) {
91 if (!DolibarrApiAccess::$user->hasRight('salaries', 'readchild')) {
92 $sql .= ' AND t.fk_user = '.((int) DolibarrApiAccess::$user->id);
93 } else {
94 $childids = DolibarrApiAccess::$user->getAllChildIds(1);
95 $sql .= ' AND t.fk_user IN ('.$this->db->sanitize(implode(',', $childids)).')';
96 }
97 }
98
99 // Add sql filters
100 if ($sqlfilters) {
101 $errormessage = '';
102 $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
103 if ($errormessage) {
104 throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
105 }
106 }
107
108 $sql .= $this->db->order($sortfield, $sortorder);
109 if ($limit) {
110 if ($page < 0) {
111 $page = 0;
112 }
113 $offset = $limit * $page;
114
115 $sql .= $this->db->plimit($limit + 1, $offset);
116 }
117
118 dol_syslog("API Rest request");
119 $result = $this->db->query($sql);
120
121 if ($result) {
122 $num = $this->db->num_rows($result);
123 $min = min($num, ($limit <= 0 ? $num : $limit));
124 for ($i = 0; $i < $min; $i++) {
125 $obj = $this->db->fetch_object($result);
126 $salary = new Salary($this->db);
127 if ($salary->fetch($obj->rowid) > 0) {
128 $list[] = $this->_cleanObjectDatas($salary);
129 }
130 }
131 } else {
132 throw new RestException(503, 'Error when retrieving list of salaries: ' . $this->db->lasterror());
133 }
134
135 return $list;
136 }
137
146 public function get($id)
147 {
148 if (!DolibarrApiAccess::$user->hasRight('salaries', 'read')
149 && !DolibarrApiAccess::$user->hasRight('salaries', 'readchild')
150 && !DolibarrApiAccess::$user->hasRight('salaries', 'readall')) {
151 throw new RestException(403);
152 }
153
154 $salary = new Salary($this->db);
155 $result = $salary->fetch($id);
156 if (!$result) {
157 throw new RestException(404, 'salary not found');
158 }
159
160 if (!DolibarrApiAccess::$user->hasRight('salaries', 'readall')) {
161 if (!DolibarrApiAccess::$user->hasRight('salaries', 'readchild')) {
162 if ($salary->fk_user != DolibarrApiAccess::$user->id) {
163 throw new RestException(404, 'salary not found');
164 }
165 } else {
166 $childids = DolibarrApiAccess::$user->getAllChildIds(1);
167 if (!in_array($salary->fk_user, $childids)) {
168 throw new RestException(404, 'salary not found');
169 }
170 }
171 }
172
173 return $this->_cleanObjectDatas($salary);
174 }
175
184 public function post($request_data = null)
185 {
186 if (!DolibarrApiAccess::$user->hasRight('salaries', 'write')) {
187 throw new RestException(403);
188 }
189 // Check mandatory fields
190 $result = $this->_validate($request_data);
191
192 $salary = new Salary($this->db);
193 foreach ($request_data as $field => $value) {
194 $salary->$field = $this->_checkValForAPI($field, $value, $salary);
195 }
196
197 if ($salary->create(DolibarrApiAccess::$user) < 0) {
198 throw new RestException(500, 'Error creating salary', array_merge(array($salary->error), $salary->errors));
199 }
200 return $salary->id;
201 }
202
212 public function put($id, $request_data = null)
213 {
214 if (!DolibarrApiAccess::$user->hasRight('salaries', 'write')) {
215 throw new RestException(403);
216 }
217
218 $salary = new Salary($this->db);
219 $result = $salary->fetch($id);
220 if (!$result) {
221 throw new RestException(404, 'salary not found');
222 }
223
224 foreach ($request_data as $field => $value) {
225 if ($field == 'id') {
226 continue;
227 }
228 $salary->$field = $this->_checkValForAPI($field, $value, $salary);
229 }
230
231 if ($salary->update(DolibarrApiAccess::$user) > 0) {
232 return $this->get($id);
233 } else {
234 throw new RestException(500, $salary->errorsToString());
235 }
236 }
237
244 /*public function delete($id)
245 {
246 if (!DolibarrApiAccess::$user->hasRight('salaries', 'delete')) {
247 throw new RestException(403);
248 }
249 $salary = new Salary($this->db);
250 $result = $salary->fetch($id);
251 if (!$result) {
252 throw new RestException(404, 'salary not found');
253 }
254
255 if ($salary->delete(DolibarrApiAccess::$user) < 0) {
256 throw new RestException(500, 'error when deleting salary');
257 }
258
259 return array(
260 'success' => array(
261 'code' => 200,
262 'message' => 'salary deleted'
263 )
264 );
265 }*/
266
267
283 public function getAllPayments($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0)
284 {
285 $list = array();
286
287 if (!DolibarrApiAccess::$user->hasRight('salaries', 'read')
288 && !DolibarrApiAccess::$user->hasRight('salaries', 'readchild')
289 && !DolibarrApiAccess::$user->hasRight('salaries', 'readall')) {
290 throw new RestException(403);
291 }
292
293 $sql = "SELECT t.rowid FROM " . MAIN_DB_PREFIX . "payment_salary as t, ".MAIN_DB_PREFIX."salary as s";
294 $sql .= ' WHERE s.rowid = t.fk_salary AND t.entity IN ('.getEntity('salary').')';
295 if (!DolibarrApiAccess::$user->hasRight('salaries', 'readall')) {
296 if (!DolibarrApiAccess::$user->hasRight('salaries', 'readchild')) {
297 $sql .= ' AND s.fk_user = '.((int) DolibarrApiAccess::$user->id).')';
298 } else {
299 $childids = DolibarrApiAccess::$user->getAllChildIds(1);
300 $sql .= ' AND s.fk_user IN ('.$this->db->sanitize(implode(',', $childids)).')';
301 }
302 }
303
304 $sql .= $this->db->order($sortfield, $sortorder);
305 if ($limit) {
306 if ($page < 0) {
307 $page = 0;
308 }
309 $offset = $limit * $page;
310
311 $sql .= $this->db->plimit($limit + 1, $offset);
312 }
313
314 dol_syslog("API Rest request");
315
316 $result = $this->db->query($sql);
317
318 if ($result) {
319 $num = $this->db->num_rows($result);
320 $min = min($num, ($limit <= 0 ? $num : $limit));
321 for ($i = 0; $i < $min; $i++) {
322 $obj = $this->db->fetch_object($result);
323 $paymentsalary = new PaymentSalary($this->db);
324 if ($paymentsalary->fetch($obj->rowid) > 0) {
325 $list[] = $this->_cleanObjectDatas($paymentsalary);
326 }
327 }
328 } else {
329 throw new RestException(503, 'Error when retrieving list of paymentsalaries: ' . $this->db->lasterror());
330 }
331
332 return $list;
333 }
334
345 public function getPayments($pid)
346 {
347 // A payment of salary can be done on different salaries of different users, so only users with permission
348 // to read all area allowed.
349 // TODO To support read or readchild case, the get must be done with a SQL that include the paid user with
350 // a where on current user and childids of current user.
351 if (!DolibarrApiAccess::$user->hasRight('salaries', 'readall')) {
352 throw new RestException(403);
353 }
354
355 $paymentsalary = new PaymentSalary($this->db);
356 $result = $paymentsalary->fetch($pid);
357 if (!$result) {
358 throw new RestException(404, 'paymentsalary not found');
359 }
360
361 return $this->_cleanObjectDatas($paymentsalary);
362 }
363
377 public function addPayment($id, $request_data = null)
378 {
379 if (!DolibarrApiAccess::$user->hasRight('salaries', 'write')) {
380 throw new RestException(403);
381 }
382 // Check mandatory fields
383 $result = $this->_validatepayments($request_data);
384
385 $salary = new Salary($this->db);
386 if ($salary->fetch($id) <= 0 || empty($salary->id)) {
387 throw new RestException(404, 'Salary not found');
388 }
389 // create() pays the salaries that are the keys of amounts, not {id}
390 if (!is_array($request_data['amounts']) || array_diff(array_keys($request_data['amounts']), array($salary->id))) {
391 throw new RestException(400, 'amounts must be keyed by the salary id '.$salary->id);
392 }
393
394 $paymentsalary = new PaymentSalary($this->db);
395 $paymentsalary->fk_salary = $id;
396 foreach ($request_data as $field => $value) {
397 $paymentsalary->$field = $this->_checkValForAPI($field, $value, $paymentsalary);
398 }
399 // create() and addPaymentToBank() read fk_typepayment, the mandatory field is paiementtype
400 if (empty($paymentsalary->fk_typepayment)) {
401 $paymentsalary->fk_typepayment = (int) $request_data['paiementtype'];
402 }
403
404 // Payment and bank line are written together, or not at all
405 $this->db->begin();
406
407 if ($paymentsalary->create(DolibarrApiAccess::$user, 1) < 0) {
408 $this->db->rollback();
409 throw new RestException(400, 'Payment error : '.$paymentsalary->errorsToString());
410 }
411 if (isModEnabled("bank")) {
412 $result = $paymentsalary->addPaymentToBank(
413 DolibarrApiAccess::$user,
414 'payment_salary',
415 '(SalaryPayment)',
416 (int) $request_data['accountid'],
417 '',
418 ''
419 );
420 if ($result <= 0) {
421 $this->db->rollback();
422 throw new RestException(400, 'Add payment to bank error : '.$paymentsalary->errorsToString());
423 }
424 }
425
426 $this->db->commit();
427
428 return $paymentsalary->id;
429 }
430
444 public function updatePayment($id, $request_data = null)
445 {
446 if (!DolibarrApiAccess::$user->hasRight('salaries', 'write')) {
447 throw new RestException(403);
448 }
449
450 $paymentsalary = new PaymentSalary($this->db);
451 $result = $paymentsalary->fetch($id);
452 if (!$result) {
453 throw new RestException(404, 'Payment salary not found');
454 }
455
456 foreach ($request_data as $field => $value) {
457 if ($field == 'id') {
458 continue;
459 }
460 $paymentsalary->$field = $this->_checkValForAPI($field, $value, $paymentsalary);
461 }
462
463 if ($paymentsalary->update(DolibarrApiAccess::$user) > 0) {
464 return $this->get($id);
465 } else {
466 throw new RestException(500, $paymentsalary->errorsToString());
467 }
468 }
469
478 /*public function delete($id)
479 {
480 if (!DolibarrApiAccess::$user->hasRight('salaries', 'delete')) {
481 throw new RestException(403);
482 }
483 $paymentsalary = new PaymentSalary($this->db);
484 $result = $paymentsalary->fetch($id);
485 if (!$result) {
486 throw new RestException(404, 'paymentsalary not found');
487 }
488
489 if ($paymentsalary->delete(DolibarrApiAccess::$user) < 0) {
490 throw new RestException(500, 'error when deleting paymentsalary');
491 }
492
493 return array(
494 'success' => array(
495 'code' => 200,
496 'message' => 'paymentsalary deleted'
497 )
498 );
499 }*/
500
501
510 private function _validate($data)
511 {
512 if ($data === null) {
513 $data = array();
514 }
515 $salary = array();
516 foreach (Salaries::$FIELDS as $field) {
517 if (!isset($data[$field])) {
518 throw new RestException(400, "$field field missing");
519 }
520 $salary[$field] = $data[$field];
521 }
522 return $salary;
523 }
524
533 private function _validatepayments($data)
534 {
535 if ($data === null) {
536 $data = array();
537 }
538 $paymentsalary = array();
539 $fields = Salaries::$FIELDSPAYMENT;
540 if (isModEnabled("bank")) {
541 array_push($fields, "accountid");
542 }
543 foreach ($fields as $field) {
544 if (!isset($data[$field])) {
545 throw new RestException(400, "$field field missing");
546 }
547 $paymentsalary[$field] = $data[$field];
548 }
549 return $paymentsalary;
550 }
551
552 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
562 protected function _cleanObjectDatas($object)
563 {
564 // phpcs:enable
565 $object = parent::_cleanObjectDatas($object);
566
567 unset($object->rowid);
568
569 return $object;
570 }
571}
$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
_checkValForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
Class to manage payments of salaries.
index($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0, $sqlfilters='')
Get the list of salaries.
put($id, $request_data=null)
Update salary.
__construct()
Constructor.
updatePayment($id, $request_data=null)
Update paymentsalary.
_cleanObjectDatas($object)
Clean sensible object datas @phpstan-template T.
_validate($data)
Delete a payment salary.
getPayments($pid)
Get a given payment.
getAllPayments($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0)
Delete salary.
post($request_data=null)
Create salary object.
_validatepayments($data)
Validate fields before creating an object.
addPayment($id, $request_data=null)
Create payment salary on a salary.
Class to manage salary payments.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0, $forbiddenfields=array())
forgeSQLFromUniversalSearchCriteria
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.