dolibarr  16.0.5
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  $result = $this->invoice->fetch($id);
384  if (!$result) {
385  throw new RestException(404, 'Invoice not found');
386  }
387 
388  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
389  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
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  $result = $this->invoice->fetch($id);
433  if (!$result) {
434  throw new RestException(404, 'Invoice not found');
435  }
436 
437  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
438  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
439  }
440 
441  if (!empty($conf->banque->enabled)) {
442  if (empty($accountid)) {
443  throw new RestException(400, 'Bank account ID is mandatory');
444  }
445  }
446 
447  if (empty($payment_mode_id)) {
448  throw new RestException(400, 'Payment mode ID is mandatory');
449  }
450 
451  // Calculate amount to pay
452  $totalpaid = $this->invoice->getSommePaiement();
453  $totaldeposits = $this->invoice->getSumDepositsUsed();
454  $resteapayer = price2num($this->invoice->total_ttc - $totalpaid - $totaldeposits, 'MT');
455 
456  $this->db->begin();
457 
458  $amounts = array();
459  $multicurrency_amounts = array();
460 
461  $resteapayer = price2num($resteapayer, 'MT');
462  $amounts[$id] = $resteapayer;
463 
464  // Multicurrency
465  $newvalue = price2num($this->invoice->multicurrency_total_ttc, 'MT');
466  $multicurrency_amounts[$id] = $newvalue;
467 
468  // Creation of payment line
469  $paiement = new PaiementFourn($this->db);
470  $paiement->datepaye = $datepaye;
471  $paiement->amounts = $amounts; // Array with all payments dispatching with invoice id
472  $paiement->multicurrency_amounts = $multicurrency_amounts; // Array with all payments dispatching
473  $paiement->paiementid = $payment_mode_id;
474  $paiement->paiementcode = dol_getIdFromCode($this->db, $payment_mode_id, 'c_paiement', 'id', 'code', 1);
475  $paiement->num_payment = $num_payment;
476  $paiement->note_public = $comment;
477 
478  $paiement_id = $paiement->create(DolibarrApiAccess::$user, ($closepaidinvoices == 'yes' ? 1 : 0)); // This include closing invoices
479  if ($paiement_id < 0) {
480  $this->db->rollback();
481  throw new RestException(400, 'Payment error : '.$paiement->error);
482  }
483 
484  if (!empty($conf->banque->enabled)) {
485  $result = $paiement->addPaymentToBank(DolibarrApiAccess::$user, 'payment_supplier', '(SupplierInvoicePayment)', $accountid, $chqemetteur, $chqbank);
486  if ($result < 0) {
487  $this->db->rollback();
488  throw new RestException(400, 'Add payment to bank error : '.$paiement->error);
489  }
490  }
491 
492  $this->db->commit();
493 
494  return $paiement_id;
495  }
496 
506  public function getLines($id)
507  {
508  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
509  throw new RestException(401);
510  }
511 
512  $result = $this->invoice->fetch($id);
513  if (!$result) {
514  throw new RestException(404, 'Supplier invoice not found');
515  }
516 
517  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
518  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
519  }
520  $this->invoice->fetch_lines();
521  $result = array();
522  foreach ($this->invoice->lines as $line) {
523  array_push($result, $this->_cleanObjectDatas($line));
524  }
525  return $result;
526  }
527 
542  public function postLine($id, $request_data = null)
543  {
544  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
545  throw new RestException(401);
546  }
547 
548  $result = $this->invoice->fetch($id);
549  if (!$result) {
550  throw new RestException(404, 'Supplier invoice not found');
551  }
552 
553  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
554  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
555  }
556 
557  $request_data = (object) $request_data;
558 
559  $request_data->description = sanitizeVal($request_data->description, 'restricthtml');
560  $request_data->ref_supplier = sanitizeVal($request_data->ref_supplier);
561 
562  $updateRes = $this->invoice->addline(
563  $request_data->description,
564  $request_data->pu_ht,
565  $request_data->tva_tx,
566  $request_data->localtax1_tx,
567  $request_data->localtax2_tx,
568  $request_data->qty,
569  $request_data->fk_product,
570  $request_data->remise_percent,
571  $request_data->date_start,
572  $request_data->date_end,
573  $request_data->ventil,
574  $request_data->info_bits,
575  $request_data->price_base_type ? $request_data->price_base_type : 'HT',
576  $request_data->product_type,
577  $request_data->rang,
578  false,
579  $request_data->array_options,
580  $request_data->fk_unit,
581  $request_data->origin_id,
582  $request_data->multicurrency_subprice,
583  $request_data->ref_supplier,
584  $request_data->special_code
585  );
586 
587  if ($updateRes < 0) {
588  throw new RestException(400, 'Unable to insert the new line. Check your inputs. '.$this->invoice->error);
589  }
590 
591  return $updateRes;
592  }
593 
609  public function putLine($id, $lineid, $request_data = null)
610  {
611  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
612  throw new RestException(401);
613  }
614 
615  $result = $this->invoice->fetch($id);
616  if (!$result) {
617  throw new RestException(404, 'Supplier invoice not found');
618  }
619 
620  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
621  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
622  }
623 
624  $request_data = (object) $request_data;
625 
626  $request_data->description = sanitizeVal($request_data->description, 'restricthtml');
627  $request_data->ref_supplier = sanitizeVal($request_data->ref_supplier);
628 
629  $updateRes = $this->invoice->updateline(
630  $lineid,
631  $request_data->description,
632  $request_data->pu_ht,
633  $request_data->tva_tx,
634  $request_data->localtax1_tx,
635  $request_data->localtax2_tx,
636  $request_data->qty,
637  $request_data->fk_product,
638  $request_data->price_base_type ? $request_data->price_base_type : 'HT',
639  $request_data->info_bits,
640  $request_data->product_type,
641  $request_data->remise_percent,
642  false,
643  $request_data->date_start,
644  $request_data->date_end,
645  $request_data->array_options,
646  $request_data->fk_unit,
647  $request_data->multicurrency_subprice,
648  $request_data->ref_supplier,
649  $request_data->rang
650  );
651 
652  if ($updateRes > 0) {
653  $result = $this->get($id);
654  unset($result->line);
655  return $this->_cleanObjectDatas($result);
656  } else {
657  throw new RestException(304, $this->invoice->error);
658  }
659  }
660 
676  public function deleteLine($id, $lineid)
677  {
678  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
679  throw new RestException(401);
680  }
681 
682  $result = $this->invoice->fetch($id);
683  if (!$result) {
684  throw new RestException(404, 'Supplier invoice not found');
685  }
686 
687  if (empty($lineid)) {
688  throw new RestException(400, 'Line ID is mandatory');
689  }
690 
691  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
692  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
693  }
694 
695  // TODO Check the lineid $lineid is a line of ojbect
696 
697  $updateRes = $this->invoice->deleteline($lineid);
698  if ($updateRes > 0) {
699  return $this->get($id);
700  } else {
701  throw new RestException(405, $this->invoice->error);
702  }
703  }
704 
705  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
712  protected function _cleanObjectDatas($object)
713  {
714  // phpcs:enable
715  $object = parent::_cleanObjectDatas($object);
716 
717  unset($object->rowid);
718  unset($object->barcode_type);
719  unset($object->barcode_type_code);
720  unset($object->barcode_type_label);
721  unset($object->barcode_type_coder);
722 
723  return $object;
724  }
725 
734  private function _validate($data)
735  {
736  $invoice = array();
737  foreach (SupplierInvoices::$FIELDS as $field) {
738  if (!isset($data[$field])) {
739  throw new RestException(400, "$field field missing");
740  }
741  $invoice[$field] = $data[$field];
742  }
743  return $invoice;
744  }
745 }
SupplierInvoices\postLine
postLine($id, $request_data=null)
Add a line to given supplier invoice.
Definition: api_supplier_invoices.class.php:542
SupplierInvoices\_cleanObjectDatas
_cleanObjectDatas($object)
Clean sensible object datas.
Definition: api_supplier_invoices.class.php:712
db
$conf db
API class for accounts.
Definition: inc.php:41
SupplierInvoices\getPayments
getPayments($id)
Get list of payments of a given supplier invoice.
Definition: api_supplier_invoices.class.php:374
SupplierInvoices\post
post($request_data=null)
Create supplier invoice object.
Definition: api_supplier_invoices.class.php:216
SupplierInvoices
Definition: api_supplier_invoices.class.php:31
FactureFournisseur
Class to manage suppliers invoices.
Definition: fournisseur.facture.class.php:53
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
DolibarrApi\_checkAccessToResource
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
price2num
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
Definition: functions.lib.php:5661
DolibarrApi
Class for API REST v1.
Definition: api.class.php:30
dol_getIdFromCode
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
Definition: functions.lib.php:8535
SupplierInvoices\getLines
getLines($id)
Get lines of a supplier invoice.
Definition: api_supplier_invoices.class.php:506
SupplierInvoices\__construct
__construct()
Constructor.
Definition: api_supplier_invoices.class.php:49
SupplierInvoices\_validate
_validate($data)
Validate fields before create or update object.
Definition: api_supplier_invoices.class.php:734
DolibarrApi\_checkFilters
_checkFilters($sqlfilters, &$error='')
Return if a $sqlfilters parameter is valid.
Definition: api.class.php:310
SupplierInvoices\putLine
putLine($id, $lineid, $request_data=null)
Update a line to a given supplier invoice.
Definition: api_supplier_invoices.class.php:609
SupplierInvoices\put
put($id, $request_data=null)
Update supplier invoice.
Definition: api_supplier_invoices.class.php:248
SupplierInvoices\addPayment
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.
Definition: api_supplier_invoices.class.php:421
PaiementFourn
Class to manage payments for supplier invoices.
Definition: paiementfourn.class.php:37
SupplierInvoices\index
index($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0, $thirdparty_ids='', $status='', $sqlfilters='')
List invoices.
Definition: api_supplier_invoices.class.php:101
dol_now
dol_now($mode='auto')
Return date for now.
Definition: functions.lib.php:2845
SupplierInvoices\validate
validate($id, $idwarehouse=0, $notrigger=0)
Validate an invoice.
Definition: api_supplier_invoices.class.php:331
SupplierInvoices\deleteLine
deleteLine($id, $lineid)
Deletes a line of a given supplier invoice.
Definition: api_supplier_invoices.class.php:676