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 $account->$field = $this->_checkValForAPI($field, $value, $account);
336 }
337
338 if ($account->update(DolibarrApiAccess::$user) > 0) {
339 return $this->get($id);
340 } else {
341 throw new RestException(500, $account->error);
342 }
343 }
344
351 public function delete($id)
352 {
353 if (!DolibarrApiAccess::$user->rights->banque->configurer) {
354 throw new RestException(401);
355 }
356 $account = new Account($this->db);
357 $result = $account->fetch($id);
358 if (!$result) {
359 throw new RestException(404, 'account not found');
360 }
361
362 if ($account->delete(DolibarrApiAccess::$user) < 0) {
363 throw new RestException(401, 'error when deleting account');
364 }
365
366 return array(
367 'success' => array(
368 'code' => 200,
369 'message' => 'account deleted'
370 )
371 );
372 }
373
382 private function _validate($data)
383 {
384 $account = array();
385 foreach (BankAccounts::$FIELDS as $field) {
386 if (!isset($data[$field])) {
387 throw new RestException(400, "$field field missing");
388 }
389 $account[$field] = $data[$field];
390 }
391 return $account;
392 }
393
394 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
401 protected function _cleanObjectDatas($object)
402 {
403 // phpcs:enable
404 $object = parent::_cleanObjectDatas($object);
405
406 unset($object->rowid);
407
408 return $object;
409 }
410
422 public function getLines($id, $sqlfilters = '')
423 {
424 $list = array();
425
426 if (!DolibarrApiAccess::$user->rights->banque->lire) {
427 throw new RestException(401);
428 }
429
430 $account = new Account($this->db);
431 $result = $account->fetch($id);
432 if (!$result) {
433 throw new RestException(404, 'account not found');
434 }
435
436 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."bank ";
437 $sql .= " WHERE fk_account = ".((int) $id);
438
439 // Add sql filters
440 if ($sqlfilters) {
441 $errormessage = '';
442 $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
443 if ($errormessage) {
444 throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
445 }
446 }
447
448 $sql .= " ORDER BY rowid";
449
450 $result = $this->db->query($sql);
451
452 if ($result) {
453 $num = $this->db->num_rows($result);
454 for ($i = 0; $i < $num; $i++) {
455 $obj = $this->db->fetch_object($result);
456 $accountLine = new AccountLine($this->db);
457 if ($accountLine->fetch($obj->rowid) > 0) {
458 $list[] = $this->_cleanObjectDatas($accountLine);
459 }
460 }
461 } else {
462 throw new RestException(503, 'Error when retrieving list of account lines: '.$this->db->lasterror());
463 }
464
465 return $list;
466 }
467
487 public function addLine($id, $date, $type, $label, $amount, $category = 0, $cheque_number = '', $cheque_writer = '', $cheque_bank = '', $accountancycode = '', $datev = null, $num_releve = '')
488 {
489 if (!DolibarrApiAccess::$user->rights->banque->modifier) {
490 throw new RestException(401);
491 }
492
493 $account = new Account($this->db);
494 $result = $account->fetch($id);
495 if (!$result) {
496 throw new RestException(404, 'account not found');
497 }
498
499 $type = sanitizeVal($type);
500 $label = sanitizeVal($label);
501 $cheque_number = sanitizeVal($cheque_number);
502 $cheque_writer = sanitizeVal($cheque_writer);
503 $cheque_bank = sanitizeVal($cheque_bank);
504 $accountancycode = sanitizeVal($accountancycode);
505 $num_releve = sanitizeVal($num_releve);
506
507 $result = $account->addline(
508 $date,
509 $type,
510 $label,
511 $amount,
512 $cheque_number,
513 $category,
514 DolibarrApiAccess::$user,
515 $cheque_writer,
516 $cheque_bank,
517 $accountancycode,
518 $datev,
519 $num_releve
520 );
521 if ($result < 0) {
522 throw new RestException(503, 'Error when adding line to account: '.$account->error);
523 }
524 return $result;
525 }
526
540 public function addLink($id, $line_id, $url_id, $url, $label, $type)
541 {
542 if (!DolibarrApiAccess::$user->rights->banque->modifier) {
543 throw new RestException(401);
544 }
545
546 $account = new Account($this->db);
547 $result = $account->fetch($id);
548 if (!$result) {
549 throw new RestException(404, 'account not found');
550 }
551
552 $accountLine = new AccountLine($this->db);
553 $result = $accountLine->fetch($line_id);
554 if (!$result) {
555 throw new RestException(404, 'account line not found');
556 }
557
558 $url = sanitizeVal($url);
559 $label = sanitizeVal($label);
560 $type = sanitizeVal($type);
561
562 $result = $account->add_url_line($line_id, $url_id, $url, $label, $type);
563 if ($result < 0) {
564 throw new RestException(503, 'Error when adding link to account line: '.$account->error);
565 }
566 return $result;
567 }
568}
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.