dolibarr  20.0.0-beta
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 {
35  public static $FIELDS = array(
36  'socid',
37  'date_contrat',
38  'commercial_signature_id',
39  'commercial_suivi_id'
40  );
41 
45  public $contract;
46 
50  public function __construct()
51  {
52  global $db, $conf;
53  $this->db = $db;
54  $this->contract = new Contrat($this->db);
55  }
56 
66  public function get($id)
67  {
68  if (!DolibarrApiAccess::$user->hasRight('contrat', 'lire')) {
69  throw new RestException(403);
70  }
71 
72  $result = $this->contract->fetch($id);
73  if (!$result) {
74  throw new RestException(404, 'Contract not found');
75  }
76 
77  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
78  throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
79  }
80 
81  $this->contract->fetchObjectLinked();
82  return $this->_cleanObjectDatas($this->contract);
83  }
84 
85 
86 
104  public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '', $properties = '')
105  {
106  global $db, $conf;
107 
108  if (!DolibarrApiAccess::$user->hasRight('contrat', 'lire')) {
109  throw new RestException(403);
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->hasRight('societe', 'client', 'voir') && !$socids) {
120  $search_sale = DolibarrApiAccess::$user->id;
121  }
122 
123  $sql = "SELECT t.rowid";
124  $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
125  $sql .= ' WHERE t.entity IN ('.getEntity('contrat').')';
126  if ($socids) {
127  $sql .= " AND t.fk_soc IN (".$this->db->sanitize($socids).")";
128  }
129  // Search on sale representative
130  if ($search_sale && $search_sale != '-1') {
131  if ($search_sale == -2) {
132  $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc)";
133  } elseif ($search_sale > 0) {
134  $sql .= " AND EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc AND sc.fk_user = ".((int) $search_sale).")";
135  }
136  }
137  // Add sql filters
138  if ($sqlfilters) {
139  $errormessage = '';
140  $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
141  if ($errormessage) {
142  throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
143  }
144  }
145 
146  $sql .= $this->db->order($sortfield, $sortorder);
147  if ($limit) {
148  if ($page < 0) {
149  $page = 0;
150  }
151  $offset = $limit * $page;
152 
153  $sql .= $this->db->plimit($limit + 1, $offset);
154  }
155 
156  dol_syslog("API Rest request");
157  $result = $this->db->query($sql);
158 
159  if ($result) {
160  $num = $this->db->num_rows($result);
161  $min = min($num, ($limit <= 0 ? $num : $limit));
162  $i = 0;
163  while ($i < $min) {
164  $obj = $this->db->fetch_object($result);
165  $contrat_static = new Contrat($this->db);
166  if ($contrat_static->fetch($obj->rowid)) {
167  $obj_ret[] = $this->_filterObjectProperties($this->_cleanObjectDatas($contrat_static), $properties);
168  }
169  $i++;
170  }
171  } else {
172  throw new RestException(503, 'Error when retrieve contrat list : '.$this->db->lasterror());
173  }
174 
175  return $obj_ret;
176  }
177 
184  public function post($request_data = null)
185  {
186  if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
187  throw new RestException(403, "Insufficient rights");
188  }
189  // Check mandatory fields
190  $result = $this->_validate($request_data);
191 
192  foreach ($request_data as $field => $value) {
193  if ($field === 'caller') {
194  // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller
195  $this->contract->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
196  continue;
197  }
198 
199  $this->contract->$field = $this->_checkValForAPI($field, $value, $this->contract);
200  }
201  /*if (isset($request_data["lines"])) {
202  $lines = array();
203  foreach ($request_data["lines"] as $line) {
204  array_push($lines, (object) $line);
205  }
206  $this->contract->lines = $lines;
207  }*/
208  if ($this->contract->create(DolibarrApiAccess::$user) < 0) {
209  throw new RestException(500, "Error creating contract", array_merge(array($this->contract->error), $this->contract->errors));
210  }
211 
212  return $this->contract->id;
213  }
214 
224  public function getLines($id)
225  {
226  if (!DolibarrApiAccess::$user->hasRight('contrat', 'lire')) {
227  throw new RestException(403);
228  }
229 
230  $result = $this->contract->fetch($id);
231  if (!$result) {
232  throw new RestException(404, 'Contract not found');
233  }
234 
235  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
236  throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
237  }
238  $this->contract->getLinesArray();
239  $result = array();
240  foreach ($this->contract->lines as $line) {
241  array_push($result, $this->_cleanObjectDatas($line));
242  }
243  return $result;
244  }
245 
256  public function postLine($id, $request_data = null)
257  {
258  if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
259  throw new RestException(403);
260  }
261 
262  $result = $this->contract->fetch($id);
263  if (!$result) {
264  throw new RestException(404, 'Contract not found');
265  }
266 
267  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
268  throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
269  }
270 
271  $request_data = (object) $request_data;
272 
273  $request_data->desc = sanitizeVal($request_data->desc, 'restricthtml');
274  $request_data->price_base_type = sanitizeVal($request_data->price_base_type);
275 
276  $updateRes = $this->contract->addline(
277  $request_data->desc,
278  $request_data->subprice,
279  $request_data->qty,
280  $request_data->tva_tx,
281  $request_data->localtax1_tx,
282  $request_data->localtax2_tx,
283  $request_data->fk_product,
284  $request_data->remise_percent,
285  $request_data->date_start,
286  $request_data->date_end,
287  $request_data->price_base_type ? $request_data->price_base_type : 'HT',
288  $request_data->subprice_excl_tax,
289  $request_data->info_bits,
290  $request_data->fk_fournprice,
291  $request_data->pa_ht,
292  $request_data->array_options,
293  $request_data->fk_unit,
294  $request_data->rang
295  );
296 
297  if ($updateRes > 0) {
298  return $updateRes;
299  }
300  return false;
301  }
302 
314  public function putLine($id, $lineid, $request_data = null)
315  {
316  if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
317  throw new RestException(403);
318  }
319 
320  $result = $this->contract->fetch($id);
321  if (!$result) {
322  throw new RestException(404, 'Contrat not found');
323  }
324 
325  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
326  throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
327  }
328 
329  $request_data = (object) $request_data;
330 
331  $request_data->desc = sanitizeVal($request_data->desc, 'restricthtml');
332  $request_data->price_base_type = sanitizeVal($request_data->price_base_type);
333 
334  $updateRes = $this->contract->updateline(
335  $lineid,
336  $request_data->desc,
337  $request_data->subprice,
338  $request_data->qty,
339  $request_data->remise_percent,
340  $request_data->date_start,
341  $request_data->date_end,
342  $request_data->tva_tx,
343  $request_data->localtax1_tx,
344  $request_data->localtax2_tx,
345  $request_data->date_start_real,
346  $request_data->date_end_real,
347  $request_data->price_base_type ? $request_data->price_base_type : 'HT',
348  $request_data->info_bits,
349  $request_data->fk_fourn_price,
350  $request_data->pa_ht,
351  $request_data->array_options,
352  $request_data->fk_unit
353  );
354 
355  if ($updateRes > 0) {
356  $result = $this->get($id);
357  unset($result->line);
358  return $this->_cleanObjectDatas($result);
359  }
360 
361  return false;
362  }
363 
377  public function activateLine($id, $lineid, $datestart, $dateend = null, $comment = null)
378  {
379  if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
380  throw new RestException(403);
381  }
382 
383  $result = $this->contract->fetch($id);
384  if (!$result) {
385  throw new RestException(404, 'Contrat not found');
386  }
387 
388  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
389  throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
390  }
391 
392  $updateRes = $this->contract->active_line(DolibarrApiAccess::$user, $lineid, $datestart, $dateend, $comment);
393 
394  if ($updateRes > 0) {
395  $result = $this->get($id);
396  unset($result->line);
397  return $this->_cleanObjectDatas($result);
398  }
399 
400  return false;
401  }
402 
415  public function unactivateLine($id, $lineid, $datestart, $comment = null)
416  {
417  if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
418  throw new RestException(403);
419  }
420 
421  $result = $this->contract->fetch($id);
422  if (!$result) {
423  throw new RestException(404, 'Contrat not found');
424  }
425 
426  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
427  throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
428  }
429 
430  $updateRes = $this->contract->close_line(DolibarrApiAccess::$user, $lineid, $datestart, $comment);
431 
432  if ($updateRes > 0) {
433  $result = $this->get($id);
434  unset($result->line);
435  return $this->_cleanObjectDatas($result);
436  }
437 
438  return false;
439  }
440 
455  public function deleteLine($id, $lineid)
456  {
457  if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
458  throw new RestException(403);
459  }
460 
461  $result = $this->contract->fetch($id);
462  if (!$result) {
463  throw new RestException(404, 'Contrat not found');
464  }
465 
466  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
467  throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
468  }
469 
470  // TODO Check the lineid $lineid is a line of object
471 
472  $updateRes = $this->contract->deleteLine($lineid, DolibarrApiAccess::$user);
473  if ($updateRes > 0) {
474  return $this->get($id);
475  } else {
476  throw new RestException(405, $this->contract->error);
477  }
478  }
479 
487  public function put($id, $request_data = null)
488  {
489  if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
490  throw new RestException(403);
491  }
492 
493  $result = $this->contract->fetch($id);
494  if (!$result) {
495  throw new RestException(404, 'Contrat not found');
496  }
497 
498  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
499  throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
500  }
501  foreach ($request_data as $field => $value) {
502  if ($field == 'id') {
503  continue;
504  }
505  if ($field === 'caller') {
506  // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller
507  $this->contract->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
508  continue;
509  }
510  if ($field == 'array_options' && is_array($value)) {
511  foreach ($value as $index => $val) {
512  $this->contract->array_options[$index] = $this->_checkValForAPI($field, $val, $this->contract);;
513  }
514  continue;
515  }
516 
517  $this->contract->$field = $this->_checkValForAPI($field, $value, $this->contract);
518  }
519 
520  if ($this->contract->update(DolibarrApiAccess::$user) > 0) {
521  return $this->get($id);
522  } else {
523  throw new RestException(500, $this->contract->error);
524  }
525  }
526 
534  public function delete($id)
535  {
536  if (!DolibarrApiAccess::$user->hasRight('contrat', 'supprimer')) {
537  throw new RestException(403);
538  }
539  $result = $this->contract->fetch($id);
540  if (!$result) {
541  throw new RestException(404, 'Contract not found');
542  }
543 
544  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
545  throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
546  }
547 
548  if (!$this->contract->delete(DolibarrApiAccess::$user)) {
549  throw new RestException(500, 'Error when delete contract : '.$this->contract->error);
550  }
551 
552  return array(
553  'success' => array(
554  'code' => 200,
555  'message' => 'Contract deleted'
556  )
557  );
558  }
559 
576  public function validate($id, $notrigger = 0)
577  {
578  if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
579  throw new RestException(403);
580  }
581  $result = $this->contract->fetch($id);
582  if (!$result) {
583  throw new RestException(404, 'Contract not found');
584  }
585 
586  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
587  throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
588  }
589 
590  $result = $this->contract->validate(DolibarrApiAccess::$user, '', $notrigger);
591  if ($result == 0) {
592  throw new RestException(304, 'Error nothing done. May be object is already validated');
593  }
594  if ($result < 0) {
595  throw new RestException(500, 'Error when validating Contract: '.$this->contract->error);
596  }
597 
598  return array(
599  'success' => array(
600  'code' => 200,
601  'message' => 'Contract validated (Ref='.$this->contract->ref.')'
602  )
603  );
604  }
605 
622  public function close($id, $notrigger = 0)
623  {
624  if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
625  throw new RestException(403);
626  }
627  $result = $this->contract->fetch($id);
628  if (!$result) {
629  throw new RestException(404, 'Contract not found');
630  }
631 
632  if (!DolibarrApi::_checkAccessToResource('contrat', $this->contract->id)) {
633  throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
634  }
635 
636  $result = $this->contract->closeAll(DolibarrApiAccess::$user, $notrigger);
637  if ($result == 0) {
638  throw new RestException(304, 'Error nothing done. May be object is already close');
639  }
640  if ($result < 0) {
641  throw new RestException(500, 'Error when closing Contract: '.$this->contract->error);
642  }
643 
644  return array(
645  'success' => array(
646  'code' => 200,
647  'message' => 'Contract closed (Ref='.$this->contract->ref.'). All services were closed.'
648  )
649  );
650  }
651 
652 
653 
654  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
661  protected function _cleanObjectDatas($object)
662  {
663  // phpcs:enable
664  $object = parent::_cleanObjectDatas($object);
665 
666  unset($object->address);
667  unset($object->civility_id);
668 
669  return $object;
670  }
671 
679  private function _validate($data)
680  {
681  $contrat = array();
682  foreach (Contracts::$FIELDS as $field) {
683  if (!isset($data[$field])) {
684  throw new RestException(400, "$field field missing");
685  }
686  $contrat[$field] = $data[$field];
687  }
688  return $contrat;
689  }
690 }
if($user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition: card.php:58
index($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0, $thirdparty_ids='', $sqlfilters='', $properties='')
List contracts.
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.
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:30
_filterObjectProperties($object, $properties)
Filter properties that will be returned on object.
Definition: api.class.php:136
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:369
_checkValForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
Definition: api.class.php:82
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('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') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:745
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.