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 19use Luracast\Restler\RestException; 20 21require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; 22 23/** 24 * API class for orders 25 * 26 * @access protected 27 * @class DolibarrApiAccess {@requires user,external} 28 */ 29class Orders extends DolibarrApi 30{ 31 32 /** 33 * @var array $FIELDS Mandatory fields, checked when create and update object 34 */ 35 static $FIELDS = array( 36 'socid', 37 'date' 38 ); 39 40 /** 41 * @var Commande $commande {@type Commande} 42 */ 43 public $commande; 44 45 /** 46 * Constructor 47 */ 48 public function __construct() 49 { 50 global $db, $conf; 51 $this->db = $db; 52 $this->commande = new Commande($this->db); 53 } 54 55 /** 56 * Get properties of an order object by id 57 * 58 * Return an array with order informations 59 * 60 * @param int $id ID of order 61 * @param int $contact_list 0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id 62 * @return array|mixed data without useless information 63 * 64 * @throws RestException 65 */ 66 public function get($id, $contact_list = 1) 67 { 68 return $this->_fetch($id, '', '', $contact_list); 69 } 70 71 /** 72 * Get properties of an order object by ref 73 * 74 * Return an array with order informations 75 * 76 * @param string $ref Ref of object 77 * @param int $contact_list 0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id 78 * @return array|mixed data without useless information 79 * 80 * @url GET ref/{ref} 81 * 82 * @throws RestException 83 */ 84 public function getByRef($ref, $contact_list = 1) 85 { 86 return $this->_fetch('', $ref, '', $contact_list); 87 } 88 89 /** 90 * Get properties of an order object by ref_ext 91 * 92 * Return an array with order informations 93 * 94 * @param string $ref_ext External reference of object 95 * @param int $contact_list 0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id 96 * @return array|mixed data without useless information 97 * 98 * @url GET ref_ext/{ref_ext} 99 * 100 * @throws RestException 101 */ 102 public function getByRefExt($ref_ext, $contact_list = 1) 103 { 104 return $this->_fetch('', '', $ref_ext, $contact_list); 105 } 106 107 /** 108 * Get properties of an order object 109 * 110 * Return an array with order informations 111 * 112 * @param int $id ID of order 113 * @param string $ref Ref of object 114 * @param string $ref_ext External reference of object 115 * @param int $contact_list 0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id 116 * @return array|mixed data without useless information 117 * 118 * @throws RestException 119 */ 120 private function _fetch($id, $ref = '', $ref_ext = '', $contact_list = 1) 121 { 122 if (!DolibarrApiAccess::$user->rights->commande->lire) { 123 throw new RestException(401); 124 } 125 126 $result = $this->commande->fetch($id, $ref, $ref_ext); 127 if (!$result) { 128 throw new RestException(404, 'Order not found'); 129 } 130 131 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 132 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 133 } 134 135 // Add external contacts ids 136 $this->commande->contacts_ids = $this->commande->liste_contact(-1, 'external', $contact_list); 137 $this->commande->fetchObjectLinked(); 138 return $this->_cleanObjectDatas($this->commande); 139 } 140 141 /** 142 * List orders 143 * 144 * Get a list of orders 145 * 146 * @param string $sortfield Sort field 147 * @param string $sortorder Sort order 148 * @param int $limit Limit for list 149 * @param int $page Page number 150 * @param string $thirdparty_ids Thirdparty ids to filter orders of (example '1' or '1,2,3') {@pattern /^[0-9,]*$/i} 151 * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" 152 * @return array Array of order objects 153 * 154 * @throws RestException 404 Not found 155 * @throws RestException 503 Error 156 */ 157 public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '') 158 { 159 global $db, $conf; 160 161 if (!DolibarrApiAccess::$user->rights->commande->lire) { 162 throw new RestException(401); 163 } 164 165 $obj_ret = array(); 166 167 // case of external user, $thirdparty_ids param is ignored and replaced by user's socid 168 $socids = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $thirdparty_ids; 169 170 // If the internal user must only see his customers, force searching by him 171 $search_sale = 0; 172 if (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) { 173 $search_sale = DolibarrApiAccess::$user->id; 174 } 175 176 $sql = "SELECT t.rowid"; 177 if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { 178 $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) 179 } 180 $sql .= " FROM ".MAIN_DB_PREFIX."commande as t"; 181 182 if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { 183 $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale 184 } 185 186 $sql .= ' WHERE t.entity IN ('.getEntity('commande').')'; 187 if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { 188 $sql .= " AND t.fk_soc = sc.fk_soc"; 189 } 190 if ($socids) { 191 $sql .= " AND t.fk_soc IN (".$this->db->sanitize($socids).")"; 192 } 193 if ($search_sale > 0) { 194 $sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale 195 } 196 // Insert sale filter 197 if ($search_sale > 0) { 198 $sql .= " AND sc.fk_user = ".((int) $search_sale); 199 } 200 // Add sql filters 201 if ($sqlfilters) { 202 if (!DolibarrApi::_checkFilters($sqlfilters)) { 203 throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); 204 } 205 $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; 206 $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; 207 } 208 209 $sql .= $this->db->order($sortfield, $sortorder); 210 if ($limit) { 211 if ($page < 0) { 212 $page = 0; 213 } 214 $offset = $limit * $page; 215 216 $sql .= $this->db->plimit($limit + 1, $offset); 217 } 218 219 dol_syslog("API Rest request"); 220 $result = $this->db->query($sql); 221 222 if ($result) { 223 $num = $this->db->num_rows($result); 224 $min = min($num, ($limit <= 0 ? $num : $limit)); 225 $i = 0; 226 while ($i < $min) { 227 $obj = $this->db->fetch_object($result); 228 $commande_static = new Commande($this->db); 229 if ($commande_static->fetch($obj->rowid)) { 230 // Add external contacts ids 231 $commande_static->contacts_ids = $commande_static->liste_contact(-1, 'external', 1); 232 $obj_ret[] = $this->_cleanObjectDatas($commande_static); 233 } 234 $i++; 235 } 236 } else { 237 throw new RestException(503, 'Error when retrieve commande list : '.$this->db->lasterror()); 238 } 239 if (!count($obj_ret)) { 240 throw new RestException(404, 'No order found'); 241 } 242 return $obj_ret; 243 } 244 245 /** 246 * Create a sale order 247 * 248 * Exemple: { "socid": 2, "date": 1595196000, "type": 0, "lines": [{ "fk_product": 2, "qty": 1 }] } 249 * 250 * @param array $request_data Request data 251 * @return int ID of order 252 */ 253 public function post($request_data = null) 254 { 255 if (!DolibarrApiAccess::$user->rights->commande->creer) { 256 throw new RestException(401, "Insuffisant rights"); 257 } 258 // Check mandatory fields 259 $result = $this->_validate($request_data); 260 261 foreach ($request_data as $field => $value) { 262 $this->commande->$field = $value; 263 } 264 /*if (isset($request_data["lines"])) { 265 $lines = array(); 266 foreach ($request_data["lines"] as $line) { 267 array_push($lines, (object) $line); 268 } 269 $this->commande->lines = $lines; 270 }*/ 271 272 if ($this->commande->create(DolibarrApiAccess::$user) < 0) { 273 throw new RestException(500, "Error creating order", array_merge(array($this->commande->error), $this->commande->errors)); 274 } 275 276 return $this->commande->id; 277 } 278 279 /** 280 * Get lines of an order 281 * 282 * @param int $id Id of order 283 * 284 * @url GET {id}/lines 285 * 286 * @return int 287 */ 288 public function getLines($id) 289 { 290 if (!DolibarrApiAccess::$user->rights->commande->lire) { 291 throw new RestException(401); 292 } 293 294 $result = $this->commande->fetch($id); 295 if (!$result) { 296 throw new RestException(404, 'Order not found'); 297 } 298 299 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 300 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 301 } 302 $this->commande->getLinesArray(); 303 $result = array(); 304 foreach ($this->commande->lines as $line) { 305 array_push($result, $this->_cleanObjectDatas($line)); 306 } 307 return $result; 308 } 309 310 /** 311 * Add a line to given order 312 * 313 * @param int $id Id of order to update 314 * @param array $request_data OrderLine data 315 * 316 * @url POST {id}/lines 317 * 318 * @return int 319 */ 320 public function postLine($id, $request_data = null) 321 { 322 if (!DolibarrApiAccess::$user->rights->commande->creer) { 323 throw new RestException(401); 324 } 325 326 $result = $this->commande->fetch($id); 327 if (!$result) { 328 throw new RestException(404, 'Order not found'); 329 } 330 331 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->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 = checkVal($request_data->desc, 'restricthtml'); 338 $request_data->label = checkVal($request_data->label); 339 340 $updateRes = $this->commande->addline( 341 $request_data->desc, 342 $request_data->subprice, 343 $request_data->qty, 344 $request_data->tva_tx, 345 $request_data->localtax1_tx, 346 $request_data->localtax2_tx, 347 $request_data->fk_product, 348 $request_data->remise_percent, 349 $request_data->info_bits, 350 $request_data->fk_remise_except, 351 $request_data->price_base_type ? $request_data->price_base_type : 'HT', 352 $request_data->subprice, 353 $request_data->date_start, 354 $request_data->date_end, 355 $request_data->product_type, 356 $request_data->rang, 357 $request_data->special_code, 358 $request_data->fk_parent_line, 359 $request_data->fk_fournprice, 360 $request_data->pa_ht, 361 $request_data->label, 362 $request_data->array_options, 363 $request_data->fk_unit, 364 $request_data->origin, 365 $request_data->origin_id, 366 $request_data->multicurrency_subprice, 367 $request_data->ref_ext 368 ); 369 370 if ($updateRes > 0) { 371 return $updateRes; 372 } else { 373 throw new RestException(400, $this->commande->error); 374 } 375 } 376 377 /** 378 * Update a line to given order 379 * 380 * @param int $id Id of order to update 381 * @param int $lineid Id of line to update 382 * @param array $request_data OrderLine data 383 * 384 * @url PUT {id}/lines/{lineid} 385 * 386 * @return array|bool 387 */ 388 public function putLine($id, $lineid, $request_data = null) 389 { 390 if (!DolibarrApiAccess::$user->rights->commande->creer) { 391 throw new RestException(401); 392 } 393 394 $result = $this->commande->fetch($id); 395 if (!$result) { 396 throw new RestException(404, 'Order not found'); 397 } 398 399 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 400 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 401 } 402 403 $request_data = (object) $request_data; 404 405 $request_data->desc = checkVal($request_data->desc, 'restricthtml'); 406 $request_data->label = checkVal($request_data->label); 407 408 $updateRes = $this->commande->updateline( 409 $lineid, 410 $request_data->desc, 411 $request_data->subprice, 412 $request_data->qty, 413 $request_data->remise_percent, 414 $request_data->tva_tx, 415 $request_data->localtax1_tx, 416 $request_data->localtax2_tx, 417 $request_data->price_base_type ? $request_data->price_base_type : 'HT', 418 $request_data->info_bits, 419 $request_data->date_start, 420 $request_data->date_end, 421 $request_data->product_type, 422 $request_data->fk_parent_line, 423 0, 424 $request_data->fk_fournprice, 425 $request_data->pa_ht, 426 $request_data->label, 427 $request_data->special_code, 428 $request_data->array_options, 429 $request_data->fk_unit, 430 $request_data->multicurrency_subprice, 431 0, 432 $request_data->ref_ext 433 ); 434 435 if ($updateRes > 0) { 436 $result = $this->get($id); 437 unset($result->line); 438 return $this->_cleanObjectDatas($result); 439 } 440 return false; 441 } 442 443 /** 444 * Delete a line to given order 445 * 446 * 447 * @param int $id Id of order to update 448 * @param int $lineid Id of line to delete 449 * 450 * @url DELETE {id}/lines/{lineid} 451 * 452 * @return int 453 * 454 * @throws RestException 401 455 * @throws RestException 404 456 */ 457 public function deleteLine($id, $lineid) 458 { 459 if (!DolibarrApiAccess::$user->rights->commande->creer) { 460 throw new RestException(401); 461 } 462 463 $result = $this->commande->fetch($id); 464 if (!$result) { 465 throw new RestException(404, 'Order not found'); 466 } 467 468 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 469 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 470 } 471 472 // TODO Check the lineid $lineid is a line of ojbect 473 474 $updateRes = $this->commande->deleteline(DolibarrApiAccess::$user, $lineid); 475 if ($updateRes > 0) { 476 return $this->get($id); 477 } else { 478 throw new RestException(405, $this->commande->error); 479 } 480 } 481 482 /** 483 * Get contacts of given order 484 * 485 * Return an array with contact informations 486 * 487 * @param int $id ID of order 488 * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER) 489 * 490 * @url GET {id}/contacts 491 * 492 * @return array data without useless information 493 * 494 * @throws RestException 495 */ 496 public function getContacts($id, $type = '') 497 { 498 if (!DolibarrApiAccess::$user->rights->commande->lire) { 499 throw new RestException(401); 500 } 501 502 $result = $this->commande->fetch($id); 503 if (!$result) { 504 throw new RestException(404, 'Order not found'); 505 } 506 507 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 508 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 509 } 510 511 $contacts = $this->commande->liste_contact(-1, 'external', 0, $type); 512 513 return $this->_cleanObjectDatas($contacts); 514 } 515 516 /** 517 * Add a contact type of given order 518 * 519 * @param int $id Id of order to update 520 * @param int $contactid Id of contact to add 521 * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER) 522 * 523 * @url POST {id}/contact/{contactid}/{type} 524 * 525 * @return int 526 * 527 * @throws RestException 401 528 * @throws RestException 404 529 */ 530 public function postContact($id, $contactid, $type) 531 { 532 if (!DolibarrApiAccess::$user->rights->commande->creer) { 533 throw new RestException(401); 534 } 535 536 $result = $this->commande->fetch($id); 537 if (!$result) { 538 throw new RestException(404, 'Order not found'); 539 } 540 541 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 542 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 543 } 544 545 $result = $this->commande->add_contact($contactid, $type, 'external'); 546 547 if ($result < 0) { 548 throw new RestException(500, 'Error when added the contact'); 549 } 550 551 if ($result == 0) { 552 throw new RestException(304, 'contact already added'); 553 } 554 555 return array( 556 'success' => array( 557 'code' => 200, 558 'message' => 'Contact linked to the order' 559 ) 560 ); 561 } 562 563 /** 564 * Unlink a contact type of given order 565 * 566 * @param int $id Id of order to update 567 * @param int $contactid Id of contact 568 * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER). 569 * 570 * @url DELETE {id}/contact/{contactid}/{type} 571 * 572 * @return int 573 * 574 * @throws RestException 401 575 * @throws RestException 404 576 * @throws RestException 500 577 */ 578 public function deleteContact($id, $contactid, $type) 579 { 580 if (!DolibarrApiAccess::$user->rights->commande->creer) { 581 throw new RestException(401); 582 } 583 584 $result = $this->commande->fetch($id); 585 if (!$result) { 586 throw new RestException(404, 'Order not found'); 587 } 588 589 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 590 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 591 } 592 593 $contacts = $this->commande->liste_contact(); 594 595 foreach ($contacts as $contact) { 596 if ($contact['id'] == $contactid && $contact['code'] == $type) { 597 $result = $this->commande->delete_contact($contact['rowid']); 598 599 if (!$result) { 600 throw new RestException(500, 'Error when deleted the contact'); 601 } 602 } 603 } 604 605 return array( 606 'success' => array( 607 'code' => 200, 608 'message' => 'Contact unlinked from order' 609 ) 610 ); 611 } 612 613 /** 614 * Update order general fields (won't touch lines of order) 615 * 616 * @param int $id Id of order to update 617 * @param array $request_data Datas 618 * 619 * @return int 620 */ 621 public function put($id, $request_data = null) 622 { 623 if (!DolibarrApiAccess::$user->rights->commande->creer) { 624 throw new RestException(401); 625 } 626 627 $result = $this->commande->fetch($id); 628 if (!$result) { 629 throw new RestException(404, 'Order not found'); 630 } 631 632 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 633 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 634 } 635 foreach ($request_data as $field => $value) { 636 if ($field == 'id') { 637 continue; 638 } 639 $this->commande->$field = $value; 640 } 641 642 // Update availability 643 if (!empty($this->commande->availability_id)) { 644 if ($this->commande->availability($this->commande->availability_id) < 0) { 645 throw new RestException(400, 'Error while updating availability'); 646 } 647 } 648 649 if ($this->commande->update(DolibarrApiAccess::$user) > 0) { 650 return $this->get($id); 651 } else { 652 throw new RestException(500, $this->commande->error); 653 } 654 } 655 656 /** 657 * Delete order 658 * 659 * @param int $id Order ID 660 * @return array 661 */ 662 public function delete($id) 663 { 664 if (!DolibarrApiAccess::$user->rights->commande->supprimer) { 665 throw new RestException(401); 666 } 667 $result = $this->commande->fetch($id); 668 if (!$result) { 669 throw new RestException(404, 'Order not found'); 670 } 671 672 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 673 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 674 } 675 676 if (!$this->commande->delete(DolibarrApiAccess::$user)) { 677 throw new RestException(500, 'Error when deleting order : '.$this->commande->error); 678 } 679 680 return array( 681 'success' => array( 682 'code' => 200, 683 'message' => 'Order deleted' 684 ) 685 ); 686 } 687 688 /** 689 * Validate an order 690 * 691 * If you get a bad value for param notrigger check, provide this in body 692 * { 693 * "idwarehouse": 0, 694 * "notrigger": 0 695 * } 696 * 697 * @param int $id Order ID 698 * @param int $idwarehouse Warehouse ID 699 * @param int $notrigger 1=Does not execute triggers, 0= execute triggers 700 * 701 * @url POST {id}/validate 702 * 703 * @throws RestException 304 704 * @throws RestException 401 705 * @throws RestException 404 706 * @throws RestException 500 707 * 708 * @return array 709 */ 710 public function validate($id, $idwarehouse = 0, $notrigger = 0) 711 { 712 if (!DolibarrApiAccess::$user->rights->commande->creer) { 713 throw new RestException(401); 714 } 715 $result = $this->commande->fetch($id); 716 if (!$result) { 717 throw new RestException(404, 'Order not found'); 718 } 719 720 $result = $this->commande->fetch_thirdparty(); // do not check result, as failure is not fatal (used only for mail notification substitutes) 721 722 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 723 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 724 } 725 726 $result = $this->commande->valid(DolibarrApiAccess::$user, $idwarehouse, $notrigger); 727 if ($result == 0) { 728 throw new RestException(304, 'Error nothing done. May be object is already validated'); 729 } 730 if ($result < 0) { 731 throw new RestException(500, 'Error when validating Order: '.$this->commande->error); 732 } 733 $result = $this->commande->fetch($id); 734 735 $this->commande->fetchObjectLinked(); 736 737 return $this->_cleanObjectDatas($this->commande); 738 } 739 740 /** 741 * Tag the order as validated (opened) 742 * 743 * Function used when order is reopend after being closed. 744 * 745 * @param int $id Id of the order 746 * 747 * @url POST {id}/reopen 748 * 749 * @return int 750 * 751 * @throws RestException 304 752 * @throws RestException 400 753 * @throws RestException 401 754 * @throws RestException 404 755 * @throws RestException 405 756 */ 757 public function reopen($id) 758 { 759 760 if (!DolibarrApiAccess::$user->rights->commande->creer) { 761 throw new RestException(401); 762 } 763 if (empty($id)) { 764 throw new RestException(400, 'Order ID is mandatory'); 765 } 766 $result = $this->commande->fetch($id); 767 if (!$result) { 768 throw new RestException(404, 'Order not found'); 769 } 770 771 $result = $this->commande->set_reopen(DolibarrApiAccess::$user); 772 if ($result < 0) { 773 throw new RestException(405, $this->commande->error); 774 } elseif ($result == 0) { 775 throw new RestException(304); 776 } 777 778 return $result; 779 } 780 781 /** 782 * Classify the order as invoiced. Could be also called setbilled 783 * 784 * @param int $id Id of the order 785 * 786 * @url POST {id}/setinvoiced 787 * 788 * @return int 789 * 790 * @throws RestException 400 791 * @throws RestException 401 792 * @throws RestException 404 793 * @throws RestException 405 794 */ 795 public function setinvoiced($id) 796 { 797 798 if (!DolibarrApiAccess::$user->rights->commande->creer) { 799 throw new RestException(401); 800 } 801 if (empty($id)) { 802 throw new RestException(400, 'Order ID is mandatory'); 803 } 804 $result = $this->commande->fetch($id); 805 if (!$result) { 806 throw new RestException(404, 'Order not found'); 807 } 808 809 $result = $this->commande->classifyBilled(DolibarrApiAccess::$user); 810 if ($result < 0) { 811 throw new RestException(400, $this->commande->error); 812 } 813 814 $result = $this->commande->fetch($id); 815 if (!$result) { 816 throw new RestException(404, 'Order not found'); 817 } 818 819 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 820 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 821 } 822 823 $this->commande->fetchObjectLinked(); 824 825 return $this->_cleanObjectDatas($this->commande); 826 } 827 828 /** 829 * Close an order (Classify it as "Delivered") 830 * 831 * @param int $id Order ID 832 * @param int $notrigger Disabled triggers 833 * 834 * @url POST {id}/close 835 * 836 * @return int 837 */ 838 public function close($id, $notrigger = 0) 839 { 840 if (!DolibarrApiAccess::$user->rights->commande->creer) { 841 throw new RestException(401); 842 } 843 $result = $this->commande->fetch($id); 844 if (!$result) { 845 throw new RestException(404, 'Order not found'); 846 } 847 848 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 849 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 850 } 851 852 $result = $this->commande->cloture(DolibarrApiAccess::$user, $notrigger); 853 if ($result == 0) { 854 throw new RestException(304, 'Error nothing done. May be object is already closed'); 855 } 856 if ($result < 0) { 857 throw new RestException(500, 'Error when closing Order: '.$this->commande->error); 858 } 859 860 $result = $this->commande->fetch($id); 861 if (!$result) { 862 throw new RestException(404, 'Order not found'); 863 } 864 865 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 866 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 867 } 868 869 $this->commande->fetchObjectLinked(); 870 871 return $this->_cleanObjectDatas($this->commande); 872 } 873 874 /** 875 * Set an order to draft 876 * 877 * @param int $id Order ID 878 * @param int $idwarehouse Warehouse ID to use for stock change (Used only if option STOCK_CALCULATE_ON_VALIDATE_ORDER is on) 879 * 880 * @url POST {id}/settodraft 881 * 882 * @return array 883 */ 884 public function settodraft($id, $idwarehouse = -1) 885 { 886 if (!DolibarrApiAccess::$user->rights->commande->creer) { 887 throw new RestException(401); 888 } 889 $result = $this->commande->fetch($id); 890 if (!$result) { 891 throw new RestException(404, 'Order not found'); 892 } 893 894 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 895 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 896 } 897 898 $result = $this->commande->setDraft(DolibarrApiAccess::$user, $idwarehouse); 899 if ($result == 0) { 900 throw new RestException(304, 'Nothing done. May be object is already closed'); 901 } 902 if ($result < 0) { 903 throw new RestException(500, 'Error when closing Order: '.$this->commande->error); 904 } 905 906 $result = $this->commande->fetch($id); 907 if (!$result) { 908 throw new RestException(404, 'Order not found'); 909 } 910 911 if (!DolibarrApi::_checkAccessToResource('commande', $this->commande->id)) { 912 throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); 913 } 914 915 $this->commande->fetchObjectLinked(); 916 917 return $this->_cleanObjectDatas($this->commande); 918 } 919 920 921 /** 922 * Create an order using an existing proposal. 923 * 924 * 925 * @param int $proposalid Id of the proposal 926 * 927 * @url POST /createfromproposal/{proposalid} 928 * 929 * @return int 930 * @throws RestException 400 931 * @throws RestException 401 932 * @throws RestException 404 933 * @throws RestException 405 934 */ 935 public function createOrderFromProposal($proposalid) 936 { 937 938 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; 939 940 if (!DolibarrApiAccess::$user->rights->propal->lire) { 941 throw new RestException(401); 942 } 943 if (!DolibarrApiAccess::$user->rights->commande->creer) { 944 throw new RestException(401); 945 } 946 if (empty($proposalid)) { 947 throw new RestException(400, 'Proposal ID is mandatory'); 948 } 949 950 $propal = new Propal($this->db); 951 $result = $propal->fetch($proposalid); 952 if (!$result) { 953 throw new RestException(404, 'Proposal not found'); 954 } 955 956 $result = $this->commande->createFromProposal($propal, DolibarrApiAccess::$user); 957 if ($result < 0) { 958 throw new RestException(405, $this->commande->error); 959 } 960 $this->commande->fetchObjectLinked(); 961 962 return $this->_cleanObjectDatas($this->commande); 963 } 964 965 966 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore 967 /** 968 * Clean sensible object datas 969 * 970 * @param Object $object Object to clean 971 * @return Object Object with cleaned properties 972 */ 973 protected function _cleanObjectDatas($object) 974 { 975 // phpcs:enable 976 $object = parent::_cleanObjectDatas($object); 977 978 unset($object->note); 979 unset($object->address); 980 unset($object->barcode_type); 981 unset($object->barcode_type_code); 982 unset($object->barcode_type_label); 983 unset($object->barcode_type_coder); 984 985 return $object; 986 } 987 988 /** 989 * Validate fields before create or update object 990 * 991 * @param array $data Array with data to verify 992 * @return array 993 * @throws RestException 994 */ 995 private function _validate($data) 996 { 997 $commande = array(); 998 foreach (Orders::$FIELDS as $field) { 999 if (!isset($data[$field])) { 1000 throw new RestException(400, $field." field missing"); 1001 } 1002 $commande[$field] = $data[$field]; 1003 } 1004 return $commande; 1005 } 1006} 1007