dolibarr  x.y.z
api_supplier_invoices.class.php
1 <?php
2 /* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
3  * Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
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.'/fourn/class/fournisseur.facture.class.php';
22 require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php';
23 
32 {
37  public static $FIELDS = array(
38  'socid',
39  );
40 
44  public $invoice;
45 
49  public function __construct()
50  {
51  global $db;
52  $this->db = $db;
53  $this->invoice = new FactureFournisseur($this->db);
54  }
55 
66  public function get($id)
67  {
68  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->lire) {
69  throw new RestException(401);
70  }
71 
72  $result = $this->invoice->fetch($id);
73  if (!$result) {
74  throw new RestException(404, 'Supplier invoice not found');
75  }
76 
77  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
78  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
79  }
80 
81  $this->invoice->fetchObjectLinked();
82  return $this->_cleanObjectDatas($this->invoice);
83  }
84 
101  public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $status = '', $sqlfilters = '')
102  {
103  global $db;
104 
105  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->lire) {
106  throw new RestException(401);
107  }
108 
109  $obj_ret = array();
110 
111  // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
112  $socids = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $thirdparty_ids;
113 
114  // If the internal user must only see his customers, force searching by him
115  $search_sale = 0;
116  if (!DolibarrApiAccess::$user->rights->societe->client->voir) {
117  $search_sale = DolibarrApiAccess::$user->id;
118  }
119 
120  $sql = "SELECT t.rowid";
121  // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
122  if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) {
123  $sql .= ", sc.fk_soc, sc.fk_user";
124  }
125  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as t";
126 
127  // We need this table joined to the select in order to filter by sale
128  if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) {
129  $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
130  }
131 
132  $sql .= ' WHERE t.entity IN ('.getEntity('supplier_invoice').')';
133  if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) {
134  $sql .= " AND t.fk_soc = sc.fk_soc";
135  }
136  if ($socids) {
137  $sql .= " AND t.fk_soc IN (".$this->db->sanitize($socids).")";
138  }
139  if ($search_sale > 0) {
140  $sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
141  }
142 
143  // Filter by status
144  if ($status == 'draft') {
145  $sql .= " AND t.fk_statut IN (0)";
146  }
147  if ($status == 'unpaid') {
148  $sql .= " AND t.fk_statut IN (1)";
149  }
150  if ($status == 'paid') {
151  $sql .= " AND t.fk_statut IN (2)";
152  }
153  if ($status == 'cancelled') {
154  $sql .= " AND t.fk_statut IN (3)";
155  }
156  // Insert sale filter
157  if ($search_sale > 0) {
158  $sql .= " AND sc.fk_user = ".((int) $search_sale);
159  }
160  // Add sql filters
161  if ($sqlfilters) {
162  $errormessage = '';
163  if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
164  throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
165  }
166  $regexstring = '\‍(([^:\'\‍(\‍)]+:[^:\'\‍(\‍)]+:[^\‍(\‍)]+)\‍)';
167  $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
168  }
169 
170  $sql .= $this->db->order($sortfield, $sortorder);
171  if ($limit) {
172  if ($page < 0) {
173  $page = 0;
174  }
175  $offset = $limit * $page;
176 
177  $sql .= $this->db->plimit($limit + 1, $offset);
178  }
179 
180  $result = $this->db->query($sql);
181  if ($result) {
182  $i = 0;
183  $num = $this->db->num_rows($result);
184  $min = min($num, ($limit <= 0 ? $num : $limit));
185  while ($i < $min) {
186  $obj = $this->db->fetch_object($result);
187  $invoice_static = new FactureFournisseur($this->db);
188  if ($invoice_static->fetch($obj->rowid)) {
189  $obj_ret[] = $this->_cleanObjectDatas($invoice_static);
190  }
191  $i++;
192  }
193  } else {
194  throw new RestException(503, 'Error when retrieve supplier invoice list : '.$this->db->lasterror());
195  }
196  if (!count($obj_ret)) {
197  throw new RestException(404, 'No supplier invoice found');
198  }
199  return $obj_ret;
200  }
201 
216  public function post($request_data = null)
217  {
218  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
219  throw new RestException(401, "Insuffisant rights");
220  }
221  // Check mandatory fields
222  $result = $this->_validate($request_data);
223 
224  foreach ($request_data as $field => $value) {
225  $this->invoice->$field = $value;
226  }
227  if (!array_key_exists('date', $request_data)) {
228  $this->invoice->date = dol_now();
229  }
230 
231  if ($this->invoice->create(DolibarrApiAccess::$user) < 0) {
232  throw new RestException(500, "Error creating order", array_merge(array($this->invoice->error), $this->invoice->errors));
233  }
234  return $this->invoice->id;
235  }
236 
248  public function put($id, $request_data = null)
249  {
250  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
251  throw new RestException(401);
252  }
253 
254  $result = $this->invoice->fetch($id);
255  if (!$result) {
256  throw new RestException(404, 'Supplier invoice not found');
257  }
258 
259  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
260  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
261  }
262 
263  foreach ($request_data as $field => $value) {
264  if ($field == 'id') {
265  continue;
266  }
267  $this->invoice->$field = $value;
268  }
269 
270  if ($this->invoice->update($id, DolibarrApiAccess::$user)) {
271  return $this->get($id);
272  }
273 
274  return false;
275  }
276 
288  public function delete($id)
289  {
290  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->supprimer) {
291  throw new RestException(401);
292  }
293  $result = $this->invoice->fetch($id);
294  if (!$result) {
295  throw new RestException(404, 'Supplier invoice not found');
296  }
297 
298  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
299  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
300  }
301 
302  if ($this->invoice->delete(DolibarrApiAccess::$user) < 0) {
303  throw new RestException(500, 'Error when deleting invoice');
304  }
305 
306  return array(
307  'success' => array(
308  'code' => 200,
309  'message' => 'Supplier invoice deleted'
310  )
311  );
312  }
313 
331  public function validate($id, $idwarehouse = 0, $notrigger = 0)
332  {
333  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
334  throw new RestException(401);
335  }
336  $result = $this->invoice->fetch($id);
337  if (!$result) {
338  throw new RestException(404, 'Invoice not found');
339  }
340 
341  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
342  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
343  }
344 
345  $result = $this->invoice->validate(DolibarrApiAccess::$user, '', $idwarehouse, $notrigger);
346  if ($result == 0) {
347  throw new RestException(304, 'Error nothing done. The invoice is already validated');
348  }
349  if ($result < 0) {
350  throw new RestException(500, 'Error when validating Invoice: '.$this->invoice->error);
351  }
352 
353  return array(
354  'success' => array(
355  'code' => 200,
356  'message' => 'Invoice validated (Ref='.$this->invoice->ref.')'
357  )
358  );
359  }
360 
374  public function getPayments($id)
375  {
376  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->lire) {
377  throw new RestException(401);
378  }
379  if (empty($id)) {
380  throw new RestException(400, 'Invoice ID is mandatory');
381  }
382 
383  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
384  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
385  }
386 
387  $result = $this->invoice->fetch($id);
388  if (!$result) {
389  throw new RestException(404, 'Invoice not found');
390  }
391 
392  $result = $this->invoice->getListOfPayments();
393  if ($result < 0) {
394  throw new RestException(405, $this->invoice->error);
395  }
396 
397  return $result;
398  }
399 
400 
421  public function addPayment($id, $datepaye, $payment_mode_id, $closepaidinvoices, $accountid, $num_payment = '', $comment = '', $chqemetteur = '', $chqbank = '')
422  {
423  global $conf;
424 
425  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
426  throw new RestException(403);
427  }
428  if (empty($id)) {
429  throw new RestException(400, 'Invoice ID is mandatory');
430  }
431 
432  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
433  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
434  }
435 
436  if (isModEnabled("banque")) {
437  if (empty($accountid)) {
438  throw new RestException(400, 'Bank account ID is mandatory');
439  }
440  }
441 
442  if (empty($payment_mode_id)) {
443  throw new RestException(400, 'Payment mode ID is mandatory');
444  }
445 
446 
447  $result = $this->invoice->fetch($id);
448  if (!$result) {
449  throw new RestException(404, 'Invoice not found');
450  }
451 
452  // Calculate amount to pay
453  $totalpaid = $this->invoice->getSommePaiement();
454  $totaldeposits = $this->invoice->getSumDepositsUsed();
455  $resteapayer = price2num($this->invoice->total_ttc - $totalpaid - $totaldeposits, 'MT');
456 
457  $this->db->begin();
458 
459  $amounts = array();
460  $multicurrency_amounts = array();
461 
462  $resteapayer = price2num($resteapayer, 'MT');
463  $amounts[$id] = $resteapayer;
464 
465  // Multicurrency
466  $newvalue = price2num($this->invoice->multicurrency_total_ttc, 'MT');
467  $multicurrency_amounts[$id] = $newvalue;
468 
469  // Creation of payment line
470  $paiement = new PaiementFourn($this->db);
471  $paiement->datepaye = $datepaye;
472  $paiement->amounts = $amounts; // Array with all payments dispatching with invoice id
473  $paiement->multicurrency_amounts = $multicurrency_amounts; // Array with all payments dispatching
474  $paiement->paiementid = $payment_mode_id;
475  $paiement->paiementcode = dol_getIdFromCode($this->db, $payment_mode_id, 'c_paiement', 'id', 'code', 1);
476  $paiement->num_payment = $num_payment;
477  $paiement->note_public = $comment;
478 
479  $paiement_id = $paiement->create(DolibarrApiAccess::$user, ($closepaidinvoices == 'yes' ? 1 : 0)); // This include closing invoices
480  if ($paiement_id < 0) {
481  $this->db->rollback();
482  throw new RestException(400, 'Payment error : '.$paiement->error);
483  }
484 
485  if (isModEnabled("banque")) {
486  $result = $paiement->addPaymentToBank(DolibarrApiAccess::$user, 'payment_supplier', '(SupplierInvoicePayment)', $accountid, $chqemetteur, $chqbank);
487  if ($result < 0) {
488  $this->db->rollback();
489  throw new RestException(400, 'Add payment to bank error : '.$paiement->error);
490  }
491  }
492 
493  $this->db->commit();
494 
495  return $paiement_id;
496  }
497 
507  public function getLines($id)
508  {
509  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
510  throw new RestException(401);
511  }
512 
513  $result = $this->invoice->fetch($id);
514  if (!$result) {
515  throw new RestException(404, 'Supplier invoice not found');
516  }
517 
518  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
519  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
520  }
521  $this->invoice->fetch_lines();
522  $result = array();
523  foreach ($this->invoice->lines as $line) {
524  array_push($result, $this->_cleanObjectDatas($line));
525  }
526  return $result;
527  }
528 
543  public function postLine($id, $request_data = null)
544  {
545  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
546  throw new RestException(401);
547  }
548 
549  $result = $this->invoice->fetch($id);
550  if (!$result) {
551  throw new RestException(404, 'Supplier invoice not found');
552  }
553 
554  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
555  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
556  }
557 
558  $request_data = (object) $request_data;
559 
560  $request_data->description = sanitizeVal($request_data->description, 'restricthtml');
561  $request_data->ref_supplier = sanitizeVal($request_data->ref_supplier);
562 
563  $updateRes = $this->invoice->addline(
564  $request_data->description,
565  $request_data->pu_ht,
566  $request_data->tva_tx,
567  $request_data->localtax1_tx,
568  $request_data->localtax2_tx,
569  $request_data->qty,
570  $request_data->fk_product,
571  $request_data->remise_percent,
572  $request_data->date_start,
573  $request_data->date_end,
574  $request_data->ventil,
575  $request_data->info_bits,
576  $request_data->price_base_type ? $request_data->price_base_type : 'HT',
577  $request_data->product_type,
578  $request_data->rang,
579  false,
580  $request_data->array_options,
581  $request_data->fk_unit,
582  $request_data->origin_id,
583  $request_data->multicurrency_subprice,
584  $request_data->ref_supplier,
585  $request_data->special_code
586  );
587 
588  if ($updateRes < 0) {
589  throw new RestException(400, 'Unable to insert the new line. Check your inputs. '.$this->invoice->error);
590  }
591 
592  return $updateRes;
593  }
594 
610  public function putLine($id, $lineid, $request_data = null)
611  {
612  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
613  throw new RestException(401);
614  }
615 
616  $result = $this->invoice->fetch($id);
617  if (!$result) {
618  throw new RestException(404, 'Supplier invoice not found');
619  }
620 
621  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
622  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
623  }
624 
625  $request_data = (object) $request_data;
626 
627  $request_data->description = sanitizeVal($request_data->description, 'restricthtml');
628  $request_data->ref_supplier = sanitizeVal($request_data->ref_supplier);
629 
630  $updateRes = $this->invoice->updateline(
631  $lineid,
632  $request_data->description,
633  $request_data->pu_ht,
634  $request_data->tva_tx,
635  $request_data->localtax1_tx,
636  $request_data->localtax2_tx,
637  $request_data->qty,
638  $request_data->fk_product,
639  $request_data->price_base_type ? $request_data->price_base_type : 'HT',
640  $request_data->info_bits,
641  $request_data->product_type,
642  $request_data->remise_percent,
643  false,
644  $request_data->date_start,
645  $request_data->date_end,
646  $request_data->array_options,
647  $request_data->fk_unit,
648  $request_data->multicurrency_subprice,
649  $request_data->ref_supplier,
650  $request_data->rang
651  );
652 
653  if ($updateRes > 0) {
654  $result = $this->get($id);
655  unset($result->line);
656  return $this->_cleanObjectDatas($result);
657  } else {
658  throw new RestException(304, $this->invoice->error);
659  }
660  }
661 
677  public function deleteLine($id, $lineid)
678  {
679  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
680  throw new RestException(401);
681  }
682 
683  $result = $this->invoice->fetch($id);
684  if (!$result) {
685  throw new RestException(404, 'Supplier invoice not found');
686  }
687 
688  if (empty($lineid)) {
689  throw new RestException(400, 'Line ID is mandatory');
690  }
691 
692  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
693  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
694  }
695 
696  // TODO Check the lineid $lineid is a line of ojbect
697 
698  $updateRes = $this->invoice->deleteline($lineid);
699  if ($updateRes > 0) {
700  return $this->get($id);
701  } else {
702  throw new RestException(405, $this->invoice->error);
703  }
704  }
705 
706  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
713  protected function _cleanObjectDatas($object)
714  {
715  // phpcs:enable
716  $object = parent::_cleanObjectDatas($object);
717 
718  unset($object->rowid);
719  unset($object->barcode_type);
720  unset($object->barcode_type_code);
721  unset($object->barcode_type_label);
722  unset($object->barcode_type_coder);
723 
724  return $object;
725  }
726 
735  private function _validate($data)
736  {
737  $invoice = array();
738  foreach (SupplierInvoices::$FIELDS as $field) {
739  if (!isset($data[$field])) {
740  throw new RestException(400, "$field field missing");
741  }
742  $invoice[$field] = $data[$field];
743  }
744  return $invoice;
745  }
746 }
Class for API REST v1.
Definition: api.class.php:31
static _checkAccessToResource($resource, $resource_id=0, $dbtablename='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid')
Check access by user to a given resource.
Definition: api.class.php:283
_checkFilters($sqlfilters, &$error='')
Return if a $sqlfilters parameter is valid.
Definition: api.class.php:310
Class to manage suppliers invoices.
Class to manage payments for supplier invoices.
validate($id, $idwarehouse=0, $notrigger=0)
Validate an invoice.
addPayment($id, $datepaye, $payment_mode_id, $closepaidinvoices, $accountid, $num_payment='', $comment='', $chqemetteur='', $chqbank='')
Add payment line to a specific supplier invoice with the remain to pay as amount.
deleteLine($id, $lineid)
Deletes a line of a given supplier invoice.
getLines($id)
Get lines of a supplier invoice.
getPayments($id)
Get list of payments of a given supplier invoice.
_cleanObjectDatas($object)
Clean sensible object datas.
index($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0, $thirdparty_ids='', $status='', $sqlfilters='')
List invoices.
post($request_data=null)
Create supplier invoice object.
postLine($id, $request_data=null)
Add a line to given supplier invoice.
put($id, $request_data=null)
Update supplier invoice.
_validate($data)
Validate fields before create or update object.
putLine($id, $lineid, $request_data=null)
Update a line to a given supplier invoice.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_now($mode='auto')
Return date for now.
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
sanitizeVal($out='', $check='alphanohtml', $filter=null, $options=null)
Return a sanitized or empty value after checking value against a rule.
isModEnabled($module)
Is Dolibarr module enabled.
$conf db
API class for accounts.
Definition: inc.php:41