dolibarr  17.0.4
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  $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, &$error='')
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.
$conf db
API class for accounts.
Definition: inc.php:41