dolibarr  19.0.0-dev
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->hasRight("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->hasRight("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->hasRight("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->hasRight("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 LEFT JOIN ".MAIN_DB_PREFIX."facture_fourn_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
126 
127  // We need this table joined to the select in order to filter by sale
128  if (!DolibarrApiAccess::$user->hasRight("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->hasRight("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  $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
164  if ($errormessage) {
165  throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
166  }
167  }
168 
169  $sql .= $this->db->order($sortfield, $sortorder);
170  if ($limit) {
171  if ($page < 0) {
172  $page = 0;
173  }
174  $offset = $limit * $page;
175 
176  $sql .= $this->db->plimit($limit + 1, $offset);
177  }
178 
179  $result = $this->db->query($sql);
180  if ($result) {
181  $i = 0;
182  $num = $this->db->num_rows($result);
183  $min = min($num, ($limit <= 0 ? $num : $limit));
184  while ($i < $min) {
185  $obj = $this->db->fetch_object($result);
186  $invoice_static = new FactureFournisseur($this->db);
187  if ($invoice_static->fetch($obj->rowid)) {
188  $obj_ret[] = $this->_cleanObjectDatas($invoice_static);
189  }
190  $i++;
191  }
192  } else {
193  throw new RestException(503, 'Error when retrieve supplier invoice list : '.$this->db->lasterror());
194  }
195  if (!count($obj_ret)) {
196  throw new RestException(404, 'No supplier invoice found');
197  }
198  return $obj_ret;
199  }
200 
215  public function post($request_data = null)
216  {
217  if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "creer")) {
218  throw new RestException(401, "Insuffisant rights");
219  }
220  // Check mandatory fields
221  $result = $this->_validate($request_data);
222 
223  foreach ($request_data as $field => $value) {
224  $this->invoice->$field = $value;
225  }
226  if (!array_key_exists('date', $request_data)) {
227  $this->invoice->date = dol_now();
228  }
229 
230  if ($this->invoice->create(DolibarrApiAccess::$user) < 0) {
231  throw new RestException(500, "Error creating order", array_merge(array($this->invoice->error), $this->invoice->errors));
232  }
233  return $this->invoice->id;
234  }
235 
247  public function put($id, $request_data = null)
248  {
249  if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "creer")) {
250  throw new RestException(401);
251  }
252 
253  $result = $this->invoice->fetch($id);
254  if (!$result) {
255  throw new RestException(404, 'Supplier invoice not found');
256  }
257 
258  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
259  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
260  }
261 
262  foreach ($request_data as $field => $value) {
263  if ($field == 'id') {
264  continue;
265  }
266  $this->invoice->$field = $value;
267  }
268 
269  if ($this->invoice->update($id, DolibarrApiAccess::$user)) {
270  return $this->get($id);
271  }
272 
273  return false;
274  }
275 
287  public function delete($id)
288  {
289  if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "supprimer")) {
290  throw new RestException(401);
291  }
292  $result = $this->invoice->fetch($id);
293  if (!$result) {
294  throw new RestException(404, 'Supplier invoice not found');
295  }
296 
297  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
298  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
299  }
300 
301  if ($this->invoice->delete(DolibarrApiAccess::$user) < 0) {
302  throw new RestException(500, 'Error when deleting invoice');
303  }
304 
305  return array(
306  'success' => array(
307  'code' => 200,
308  'message' => 'Supplier invoice deleted'
309  )
310  );
311  }
312 
330  public function validate($id, $idwarehouse = 0, $notrigger = 0)
331  {
332  if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "creer")) {
333  throw new RestException(401);
334  }
335  $result = $this->invoice->fetch($id);
336  if (!$result) {
337  throw new RestException(404, 'Invoice not found');
338  }
339 
340  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
341  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
342  }
343 
344  $result = $this->invoice->validate(DolibarrApiAccess::$user, '', $idwarehouse, $notrigger);
345  if ($result == 0) {
346  throw new RestException(304, 'Error nothing done. The invoice is already validated');
347  }
348  if ($result < 0) {
349  throw new RestException(500, 'Error when validating Invoice: '.$this->invoice->error);
350  }
351 
352  return array(
353  'success' => array(
354  'code' => 200,
355  'message' => 'Invoice validated (Ref='.$this->invoice->ref.')'
356  )
357  );
358  }
359 
373  public function getPayments($id)
374  {
375  if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "lire")) {
376  throw new RestException(401);
377  }
378  if (empty($id)) {
379  throw new RestException(400, 'Invoice ID is mandatory');
380  }
381 
382  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
383  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
384  }
385 
386  $result = $this->invoice->fetch($id);
387  if (!$result) {
388  throw new RestException(404, 'Invoice not found');
389  }
390 
391  $result = $this->invoice->getListOfPayments();
392  if ($result < 0) {
393  throw new RestException(405, $this->invoice->error);
394  }
395 
396  return $result;
397  }
398 
399 
420  public function addPayment($id, $datepaye, $payment_mode_id, $closepaidinvoices, $accountid, $num_payment = '', $comment = '', $chqemetteur = '', $chqbank = '')
421  {
422  global $conf;
423 
424  if (!DolibarrApiAccess::$user->hasRight("fournisseur", "facture", "creer")) {
425  throw new RestException(403);
426  }
427  if (empty($id)) {
428  throw new RestException(400, 'Invoice ID is mandatory');
429  }
430 
431  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
432  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
433  }
434 
435  if (isModEnabled("banque")) {
436  if (empty($accountid)) {
437  throw new RestException(400, 'Bank account ID is mandatory');
438  }
439  }
440 
441  if (empty($payment_mode_id)) {
442  throw new RestException(400, 'Payment mode ID is mandatory');
443  }
444 
445 
446  $result = $this->invoice->fetch($id);
447  if (!$result) {
448  throw new RestException(404, 'Invoice not found');
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 (isModEnabled("banque")) {
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->hasRight("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->hasRight("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->hasRight("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->hasRight("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 }
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:282
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.
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
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
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.