dolibarr  16.0.5
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 
19 use Luracast\Restler\RestException;
20 
21 require_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 rowid FROM ".MAIN_DB_PREFIX."bank_account as t";
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  if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
86  throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
87  }
88  $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
89  $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
90  }
91 
92  $sql .= $this->db->order($sortfield, $sortorder);
93  if ($limit) {
94  if ($page < 0) {
95  $page = 0;
96  }
97  $offset = $limit * $page;
98 
99  $sql .= $this->db->plimit($limit + 1, $offset);
100  }
101 
102  dol_syslog("API Rest request");
103  $result = $this->db->query($sql);
104 
105  if ($result) {
106  $num = $this->db->num_rows($result);
107  $min = min($num, ($limit <= 0 ? $num : $limit));
108  for ($i = 0; $i < $min; $i++) {
109  $obj = $this->db->fetch_object($result);
110  $account = new Account($this->db);
111  if ($account->fetch($obj->rowid) > 0) {
112  $list[] = $this->_cleanObjectDatas($account);
113  }
114  }
115  } else {
116  throw new RestException(503, 'Error when retrieving list of accounts: '.$this->db->lasterror());
117  }
118 
119  return $list;
120  }
121 
130  public function get($id)
131  {
132  if (!DolibarrApiAccess::$user->rights->banque->lire) {
133  throw new RestException(401);
134  }
135 
136  $account = new Account($this->db);
137  $result = $account->fetch($id);
138  if (!$result) {
139  throw new RestException(404, 'account not found');
140  }
141 
142  return $this->_cleanObjectDatas($account);
143  }
144 
151  public function post($request_data = null)
152  {
153  if (!DolibarrApiAccess::$user->rights->banque->configurer) {
154  throw new RestException(401);
155  }
156  // Check mandatory fields
157  $result = $this->_validate($request_data);
158 
159  $account = new Account($this->db);
160  foreach ($request_data as $field => $value) {
161  $account->$field = $this->_checkValForAPI($field, $value, $account);
162  }
163  // Date of the initial balance (required to create an account).
164  $account->date_solde = time();
165  // courant and type are the same thing but the one used when
166  // creating an account is courant
167  $account->courant = $account->type;
168 
169  if ($account->create(DolibarrApiAccess::$user) < 0) {
170  throw new RestException(500, 'Error creating bank account', array_merge(array($account->error), $account->errors));
171  }
172  return $account->id;
173  }
174 
196  public function transfer($bankaccount_from_id = 0, $bankaccount_to_id = 0, $date = null, $description = "", $amount = 0.0, $amount_to = 0.0)
197  {
198  if (!DolibarrApiAccess::$user->rights->banque->configurer) {
199  throw new RestException(401);
200  }
201 
202  require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
203 
204  $accountfrom = new Account($this->db);
205  $resultAccountFrom = $accountfrom->fetch($bankaccount_from_id);
206 
207  if ($resultAccountFrom === 0) {
208  throw new RestException(404, 'The BankAccount for bankaccount_from_id provided does not exist.');
209  }
210 
211  $accountto = new Account($this->db);
212  $resultAccountTo = $accountto->fetch($bankaccount_to_id);
213 
214  if ($resultAccountTo === 0) {
215  throw new RestException(404, 'The BankAccount for bankaccount_to_id provided does not exist.');
216  }
217 
218  if ($accountto->currency_code == $accountfrom->currency_code) {
219  $amount_to = $amount;
220  } else {
221  if (!$amount_to || empty($amount_to)) {
222  throw new RestException(422, 'You must provide amount_to value since bankaccount_from and bankaccount_to does not share the same currency.');
223  }
224  }
225 
226  if ($amount_to < 0) {
227  throw new RestException(422, 'You must provide a positive value for amount.');
228  }
229 
230  if ($accountto->id == $accountfrom->id) {
231  throw new RestException(422, 'bankaccount_from_id and bankaccount_to_id must be different !');
232  }
233 
234  $this->db->begin();
235 
236  $error = 0;
237  $bank_line_id_from = 0;
238  $bank_line_id_to = 0;
239  $result = 0;
240  $user = DolibarrApiAccess::$user;
241 
242  // By default, electronic transfert from bank to bank
243  $typefrom = 'PRE';
244  $typeto = 'VIR';
245 
246  if ($accountto->courant == Account::TYPE_CASH || $accountfrom->courant == Account::TYPE_CASH) {
247  // This is transfer of change
248  $typefrom = 'LIQ';
249  $typeto = 'LIQ';
250  }
251 
252  // Clean data
253  $description = sanitizeVal($description, 'alphanohtml');
254 
255 
260  if (!$error) {
261  $bank_line_id_from = $accountfrom->addline($date, $typefrom, $description, -1 * price2num($amount), '', '', $user);
262  }
263  if (!($bank_line_id_from > 0)) {
264  $error++;
265  }
266 
267  if (!$error) {
268  $bank_line_id_to = $accountto->addline($date, $typeto, $description, price2num($amount_to), '', '', $user);
269  }
270  if (!($bank_line_id_to > 0)) {
271  $error++;
272  }
273 
278  $url = DOL_URL_ROOT.'/compta/bank/line.php?rowid=';
279  $label = '(banktransfert)';
280  $type = 'banktransfert';
281 
282  if (!$error) {
283  $result = $accountfrom->add_url_line($bank_line_id_from, $bank_line_id_to, $url, $label, $type);
284  }
285  if (!($result > 0)) {
286  $error++;
287  }
288 
289  if (!$error) {
290  $result = $accountto->add_url_line($bank_line_id_to, $bank_line_id_from, $url, $label, $type);
291  }
292  if (!($result > 0)) {
293  $error++;
294  }
295 
296  if (!$error) {
297  $this->db->commit();
298 
299  return array(
300  'success' => array(
301  'code' => 201,
302  'message' => 'Internal wire transfer created successfully.',
303  'bank_id_from' => $bank_line_id_from,
304  'bank_id_to' => $bank_line_id_to,
305  )
306  );
307  } else {
308  $this->db->rollback();
309  throw new RestException(500, $accountfrom->error.' '.$accountto->error);
310  }
311  }
312 
320  public function put($id, $request_data = null)
321  {
322  if (!DolibarrApiAccess::$user->rights->banque->configurer) {
323  throw new RestException(401);
324  }
325 
326  $account = new Account($this->db);
327  $result = $account->fetch($id);
328  if (!$result) {
329  throw new RestException(404, 'account not found');
330  }
331 
332  foreach ($request_data as $field => $value) {
333  if ($field == 'id') {
334  continue;
335  }
336  $account->$field = $this->_checkValForAPI($field, $value, $account);
337  }
338 
339  if ($account->update(DolibarrApiAccess::$user) > 0) {
340  return $this->get($id);
341  } else {
342  throw new RestException(500, $account->error);
343  }
344  }
345 
352  public function delete($id)
353  {
354  if (!DolibarrApiAccess::$user->rights->banque->configurer) {
355  throw new RestException(401);
356  }
357  $account = new Account($this->db);
358  $result = $account->fetch($id);
359  if (!$result) {
360  throw new RestException(404, 'account not found');
361  }
362 
363  if ($account->delete(DolibarrApiAccess::$user) < 0) {
364  throw new RestException(401, 'error when deleting account');
365  }
366 
367  return array(
368  'success' => array(
369  'code' => 200,
370  'message' => 'account deleted'
371  )
372  );
373  }
374 
383  private function _validate($data)
384  {
385  $account = array();
386  foreach (BankAccounts::$FIELDS as $field) {
387  if (!isset($data[$field])) {
388  throw new RestException(400, "$field field missing");
389  }
390  $account[$field] = $data[$field];
391  }
392  return $account;
393  }
394 
395  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
402  protected function _cleanObjectDatas($object)
403  {
404  // phpcs:enable
405  $object = parent::_cleanObjectDatas($object);
406 
407  unset($object->rowid);
408 
409  return $object;
410  }
411 
423  public function getLines($id, $sqlfilters = '')
424  {
425  $list = array();
426 
427  if (!DolibarrApiAccess::$user->rights->banque->lire) {
428  throw new RestException(401);
429  }
430 
431  $account = new Account($this->db);
432  $result = $account->fetch($id);
433  if (!$result) {
434  throw new RestException(404, 'account not found');
435  }
436 
437  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."bank ";
438  $sql .= " WHERE fk_account = ".((int) $id);
439 
440  // Add sql filters
441  if ($sqlfilters) {
442  $errormessage = '';
443  if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
444  throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
445  }
446  $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
447  $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
448  }
449 
450  $sql .= " ORDER BY rowid";
451 
452  $result = $this->db->query($sql);
453 
454  if ($result) {
455  $num = $this->db->num_rows($result);
456  for ($i = 0; $i < $num; $i++) {
457  $obj = $this->db->fetch_object($result);
458  $accountLine = new AccountLine($this->db);
459  if ($accountLine->fetch($obj->rowid) > 0) {
460  $list[] = $this->_cleanObjectDatas($accountLine);
461  }
462  }
463  } else {
464  throw new RestException(503, 'Error when retrieving list of account lines: '.$this->db->lasterror());
465  }
466 
467  return $list;
468  }
469 
489  public function addLine($id, $date, $type, $label, $amount, $category = 0, $cheque_number = '', $cheque_writer = '', $cheque_bank = '', $accountancycode = '', $datev = null, $num_releve = '')
490  {
491  if (!DolibarrApiAccess::$user->rights->banque->modifier) {
492  throw new RestException(401);
493  }
494 
495  $account = new Account($this->db);
496  $result = $account->fetch($id);
497  if (!$result) {
498  throw new RestException(404, 'account not found');
499  }
500 
501  $type = sanitizeVal($type);
502  $label = sanitizeVal($label);
503  $cheque_number = sanitizeVal($cheque_number);
504  $cheque_writer = sanitizeVal($cheque_writer);
505  $cheque_bank = sanitizeVal($cheque_bank);
506  $accountancycode = sanitizeVal($accountancycode);
507  $num_releve = sanitizeVal($num_releve);
508 
509  $result = $account->addline(
510  $date,
511  $type,
512  $label,
513  $amount,
514  $cheque_number,
515  $category,
516  DolibarrApiAccess::$user,
517  $cheque_writer,
518  $cheque_bank,
519  $accountancycode,
520  $datev,
521  $num_releve
522  );
523  if ($result < 0) {
524  throw new RestException(503, 'Error when adding line to account: '.$account->error);
525  }
526  return $result;
527  }
528 
542  public function addLink($id, $line_id, $url_id, $url, $label, $type)
543  {
544  if (!DolibarrApiAccess::$user->rights->banque->modifier) {
545  throw new RestException(401);
546  }
547 
548  $account = new Account($this->db);
549  $result = $account->fetch($id);
550  if (!$result) {
551  throw new RestException(404, 'account not found');
552  }
553 
554  $accountLine = new AccountLine($this->db);
555  $result = $accountLine->fetch($line_id);
556  if (!$result) {
557  throw new RestException(404, 'account line not found');
558  }
559 
560  $url = sanitizeVal($url);
561  $label = sanitizeVal($label);
562  $type = sanitizeVal($type);
563 
564  $result = $account->add_url_line($line_id, $url_id, $url, $label, $type);
565  if ($result < 0) {
566  throw new RestException(503, 'Error when adding link to account line: '.$account->error);
567  }
568  return $result;
569  }
570 }
BankAccounts\_cleanObjectDatas
_cleanObjectDatas($object)
Clean sensible object datas.
Definition: api_bankaccounts.class.php:402
db
$conf db
API class for accounts.
Definition: inc.php:41
BankAccounts\index
index($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0, $category=0, $sqlfilters='')
Get the list of accounts.
Definition: api_bankaccounts.class.php:65
sanitizeVal
sanitizeVal($out='', $check='alphanohtml', $filter=null, $options=null)
Return a sanitized or empty value after checking value against a rule.
Definition: functions.lib.php:825
BankAccounts
Definition: api_bankaccounts.class.php:30
price2num
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
Definition: functions.lib.php:5661
BankAccounts\transfer
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.
Definition: api_bankaccounts.class.php:196
DolibarrApi
Class for API REST v1.
Definition: api.class.php:30
BankAccounts\getLines
getLines($id, $sqlfilters='')
Get the list of lines of the account.
Definition: api_bankaccounts.class.php:423
Account\TYPE_CASH
const TYPE_CASH
Cash account.
Definition: account.class.php:346
BankAccounts\put
put($id, $request_data=null)
Update account.
Definition: api_bankaccounts.class.php:320
DolibarrApi\_checkFilters
_checkFilters($sqlfilters, &$error='')
Return if a $sqlfilters parameter is valid.
Definition: api.class.php:310
BankAccounts\_validate
_validate($data)
Validate fields before creating an object.
Definition: api_bankaccounts.class.php:383
BankAccounts\addLink
addLink($id, $line_id, $url_id, $url, $label, $type)
Add a link to an account line.
Definition: api_bankaccounts.class.php:542
dol_syslog
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
Definition: functions.lib.php:1603
BankAccounts\addLine
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.
Definition: api_bankaccounts.class.php:489
AccountLine
Class to manage bank transaction lines.
Definition: account.class.php:1779
BankAccounts\__construct
__construct()
Constructor.
Definition: api_bankaccounts.class.php:46
DolibarrApi\_checkValForAPI
_checkValForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
Definition: api.class.php:86
BankAccounts\$FIELDS
static $FIELDS
array $FIELDS Mandatory fields, checked when creating an object
Definition: api_bankaccounts.class.php:35
BankAccounts\post
post($request_data=null)
Create account object.
Definition: api_bankaccounts.class.php:151
Account
Class to manage bank accounts.
Definition: account.class.php:38