dolibarr  13.0.2
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  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  $obj_ret = array();
106 
107  // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
108  $socids = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $thirdparty_ids;
109 
110  // If the internal user must only see his customers, force searching by him
111  $search_sale = 0;
112  if (!DolibarrApiAccess::$user->rights->societe->client->voir) $search_sale = DolibarrApiAccess::$user->id;
113 
114  $sql = "SELECT t.rowid";
115  // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
116  if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user";
117  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as t";
118 
119  // We need this table joined to the select in order to filter by sale
120  if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
121 
122  $sql .= ' WHERE t.entity IN ('.getEntity('supplier_invoice').')';
123  if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) $sql .= " AND t.fk_soc = sc.fk_soc";
124  if ($socids) $sql .= " AND t.fk_soc IN (".$socids.")";
125  if ($search_sale > 0) $sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
126 
127  // Filter by status
128  if ($status == 'draft') {
129  $sql .= " AND t.fk_statut IN (0)";
130  }
131  if ($status == 'unpaid') {
132  $sql .= " AND t.fk_statut IN (1)";
133  }
134  if ($status == 'paid') {
135  $sql .= " AND t.fk_statut IN (2)";
136  }
137  if ($status == 'cancelled') {
138  $sql .= " AND t.fk_statut IN (3)";
139  }
140  // Insert sale filter
141  if ($search_sale > 0) {
142  $sql .= " AND sc.fk_user = ".$search_sale;
143  }
144  // Add sql filters
145  if ($sqlfilters)
146  {
147  if (!DolibarrApi::_checkFilters($sqlfilters))
148  {
149  throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
150  }
151  $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
152  $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
153  }
154 
155  $sql .= $this->db->order($sortfield, $sortorder);
156  if ($limit) {
157  if ($page < 0)
158  {
159  $page = 0;
160  }
161  $offset = $limit * $page;
162 
163  $sql .= $this->db->plimit($limit + 1, $offset);
164  }
165 
166  $result = $this->db->query($sql);
167  if ($result) {
168  $i = 0;
169  $num = $this->db->num_rows($result);
170  $min = min($num, ($limit <= 0 ? $num : $limit));
171  while ($i < $min)
172  {
173  $obj = $this->db->fetch_object($result);
174  $invoice_static = new FactureFournisseur($this->db);
175  if ($invoice_static->fetch($obj->rowid)) {
176  $obj_ret[] = $this->_cleanObjectDatas($invoice_static);
177  }
178  $i++;
179  }
180  } else {
181  throw new RestException(503, 'Error when retrieve supplier invoice list : '.$this->db->lasterror());
182  }
183  if (!count($obj_ret)) {
184  throw new RestException(404, 'No supplier invoice found');
185  }
186  return $obj_ret;
187  }
188 
199  public function post($request_data = null)
200  {
201  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
202  throw new RestException(401, "Insuffisant rights");
203  }
204  // Check mandatory fields
205  $result = $this->_validate($request_data);
206 
207  foreach ($request_data as $field => $value) {
208  $this->invoice->$field = $value;
209  }
210  if (!array_key_exists('date', $request_data)) {
211  $this->invoice->date = dol_now();
212  }
213 
214  if ($this->invoice->create(DolibarrApiAccess::$user) < 0) {
215  throw new RestException(500, "Error creating order", array_merge(array($this->invoice->error), $this->invoice->errors));
216  }
217  return $this->invoice->id;
218  }
219 
231  public function put($id, $request_data = null)
232  {
233  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
234  throw new RestException(401);
235  }
236 
237  $result = $this->invoice->fetch($id);
238  if (!$result) {
239  throw new RestException(404, 'Supplier invoice not found');
240  }
241 
242  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
243  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
244  }
245 
246  foreach ($request_data as $field => $value) {
247  if ($field == 'id') continue;
248  $this->invoice->$field = $value;
249  }
250 
251  if ($this->invoice->update($id, DolibarrApiAccess::$user))
252  return $this->get($id);
253 
254  return false;
255  }
256 
268  public function delete($id)
269  {
270  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->supprimer) {
271  throw new RestException(401);
272  }
273  $result = $this->invoice->fetch($id);
274  if (!$result) {
275  throw new RestException(404, 'Supplier invoice not found');
276  }
277 
278  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
279  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
280  }
281 
282  if ($this->invoice->delete(DolibarrApiAccess::$user) < 0)
283  {
284  throw new RestException(500);
285  }
286 
287  return array(
288  'success' => array(
289  'code' => 200,
290  'message' => 'Supplier invoice deleted'
291  )
292  );
293  }
294 
312  public function validate($id, $idwarehouse = 0, $notrigger = 0)
313  {
314  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
315  throw new RestException(401);
316  }
317  $result = $this->invoice->fetch($id);
318  if (!$result) {
319  throw new RestException(404, 'Invoice not found');
320  }
321 
322  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
323  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
324  }
325 
326  $result = $this->invoice->validate(DolibarrApiAccess::$user, '', $idwarehouse, $notrigger);
327  if ($result == 0) {
328  throw new RestException(304, 'Error nothing done. The invoice is already validated');
329  }
330  if ($result < 0) {
331  throw new RestException(500, 'Error when validating Invoice: '.$this->invoice->error);
332  }
333 
334  return array(
335  'success' => array(
336  'code' => 200,
337  'message' => 'Invoice validated (Ref='.$this->invoice->ref.')'
338  )
339  );
340  }
341 
355  public function getPayments($id)
356  {
357  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->lire) {
358  throw new RestException(401);
359  }
360  if (empty($id)) {
361  throw new RestException(400, 'Invoice ID is mandatory');
362  }
363 
364  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
365  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
366  }
367 
368  $result = $this->invoice->fetch($id);
369  if (!$result) {
370  throw new RestException(404, 'Invoice not found');
371  }
372 
373  $result = $this->invoice->getListOfPayments();
374  if ($result < 0) {
375  throw new RestException(405, $this->invoice->error);
376  }
377 
378  return $result;
379  }
380 
381 
402  public function addPayment($id, $datepaye, $payment_mode_id, $closepaidinvoices, $accountid, $num_payment = '', $comment = '', $chqemetteur = '', $chqbank = '')
403  {
404  global $conf;
405 
406  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
407  throw new RestException(403);
408  }
409  if (empty($id)) {
410  throw new RestException(400, 'Invoice ID is mandatory');
411  }
412 
413  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
414  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
415  }
416 
417  if (!empty($conf->banque->enabled)) {
418  if (empty($accountid)) {
419  throw new RestException(400, 'Bank account ID is mandatory');
420  }
421  }
422 
423  if (empty($payment_mode_id)) {
424  throw new RestException(400, 'Payment mode ID is mandatory');
425  }
426 
427 
428  $result = $this->invoice->fetch($id);
429  if (!$result) {
430  throw new RestException(404, 'Invoice not found');
431  }
432 
433  // Calculate amount to pay
434  $totalpaye = $this->invoice->getSommePaiement();
435  $totaldeposits = $this->invoice->getSumDepositsUsed();
436  $resteapayer = price2num($this->invoice->total_ttc - $totalpaye - $totaldeposits, 'MT');
437 
438  $this->db->begin();
439 
440  $amounts = array();
441  $multicurrency_amounts = array();
442 
443  $resteapayer = price2num($resteapayer, 'MT');
444  $amounts[$id] = $resteapayer;
445 
446  // Multicurrency
447  $newvalue = price2num($this->invoice->multicurrency_total_ttc, 'MT');
448  $multicurrency_amounts[$id] = $newvalue;
449 
450  // Creation of payment line
451  $paiement = new PaiementFourn($this->db);
452  $paiement->datepaye = $datepaye;
453  $paiement->amounts = $amounts; // Array with all payments dispatching with invoice id
454  $paiement->multicurrency_amounts = $multicurrency_amounts; // Array with all payments dispatching
455  $paiement->paiementid = $payment_mode_id;
456  $paiement->paiementcode = dol_getIdFromCode($this->db, $payment_mode_id, 'c_paiement', 'id', 'code', 1);
457  $paiement->oper = $paiement->paiementcode; // For backward compatibility
458  $paiement->num_payment = $num_payment;
459  $paiement->note_public = $comment;
460 
461  $paiement_id = $paiement->create(DolibarrApiAccess::$user, ($closepaidinvoices == 'yes' ? 1 : 0)); // This include closing invoices
462  if ($paiement_id < 0)
463  {
464  $this->db->rollback();
465  throw new RestException(400, 'Payment error : '.$paiement->error);
466  }
467 
468  if (!empty($conf->banque->enabled)) {
469  $result = $paiement->addPaymentToBank(DolibarrApiAccess::$user, 'payment_supplier', '(SupplierInvoicePayment)', $accountid, $chqemetteur, $chqbank);
470  if ($result < 0)
471  {
472  $this->db->rollback();
473  throw new RestException(400, 'Add payment to bank error : '.$paiement->error);
474  }
475  }
476 
477  $this->db->commit();
478 
479  return $paiement_id;
480  }
481 
491  public function getLines($id)
492  {
493  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
494  throw new RestException(401);
495  }
496 
497  $result = $this->invoice->fetch($id);
498  if (!$result) {
499  throw new RestException(404, 'Supplier invoice not found');
500  }
501 
502  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
503  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
504  }
505  $this->invoice->fetch_lines();
506  $result = array();
507  foreach ($this->invoice->lines as $line) {
508  array_push($result, $this->_cleanObjectDatas($line));
509  }
510  return $result;
511  }
512 
523  public function postLine($id, $request_data = null)
524  {
525  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
526  throw new RestException(401);
527  }
528 
529  $result = $this->invoice->fetch($id);
530  if (!$result) {
531  throw new RestException(404, 'Supplier invoice not found');
532  }
533 
534  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
535  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
536  }
537  $request_data = (object) $request_data;
538 
539  $updateRes = $this->invoice->addline(
540  $request_data->description,
541  $request_data->pu_ht,
542  $request_data->tva_tx,
543  $request_data->localtax1_tx,
544  $request_data->localtax2_tx,
545  $request_data->qty,
546  $request_data->fk_product,
547  $request_data->remise_percent,
548  $request_data->date_start,
549  $request_data->date_end,
550  $request_data->ventil,
551  $request_data->info_bits,
552  'HT',
553  $request_data->product_type,
554  $request_data->rang,
555  false,
556  $request_data->array_options,
557  $request_data->fk_unit,
558  $request_data->origin_id,
559  $request_data->multicurrency_subprice,
560  $request_data->ref_supplier,
561  $request_data->special_code
562  );
563 
564  if ($updateRes < 0) {
565  throw new RestException(400, 'Unable to insert the new line. Check your inputs. '.$this->invoice->error);
566  }
567 
568  return $updateRes;
569  }
570 
586  public function putLine($id, $lineid, $request_data = null)
587  {
588  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
589  throw new RestException(401);
590  }
591 
592  $result = $this->invoice->fetch($id);
593  if (!$result) {
594  throw new RestException(404, 'Supplier invoice not found');
595  }
596 
597  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
598  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
599  }
600  $request_data = (object) $request_data;
601  $updateRes = $this->invoice->updateline(
602  $lineid,
603  $request_data->description,
604  $request_data->pu_ht,
605  $request_data->tva_tx,
606  $request_data->localtax1_tx,
607  $request_data->localtax2_tx,
608  $request_data->qty,
609  $request_data->fk_product,
610  'HT',
611  $request_data->info_bits,
612  $request_data->product_type,
613  $request_data->remise_percent,
614  false,
615  $request_data->date_start,
616  $request_data->date_end,
617  $request_data->array_options,
618  $request_data->fk_unit,
619  $request_data->multicurrency_subprice,
620  $request_data->ref_supplier
621  );
622 
623  if ($updateRes > 0) {
624  $result = $this->get($id);
625  unset($result->line);
626  return $this->_cleanObjectDatas($result);
627  } else {
628  throw new RestException(304, $this->invoice->error);
629  }
630  }
631 
647  public function deleteLine($id, $lineid)
648  {
649  if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
650  throw new RestException(401);
651  }
652 
653  $result = $this->invoice->fetch($id);
654  if (!$result) {
655  throw new RestException(404, 'Supplier invoice not found');
656  }
657 
658  if (empty($lineid)) {
659  throw new RestException(400, 'Line ID is mandatory');
660  }
661 
662  if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
663  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
664  }
665 
666  // TODO Check the lineid $lineid is a line of ojbect
667 
668  $updateRes = $this->invoice->deleteline($lineid);
669  if ($updateRes > 0) {
670  return $this->get($id);
671  } else {
672  throw new RestException(405, $this->invoice->error);
673  }
674  }
675 
676  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
683  protected function _cleanObjectDatas($object)
684  {
685  // phpcs:enable
686  $object = parent::_cleanObjectDatas($object);
687 
688  unset($object->rowid);
689  unset($object->barcode_type);
690  unset($object->barcode_type_code);
691  unset($object->barcode_type_label);
692  unset($object->barcode_type_coder);
693 
694  return $object;
695  }
696 
705  private function _validate($data)
706  {
707  $invoice = array();
708  foreach (SupplierInvoices::$FIELDS as $field) {
709  if (!isset($data[$field]))
710  throw new RestException(400, "$field field missing");
711  $invoice[$field] = $data[$field];
712  }
713  return $invoice;
714  }
715 }
_validate($data)
Validate fields before create or update object.
putLine($id, $lineid, $request_data=null)
Update a line to a given supplier invoice.
dol_now($mode= 'auto')
Return date for now.
post($request_data=null)
Create supplier invoice object.
postLine($id, $request_data=null)
Add a line to given supplier invoice.
Class to manage suppliers invoices.
getPayments($id)
Get list of payments of a given supplier invoice.
_cleanObjectDatas($object)
Clean sensible object datas.
$conf db
API class for accounts.
Definition: inc.php:54
_checkFilters($sqlfilters)
Return if a $sqlfilters parameter is valid.
Definition: api.class.php:278
Class for API REST v1.
Definition: api.class.php:30
validate($id, $idwarehouse=0, $notrigger=0)
Validate an invoice.
deleteLine($id, $lineid)
Deletes a line of a given supplier invoice.
put($id, $request_data=null)
Update supplier invoice.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
index($sortfield="t.rowid", $sortorder= 'ASC', $limit=100, $page=0, $thirdparty_ids= '', $status= '', $sqlfilters= '')
List invoices.
static _checkAccessToResource($resource, $resource_id=0, $dbtablename= '', $feature2= '', $dbt_keyfield= 'fk_soc', $dbt_select= 'rowid')
Check user access to a resource.
Definition: api.class.php:252
dol_getIdFromCode($db, $key, $tablename, $fieldkey= 'code', $fieldid= 'id', $entityfilter=0)
Return an id or code from a code or id.
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. ...
getLines($id)
Get lines of a supplier invoice.
Class to manage payments for supplier invoices.