dolibarr  19.0.0-dev
api_contracts.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  * Copyright (C) 2018-2020 Frédéric France <frederic.france@netlogic.fr>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20  use Luracast\Restler\RestException;
21 
22  require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
23 
30 class Contracts extends DolibarrApi
31 {
32 
36  static $FIELDS = array(
37  'socid',
38  'date_contrat',
39  'commercial_signature_id',
40  'commercial_suivi_id'
41  );
42 
46  public $contract;
47 
51  public function __construct()
52  {
53  global $db, $conf;
54  $this->db = $db;
55  $this->contract = new Contrat($this->db);
56  }
57 
67  public function get($id)
68  {
69  if (!DolibarrApiAccess::$user->rights->contrat->lire) {
70  throw new RestException(401);
71  }
72 
73  $result = $this->contract->fetch($id);
74  if (!$result) {
75  throw new RestException(404, 'Contract not found');
76  }
77 
78  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
79  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
80  }
81 
82  $this->contract->fetchObjectLinked();
83  return $this->_cleanObjectDatas($this->contract);
84  }
85 
86 
87 
104  public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '')
105  {
106  global $db, $conf;
107 
108  if (!DolibarrApiAccess::$user->rights->contrat->lire) {
109  throw new RestException(401);
110  }
111 
112  $obj_ret = array();
113 
114  // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
115  $socids = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $thirdparty_ids;
116 
117  // If the internal user must only see his customers, force searching by him
118  $search_sale = 0;
119  if (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) {
120  $search_sale = DolibarrApiAccess::$user->id;
121  }
122 
123  $sql = "SELECT t.rowid";
124  if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) {
125  $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
126  }
127  $sql .= " FROM ".MAIN_DB_PREFIX."contrat AS t LEFT JOIN ".MAIN_DB_PREFIX."contrat_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
128 
129  if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) {
130  $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale
131  }
132 
133  $sql .= ' WHERE t.entity IN ('.getEntity('contrat').')';
134  if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) {
135  $sql .= " AND t.fk_soc = sc.fk_soc";
136  }
137  if ($socids) {
138  $sql .= " AND t.fk_soc IN (".$this->db->sanitize($socids).")";
139  }
140  if ($search_sale > 0) {
141  $sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
142  }
143  // Insert sale filter
144  if ($search_sale > 0) {
145  $sql .= " AND sc.fk_user = ".((int) $search_sale);
146  }
147  // Add sql filters
148  if ($sqlfilters) {
149  $errormessage = '';
150  $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
151  if ($errormessage) {
152  throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
153  }
154  }
155 
156  $sql .= $this->db->order($sortfield, $sortorder);
157  if ($limit) {
158  if ($page < 0) {
159  $page = 0;
160  }
161  $offset = $limit * $page;
162 
163  $sql .= $this->db->plimit($limit + 1, $offset);
164  }
165 
166  dol_syslog("API Rest request");
167  $result = $this->db->query($sql);
168 
169  if ($result) {
170  $num = $this->db->num_rows($result);
171  $min = min($num, ($limit <= 0 ? $num : $limit));
172  $i = 0;
173  while ($i < $min) {
174  $obj = $this->db->fetch_object($result);
175  $contrat_static = new Contrat($this->db);
176  if ($contrat_static->fetch($obj->rowid)) {
177  $obj_ret[] = $this->_cleanObjectDatas($contrat_static);
178  }
179  $i++;
180  }
181  } else {
182  throw new RestException(503, 'Error when retrieve contrat list : '.$this->db->lasterror());
183  }
184  if (!count($obj_ret)) {
185  throw new RestException(404, 'No contract found');
186  }
187  return $obj_ret;
188  }
189 
196  public function post($request_data = null)
197  {
198  if (!DolibarrApiAccess::$user->rights->contrat->creer) {
199  throw new RestException(401, "Insufficient rights");
200  }
201  // Check mandatory fields
202  $result = $this->_validate($request_data);
203 
204  foreach ($request_data as $field => $value) {
205  $this->contract->$field = $value;
206  }
207  /*if (isset($request_data["lines"])) {
208  $lines = array();
209  foreach ($request_data["lines"] as $line) {
210  array_push($lines, (object) $line);
211  }
212  $this->contract->lines = $lines;
213  }*/
214  if ($this->contract->create(DolibarrApiAccess::$user) < 0) {
215  throw new RestException(500, "Error creating contract", array_merge(array($this->contract->error), $this->contract->errors));
216  }
217 
218  return $this->contract->id;
219  }
220 
230  public function getLines($id)
231  {
232  if (!DolibarrApiAccess::$user->rights->contrat->lire) {
233  throw new RestException(401);
234  }
235 
236  $result = $this->contract->fetch($id);
237  if (!$result) {
238  throw new RestException(404, 'Contract not found');
239  }
240 
241  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
242  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
243  }
244  $this->contract->getLinesArray();
245  $result = array();
246  foreach ($this->contract->lines as $line) {
247  array_push($result, $this->_cleanObjectDatas($line));
248  }
249  return $result;
250  }
251 
262  public function postLine($id, $request_data = null)
263  {
264  if (!DolibarrApiAccess::$user->rights->contrat->creer) {
265  throw new RestException(401);
266  }
267 
268  $result = $this->contract->fetch($id);
269  if (!$result) {
270  throw new RestException(404, 'Contract not found');
271  }
272 
273  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
274  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
275  }
276 
277  $request_data = (object) $request_data;
278 
279  $request_data->desc = sanitizeVal($request_data->desc, 'restricthtml');
280  $request_data->price_base_type = sanitizeVal($request_data->price_base_type);
281 
282  $updateRes = $this->contract->addline(
283  $request_data->desc,
284  $request_data->subprice,
285  $request_data->qty,
286  $request_data->tva_tx,
287  $request_data->localtax1_tx,
288  $request_data->localtax2_tx,
289  $request_data->fk_product,
290  $request_data->remise_percent,
291  $request_data->date_start,
292  $request_data->date_end,
293  $request_data->price_base_type ? $request_data->price_base_type : 'HT',
294  $request_data->subprice_excl_tax,
295  $request_data->info_bits,
296  $request_data->fk_fournprice,
297  $request_data->pa_ht,
298  $request_data->array_options,
299  $request_data->fk_unit,
300  $request_data->rang
301  );
302 
303  if ($updateRes > 0) {
304  return $updateRes;
305  }
306  return false;
307  }
308 
320  public function putLine($id, $lineid, $request_data = null)
321  {
322  if (!DolibarrApiAccess::$user->rights->contrat->creer) {
323  throw new RestException(401);
324  }
325 
326  $result = $this->contract->fetch($id);
327  if (!$result) {
328  throw new RestException(404, 'Contrat not found');
329  }
330 
331  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
332  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
333  }
334 
335  $request_data = (object) $request_data;
336 
337  $request_data->desc = sanitizeVal($request_data->desc, 'restricthtml');
338  $request_data->price_base_type = sanitizeVal($request_data->price_base_type);
339 
340  $updateRes = $this->contract->updateline(
341  $lineid,
342  $request_data->desc,
343  $request_data->subprice,
344  $request_data->qty,
345  $request_data->remise_percent,
346  $request_data->date_start,
347  $request_data->date_end,
348  $request_data->tva_tx,
349  $request_data->localtax1_tx,
350  $request_data->localtax2_tx,
351  $request_data->date_start_real,
352  $request_data->date_end_real,
353  $request_data->price_base_type ? $request_data->price_base_type : 'HT',
354  $request_data->info_bits,
355  $request_data->fk_fourn_price,
356  $request_data->pa_ht,
357  $request_data->array_options,
358  $request_data->fk_unit
359  );
360 
361  if ($updateRes > 0) {
362  $result = $this->get($id);
363  unset($result->line);
364  return $this->_cleanObjectDatas($result);
365  }
366 
367  return false;
368  }
369 
383  public function activateLine($id, $lineid, $datestart, $dateend = null, $comment = null)
384  {
385  if (!DolibarrApiAccess::$user->rights->contrat->creer) {
386  throw new RestException(401);
387  }
388 
389  $result = $this->contract->fetch($id);
390  if (!$result) {
391  throw new RestException(404, 'Contrat not found');
392  }
393 
394  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
395  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
396  }
397 
398  $updateRes = $this->contract->active_line(DolibarrApiAccess::$user, $lineid, $datestart, $dateend, $comment);
399 
400  if ($updateRes > 0) {
401  $result = $this->get($id);
402  unset($result->line);
403  return $this->_cleanObjectDatas($result);
404  }
405 
406  return false;
407  }
408 
421  public function unactivateLine($id, $lineid, $datestart, $comment = null)
422  {
423  if (!DolibarrApiAccess::$user->rights->contrat->creer) {
424  throw new RestException(401);
425  }
426 
427  $result = $this->contract->fetch($id);
428  if (!$result) {
429  throw new RestException(404, 'Contrat not found');
430  }
431 
432  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
433  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
434  }
435 
436  $updateRes = $this->contract->close_line(DolibarrApiAccess::$user, $lineid, $datestart, $comment);
437 
438  if ($updateRes > 0) {
439  $result = $this->get($id);
440  unset($result->line);
441  return $this->_cleanObjectDatas($result);
442  }
443 
444  return false;
445  }
446 
461  public function deleteLine($id, $lineid)
462  {
463  if (!DolibarrApiAccess::$user->rights->contrat->creer) {
464  throw new RestException(401);
465  }
466 
467  $result = $this->contract->fetch($id);
468  if (!$result) {
469  throw new RestException(404, 'Contrat not found');
470  }
471 
472  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
473  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
474  }
475 
476  // TODO Check the lineid $lineid is a line of object
477 
478  $updateRes = $this->contract->deleteline($lineid, DolibarrApiAccess::$user);
479  if ($updateRes > 0) {
480  return $this->get($id);
481  } else {
482  throw new RestException(405, $this->contract->error);
483  }
484  }
485 
494  public function put($id, $request_data = null)
495  {
496  if (!DolibarrApiAccess::$user->rights->contrat->creer) {
497  throw new RestException(401);
498  }
499 
500  $result = $this->contract->fetch($id);
501  if (!$result) {
502  throw new RestException(404, 'Contrat not found');
503  }
504 
505  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
506  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
507  }
508  foreach ($request_data as $field => $value) {
509  if ($field == 'id') {
510  continue;
511  }
512  $this->contract->$field = $value;
513  }
514 
515  if ($this->contract->update(DolibarrApiAccess::$user) > 0) {
516  return $this->get($id);
517  } else {
518  throw new RestException(500, $this->contract->error);
519  }
520  }
521 
529  public function delete($id)
530  {
531  if (!DolibarrApiAccess::$user->hasRight('contrat', 'supprimer')) {
532  throw new RestException(401);
533  }
534  $result = $this->contract->fetch($id);
535  if (!$result) {
536  throw new RestException(404, 'Contract not found');
537  }
538 
539  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
540  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
541  }
542 
543  if (!$this->contract->delete(DolibarrApiAccess::$user)) {
544  throw new RestException(500, 'Error when delete contract : '.$this->contract->error);
545  }
546 
547  return array(
548  'success' => array(
549  'code' => 200,
550  'message' => 'Contract deleted'
551  )
552  );
553  }
554 
571  public function validate($id, $notrigger = 0)
572  {
573  if (!DolibarrApiAccess::$user->rights->contrat->creer) {
574  throw new RestException(401);
575  }
576  $result = $this->contract->fetch($id);
577  if (!$result) {
578  throw new RestException(404, 'Contract not found');
579  }
580 
581  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
582  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
583  }
584 
585  $result = $this->contract->validate(DolibarrApiAccess::$user, '', $notrigger);
586  if ($result == 0) {
587  throw new RestException(304, 'Error nothing done. May be object is already validated');
588  }
589  if ($result < 0) {
590  throw new RestException(500, 'Error when validating Contract: '.$this->contract->error);
591  }
592 
593  return array(
594  'success' => array(
595  'code' => 200,
596  'message' => 'Contract validated (Ref='.$this->contract->ref.')'
597  )
598  );
599  }
600 
617  public function close($id, $notrigger = 0)
618  {
619  if (!DolibarrApiAccess::$user->rights->contrat->creer) {
620  throw new RestException(401);
621  }
622  $result = $this->contract->fetch($id);
623  if (!$result) {
624  throw new RestException(404, 'Contract not found');
625  }
626 
627  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
628  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
629  }
630 
631  $result = $this->contract->closeAll(DolibarrApiAccess::$user, $notrigger);
632  if ($result == 0) {
633  throw new RestException(304, 'Error nothing done. May be object is already close');
634  }
635  if ($result < 0) {
636  throw new RestException(500, 'Error when closing Contract: '.$this->contract->error);
637  }
638 
639  return array(
640  'success' => array(
641  'code' => 200,
642  'message' => 'Contract closed (Ref='.$this->contract->ref.'). All services were closed.'
643  )
644  );
645  }
646 
647 
648 
649  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
656  protected function _cleanObjectDatas($object)
657  {
658  // phpcs:enable
659  $object = parent::_cleanObjectDatas($object);
660 
661  unset($object->address);
662  unset($object->civility_id);
663 
664  return $object;
665  }
666 
674  private function _validate($data)
675  {
676  $contrat = array();
677  foreach (Contracts::$FIELDS as $field) {
678  if (!isset($data[$field])) {
679  throw new RestException(400, "$field field missing");
680  }
681  $contrat[$field] = $data[$field];
682  }
683  return $contrat;
684  }
685 }
getLines($id)
Get lines of a contract.
putLine($id, $lineid, $request_data=null)
Update a line to given contract.
_validate($data)
Validate fields before create or update object.
index($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0, $thirdparty_ids='', $sqlfilters='')
List contracts.
put($id, $request_data=null)
Update contract general fields (won't touch lines of contract)
deleteLine($id, $lineid)
Delete a line to given contract.
_cleanObjectDatas($object)
Clean sensible object datas.
activateLine($id, $lineid, $datestart, $dateend=null, $comment=null)
Activate a service line of a given contract.
validate($id, $notrigger=0)
Validate a contract.
post($request_data=null)
Create contract object.
unactivateLine($id, $lineid, $datestart, $comment=null)
Unactivate a service line of a given contract.
__construct()
Constructor.
close($id, $notrigger=0)
Close all services of a contract.
postLine($id, $request_data=null)
Add a line to given contract.
Class to manage contracts.
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
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
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
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.