dolibarr 20.0.0
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
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.
static _checkAccessToResource($resource, $resource_id=0, $dbtablename='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid')
Check access by user to a given resource.
_checkValForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
Definition api.class.php:82
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.