dolibarr 18.0.6
api_bankaccounts.class.php
1<?php
2/*
3 * Copyright (C) 2016 Xebax Christy <xebax@wanadoo.fr>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19use Luracast\Restler\RestException;
20
21require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
22
31{
35 static $FIELDS = array(
36 'ref',
37 'label',
38 'type',
39 'currency_code',
40 'country_id'
41 );
42
46 public function __construct()
47 {
48 global $db;
49 $this->db = $db;
50 }
51
65 public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $category = 0, $sqlfilters = '')
66 {
67 $list = array();
68
69 if (!DolibarrApiAccess::$user->rights->banque->lire) {
70 throw new RestException(401);
71 }
72
73 $sql = "SELECT t.rowid FROM ".MAIN_DB_PREFIX."bank_account AS t LEFT JOIN ".MAIN_DB_PREFIX."bank_account_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
74 if ($category > 0) {
75 $sql .= ", ".MAIN_DB_PREFIX."categorie_account as c";
76 }
77 $sql .= ' WHERE t.entity IN ('.getEntity('bank_account').')';
78 // Select accounts of given category
79 if ($category > 0) {
80 $sql .= " AND c.fk_categorie = ".((int) $category)." AND c.fk_account = t.rowid";
81 }
82 // Add sql filters
83 if ($sqlfilters) {
84 $errormessage = '';
85 $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
86 if ($errormessage) {
87 throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
88 }
89 }
90
91 $sql .= $this->db->order($sortfield, $sortorder);
92 if ($limit) {
93 if ($page < 0) {
94 $page = 0;
95 }
96 $offset = $limit * $page;
97
98 $sql .= $this->db->plimit($limit + 1, $offset);
99 }
100
101 dol_syslog("API Rest request");
102 $result = $this->db->query($sql);
103
104 if ($result) {
105 $num = $this->db->num_rows($result);
106 $min = min($num, ($limit <= 0 ? $num : $limit));
107 for ($i = 0; $i < $min; $i++) {
108 $obj = $this->db->fetch_object($result);
109 $account = new Account($this->db);
110 if ($account->fetch($obj->rowid) > 0) {
111 $list[] = $this->_cleanObjectDatas($account);
112 }
113 }
114 } else {
115 throw new RestException(503, 'Error when retrieving list of accounts: '.$this->db->lasterror());
116 }
117
118 return $list;
119 }
120
129 public function get($id)
130 {
131 if (!DolibarrApiAccess::$user->rights->banque->lire) {
132 throw new RestException(401);
133 }
134
135 $account = new Account($this->db);
136 $result = $account->fetch($id);
137 if (!$result) {
138 throw new RestException(404, 'account not found');
139 }
140
141 return $this->_cleanObjectDatas($account);
142 }
143
150 public function post($request_data = null)
151 {
152 if (!DolibarrApiAccess::$user->rights->banque->configurer) {
153 throw new RestException(401);
154 }
155 // Check mandatory fields
156 $result = $this->_validate($request_data);
157
158 $account = new Account($this->db);
159 foreach ($request_data as $field => $value) {
160 $account->$field = $this->_checkValForAPI($field, $value, $account);
161 }
162 // Date of the initial balance (required to create an account).
163 $account->date_solde = time();
164 // courant and type are the same thing but the one used when
165 // creating an account is courant
166 $account->courant = $account->type;
167
168 if ($account->create(DolibarrApiAccess::$user) < 0) {
169 throw new RestException(500, 'Error creating bank account', array_merge(array($account->error), $account->errors));
170 }
171 return $account->id;
172 }
173
195 public function transfer($bankaccount_from_id = 0, $bankaccount_to_id = 0, $date = null, $description = "", $amount = 0.0, $amount_to = 0.0)
196 {
197 if (!DolibarrApiAccess::$user->rights->banque->configurer) {
198 throw new RestException(401);
199 }
200
201 require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
202
203 $accountfrom = new Account($this->db);
204 $resultAccountFrom = $accountfrom->fetch($bankaccount_from_id);
205
206 if ($resultAccountFrom === 0) {
207 throw new RestException(404, 'The BankAccount for bankaccount_from_id provided does not exist.');
208 }
209
210 $accountto = new Account($this->db);
211 $resultAccountTo = $accountto->fetch($bankaccount_to_id);
212
213 if ($resultAccountTo === 0) {
214 throw new RestException(404, 'The BankAccount for bankaccount_to_id provided does not exist.');
215 }
216
217 if ($accountto->currency_code == $accountfrom->currency_code) {
218 $amount_to = $amount;
219 } else {
220 if (!$amount_to || empty($amount_to)) {
221 throw new RestException(422, 'You must provide amount_to value since bankaccount_from and bankaccount_to does not share the same currency.');
222 }
223 }
224
225 if ($amount_to < 0) {
226 throw new RestException(422, 'You must provide a positive value for amount.');
227 }
228
229 if ($accountto->id == $accountfrom->id) {
230 throw new RestException(422, 'bankaccount_from_id and bankaccount_to_id must be different !');
231 }
232
233 $this->db->begin();
234
235 $error = 0;
236 $bank_line_id_from = 0;
237 $bank_line_id_to = 0;
238 $result = 0;
239 $user = DolibarrApiAccess::$user;
240
241 // By default, electronic transfert from bank to bank
242 $typefrom = 'PRE';
243 $typeto = 'VIR';
244
245 if ($accountto->courant == Account::TYPE_CASH || $accountfrom->courant == Account::TYPE_CASH) {
246 // This is transfer of change
247 $typefrom = 'LIQ';
248 $typeto = 'LIQ';
249 }
250
251 // Clean data
252 $description = sanitizeVal($description, 'alphanohtml');
253
254
259 if (!$error) {
260 $bank_line_id_from = $accountfrom->addline($date, $typefrom, $description, -1 * price2num($amount), '', '', $user);
261 }
262 if (!($bank_line_id_from > 0)) {
263 $error++;
264 }
265
266 if (!$error) {
267 $bank_line_id_to = $accountto->addline($date, $typeto, $description, price2num($amount_to), '', '', $user);
268 }
269 if (!($bank_line_id_to > 0)) {
270 $error++;
271 }
272
277 $url = DOL_URL_ROOT.'/compta/bank/line.php?rowid=';
278 $label = '(banktransfert)';
279 $type = 'banktransfert';
280
281 if (!$error) {
282 $result = $accountfrom->add_url_line($bank_line_id_from, $bank_line_id_to, $url, $label, $type);
283 }
284 if (!($result > 0)) {
285 $error++;
286 }
287
288 if (!$error) {
289 $result = $accountto->add_url_line($bank_line_id_to, $bank_line_id_from, $url, $label, $type);
290 }
291 if (!($result > 0)) {
292 $error++;
293 }
294
295 if (!$error) {
296 $this->db->commit();
297
298 return array(
299 'success' => array(
300 'code' => 201,
301 'message' => 'Internal wire transfer created successfully.',
302 'bank_id_from' => $bank_line_id_from,
303 'bank_id_to' => $bank_line_id_to,
304 )
305 );
306 } else {
307 $this->db->rollback();
308 throw new RestException(500, $accountfrom->error.' '.$accountto->error);
309 }
310 }
311
319 public function put($id, $request_data = null)
320 {
321 if (!DolibarrApiAccess::$user->rights->banque->configurer) {
322 throw new RestException(401);
323 }
324
325 $account = new Account($this->db);
326 $result = $account->fetch($id);
327 if (!$result) {
328 throw new RestException(404, 'account not found');
329 }
330
331 foreach ($request_data as $field => $value) {
332 if ($field == 'id') {
333 continue;
334 }
335 if ($field == 'array_options' && is_array($value)) {
336 foreach ($value as $index => $val) {
337 $account->array_options[$index] = $this->_checkValForAPI($field, $val, $account);
338 }
339 continue;
340 }
341 $account->$field = $this->_checkValForAPI($field, $value, $account);
342 }
343
344 if ($account->update(DolibarrApiAccess::$user) > 0) {
345 return $this->get($id);
346 } else {
347 throw new RestException(500, $account->error);
348 }
349 }
350
357 public function delete($id)
358 {
359 if (!DolibarrApiAccess::$user->rights->banque->configurer) {
360 throw new RestException(401);
361 }
362 $account = new Account($this->db);
363 $result = $account->fetch($id);
364 if (!$result) {
365 throw new RestException(404, 'account not found');
366 }
367
368 if ($account->delete(DolibarrApiAccess::$user) < 0) {
369 throw new RestException(401, 'error when deleting account');
370 }
371
372 return array(
373 'success' => array(
374 'code' => 200,
375 'message' => 'account deleted'
376 )
377 );
378 }
379
388 private function _validate($data)
389 {
390 $account = array();
391 foreach (BankAccounts::$FIELDS as $field) {
392 if (!isset($data[$field])) {
393 throw new RestException(400, "$field field missing");
394 }
395 $account[$field] = $data[$field];
396 }
397 return $account;
398 }
399
400 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
407 protected function _cleanObjectDatas($object)
408 {
409 // phpcs:enable
410 $object = parent::_cleanObjectDatas($object);
411
412 unset($object->rowid);
413
414 return $object;
415 }
416
428 public function getLines($id, $sqlfilters = '')
429 {
430 $list = array();
431
432 if (!DolibarrApiAccess::$user->rights->banque->lire) {
433 throw new RestException(401);
434 }
435
436 $account = new Account($this->db);
437 $result = $account->fetch($id);
438 if (!$result) {
439 throw new RestException(404, 'account not found');
440 }
441
442 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."bank ";
443 $sql .= " WHERE fk_account = ".((int) $id);
444
445 // Add sql filters
446 if ($sqlfilters) {
447 $errormessage = '';
448 $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
449 if ($errormessage) {
450 throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
451 }
452 }
453
454 $sql .= " ORDER BY rowid";
455
456 $result = $this->db->query($sql);
457
458 if ($result) {
459 $num = $this->db->num_rows($result);
460 for ($i = 0; $i < $num; $i++) {
461 $obj = $this->db->fetch_object($result);
462 $accountLine = new AccountLine($this->db);
463 if ($accountLine->fetch($obj->rowid) > 0) {
464 $list[] = $this->_cleanObjectDatas($accountLine);
465 }
466 }
467 } else {
468 throw new RestException(503, 'Error when retrieving list of account lines: '.$this->db->lasterror());
469 }
470
471 return $list;
472 }
473
493 public function addLine($id, $date, $type, $label, $amount, $category = 0, $cheque_number = '', $cheque_writer = '', $cheque_bank = '', $accountancycode = '', $datev = null, $num_releve = '')
494 {
495 if (!DolibarrApiAccess::$user->rights->banque->modifier) {
496 throw new RestException(401);
497 }
498
499 $account = new Account($this->db);
500 $result = $account->fetch($id);
501 if (!$result) {
502 throw new RestException(404, 'account not found');
503 }
504
505 $type = sanitizeVal($type);
506 $label = sanitizeVal($label);
507 $cheque_number = sanitizeVal($cheque_number);
508 $cheque_writer = sanitizeVal($cheque_writer);
509 $cheque_bank = sanitizeVal($cheque_bank);
510 $accountancycode = sanitizeVal($accountancycode);
511 $num_releve = sanitizeVal($num_releve);
512
513 $result = $account->addline(
514 $date,
515 $type,
516 $label,
517 $amount,
518 $cheque_number,
519 $category,
520 DolibarrApiAccess::$user,
521 $cheque_writer,
522 $cheque_bank,
523 $accountancycode,
524 $datev,
525 $num_releve
526 );
527 if ($result < 0) {
528 throw new RestException(503, 'Error when adding line to account: '.$account->error);
529 }
530 return $result;
531 }
532
546 public function addLink($id, $line_id, $url_id, $url, $label, $type)
547 {
548 if (!DolibarrApiAccess::$user->rights->banque->modifier) {
549 throw new RestException(401);
550 }
551
552 $account = new Account($this->db);
553 $result = $account->fetch($id);
554 if (!$result) {
555 throw new RestException(404, 'account not found');
556 }
557
558 $accountLine = new AccountLine($this->db);
559 $result = $accountLine->fetch($line_id);
560 if (!$result) {
561 throw new RestException(404, 'account line not found');
562 }
563
564 $url = sanitizeVal($url);
565 $label = sanitizeVal($label);
566 $type = sanitizeVal($type);
567
568 $result = $account->add_url_line($line_id, $url_id, $url, $label, $type);
569 if ($result < 0) {
570 throw new RestException(503, 'Error when adding link to account line: '.$account->error);
571 }
572 return $result;
573 }
574}
Class to manage bank accounts.
const TYPE_CASH
Cash account.
Class to manage bank transaction lines.
post($request_data=null)
Create account object.
addLink($id, $line_id, $url_id, $url, $label, $type)
Add a link to an account line.
put($id, $request_data=null)
Update account.
_validate($data)
Validate fields before creating an object.
__construct()
Constructor.
addLine($id, $date, $type, $label, $amount, $category=0, $cheque_number='', $cheque_writer='', $cheque_bank='', $accountancycode='', $datev=null, $num_releve='')
Add a line to an account.
transfer($bankaccount_from_id=0, $bankaccount_to_id=0, $date=null, $description="", $amount=0.0, $amount_to=0.0)
Create an internal wire transfer between two bank accounts.
getLines($id, $sqlfilters='')
Get the list of lines of the account.
index($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0, $category=0, $sqlfilters='')
Get the list of accounts.
static $FIELDS
array $FIELDS Mandatory fields, checked when creating an object
_cleanObjectDatas($object)
Clean sensible object datas.
Class for API REST v1.
Definition api.class.php:31
_checkValForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
Definition api.class.php:86
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)
forgeSQLFromUniversalSearchCriteria
sanitizeVal($out='', $check='alphanohtml', $filter=null, $options=null)
Return a sanitized or empty value after checking value against a rule.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.