dolibarr 25.0.0-alpha
api_shipments.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) 2025 MDW <mdeweerd@users.noreply.github.com>
5 * Copyright (C) 2025 Charlene Benke <charlene@patas-monkey.com>
6 * Copyright (C) 2025 Frédéric France <frederic.france@free.fr>
7 * Copyright (C) 2025 Nick Fragoulis
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
23use Luracast\Restler\RestException;
24
25require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
26require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
27
35{
39 public static $FIELDS = array(
40 'socid',
41 'origin_id',
42 'origin_type',
43 );
44
48 public $shipment;
49
53 public function __construct()
54 {
55 global $db;
56 $this->db = $db;
57 $this->shipment = new Expedition($this->db);
58 }
59
70 public function get($id)
71 {
72 if (!DolibarrApiAccess::$user->hasRight('expedition', 'lire')) {
73 throw new RestException(403);
74 }
75
76 $result = $this->shipment->fetch($id);
77 if (!$result) {
78 throw new RestException(404, 'Shipment not found');
79 }
80
81 if (!DolibarrApi::_checkAccessToResource('expedition', $this->shipment->id)) {
82 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
83 }
84
85 $this->shipment->fetchObjectLinked();
86 return $this->_cleanObjectDatas($this->shipment);
87 }
88
89
90
110 public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '', $properties = '', $pagination_data = false)
111 {
112 if (!DolibarrApiAccess::$user->hasRight('expedition', 'lire')) {
113 throw new RestException(403);
114 }
115
116 global $hookmanager;
117
118 $obj_ret = array();
119
120 // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
121 $socids = DolibarrApiAccess::$user->socid ?: $thirdparty_ids;
122
123 // If the internal user must only see his customers, force searching by him
124 $search_sale = 0;
125 if (!DolibarrApiAccess::$user->hasRight('societe', 'client', 'voir') && !$socids) {
126 $search_sale = DolibarrApiAccess::$user->id;
127 }
128
129 $sql = "SELECT t.rowid";
130 $sql .= " FROM ".MAIN_DB_PREFIX."expedition AS t";
131 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe AS s ON (s.rowid = t.fk_soc)";
132 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."expedition_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
133 $sql .= ' WHERE t.entity IN ('.getEntity('expedition').')';
134 if ($socids) {
135 $sql .= " AND t.fk_soc IN (".$this->db->sanitize($socids).")";
136 }
137 // Search on sale representative
138 if ($search_sale && $search_sale != '-1') {
139 if ($search_sale == -2) {
140 $sql .= " AND ".getSalesRepresentativeSqlFilter('t.fk_soc', 0, 1);
141 } elseif ($search_sale > 0) {
142 $sql .= " AND ".getSalesRepresentativeSqlFilter('t.fk_soc', (int) $search_sale);
143 }
144 }
145 // Add sql filters
146 if ($sqlfilters) {
147 $parameters = array('sqlfilters' => $sqlfilters, 'apiroute' => 'shipments', 'apimethod' => 'index');
148 $object = new stdClass();
149 $action = 'list';
150 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
151 if ($reshook > 0) {
152 $sql = $hookmanager->resPrint;
153 } elseif ($reshook == 0) {
154 $sql .= $hookmanager->resPrint;
155 }
156 $errormessage = '';
157 $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
158 if ($errormessage) {
159 throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
160 }
161 }
162
163 //this query will return total shipments with the filters given
164 $sqlTotals = str_replace('SELECT t.rowid', 'SELECT count(t.rowid) as total', $sql);
165
166 $sql .= $this->db->order($sortfield, $sortorder);
167 if ($limit) {
168 if ($page < 0) {
169 $page = 0;
170 }
171 $offset = $limit * $page;
172
173 $sql .= $this->db->plimit($limit + 1, $offset);
174 }
175
176 dol_syslog("API Rest request");
177 $result = $this->db->query($sql);
178
179 if ($result) {
180 $num = $this->db->num_rows($result);
181 $min = min($num, ($limit <= 0 ? $num : $limit));
182 $i = 0;
183 while ($i < $min) {
184 $obj = $this->db->fetch_object($result);
185 $shipment_static = new Expedition($this->db);
186 if ($shipment_static->fetch($obj->rowid)) {
187 $obj_ret[] = $this->_filterObjectProperties($this->_cleanObjectDatas($shipment_static), $properties);
188 }
189 $i++;
190 }
191 } else {
192 throw new RestException(503, 'Error when retrieve commande list : '.$this->db->lasterror());
193 }
194
195 //if $pagination_data is true the response will contain element data with all values and element pagination with pagination data(total,page,limit)
196 if ($pagination_data) {
197 $totalsResult = $this->db->query($sqlTotals);
198 $total = $this->db->fetch_object($totalsResult)->total;
199
200 $tmp = $obj_ret;
201 $obj_ret = [];
202
203 $obj_ret['data'] = $tmp;
204 $obj_ret['pagination'] = [
205 'total' => (int) $total,
206 'page' => $page, //count starts from 0
207 'page_count' => ceil((int) $total / $limit),
208 'limit' => $limit
209 ];
210 }
211
212 return $obj_ret;
213 }
214
223 public function post($request_data = null)
224 {
225 if (!DolibarrApiAccess::$user->hasRight('expedition', 'creer')) {
226 throw new RestException(403, "Insufficiant rights");
227 }
228 // Check mandatory fields
229 $result = $this->_validate($request_data);
230
231 foreach ($request_data as $field => $value) {
232 if ($field === 'caller') {
233 // 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
234 $this->shipment->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
235 continue;
236 }
237
238 $this->shipment->$field = $this->_checkValForAPI($field, $value, $this->shipment);
239 }
240 if (isset($request_data["lines"])) {
241 $lines = array();
242 foreach ($request_data["lines"] as $line) {
243 $shipmentline = new ExpeditionLigne($this->db);
244
245 $shipmentline->entrepot_id = (int) $line['entrepot_id'];
246 $shipmentline->fk_element = (int) ($line['fk_element'] ?? $line['origin_id']); // example: order id. this->origin is 'commande'
247 $shipmentline->origin_line_id = (int) ($line['fk_elementdet'] ?? $line['origin_line_id']); // example: order id
248 $shipmentline->fk_elementdet = (int) ($line['fk_elementdet'] ?? $line['origin_line_id']); // example: order line id
249 $shipmentline->origin_type = $line['element_type'] ?? $line['origin_type']; // example 'commande' or 'order'
250 $shipmentline->element_type = $line['element_type'] ?? $line['origin_type']; // example 'commande' or 'order'
251 $shipmentline->qty = (float) $line['qty'];
252 $shipmentline->rang = (int) $line['rang'];
253 $array_options = $line['array_options'];
254 if (is_array($array_options)) {
255 $shipmentline->array_options = $array_options;
256 }
257 $detail_batch = $line['detail_batch'];
258 if (is_array($detail_batch) || is_object($detail_batch)) {
259 $shipmentline->detail_batch = $detail_batch;
260 }
261 $lines[] = $shipmentline;
262 }
263 $this->shipment->lines = $lines;
264 }
265
266 if ($this->shipment->create(DolibarrApiAccess::$user) < 0) {
267 throw new RestException(500, "Error creating shipment", array_merge(array($this->shipment->error), $this->shipment->errors));
268 }
269
270 return $this->shipment->id;
271 }
272
284 public function getLines($id)
285 {
286 if (!DolibarrApiAccess::$user->hasRight('expedition', 'lire')) {
287 throw new RestException(403);
288 }
289
290 $result = $this->shipment->fetch($id);
291 if (!$result) {
292 throw new RestException(404, 'Shipment not found');
293 }
294
295 if (!DolibarrApi::_checkAccessToResource('expedition', $this->shipment->id)) {
296 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
297 }
298 $this->shipment->getLinesArray();
299 $result = array();
300 foreach ($this->shipment->lines as $line) {
301 array_push($result, $this->_cleanObjectDatas($line));
302 }
303 return $result;
304 }
305
331 public function postLine($id, $fk_origin_line = 0, $qty = 0, $warehouse_id = 0, $fk_product = 0)
332 {
333 if (!DolibarrApiAccess::$user->hasRight('expedition', 'creer')) {
334 throw new RestException(403);
335 }
336
337 $result = $this->shipment->fetch($id);
338 if (!$result) {
339 throw new RestException(404, 'Shipment not found');
340 }
341
342 if (!DolibarrApi::_checkAccessToResource('expedition', $this->shipment->id)) {
343 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
344 }
345
346 // A line can only be added while the shipment is a draft (no stock movement yet).
347 if ((int) $this->shipment->status != Expedition::STATUS_DRAFT) {
348 throw new RestException(405, 'Lines can only be added to a draft shipment');
349 }
350
351 $fk_origin_line = (int) $fk_origin_line;
352 if ($fk_origin_line <= 0) {
353 throw new RestException(400, 'Field fk_origin_line is mandatory');
354 }
355
356 $qty = (float) $qty;
357 if ($qty <= 0) {
358 throw new RestException(400, 'Field qty is mandatory and must be greater than 0');
359 }
360
361 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
362 $orderline = new OrderLine($this->db);
363 $resorderline = $orderline->fetch($fk_origin_line);
364 if ($resorderline <= 0) {
365 throw new RestException(404, 'Origin order line '.$fk_origin_line.' not found');
366 }
367 if (isModEnabled('productbatch') && !empty($orderline->product_tobatch)) {
368 throw new RestException(405, 'Adding a batch/lot managed shipment line is not supported through this endpoint. Use the dedicated dispatch flow instead.');
369 }
370
371 // addline() stacks the line in memory and runs native validation
372 // (warehouse requirement, stock availability, batch rejection).
373 $addResult = $this->shipment->addline((int) $warehouse_id, $fk_origin_line, $qty, array(), (int) $fk_product);
374 if ($addResult <= 0) {
375 $msg = $this->shipment->errorsToString() ? $this->shipment->errorsToString() : 'Error while adding shipment line';
376 // -1 missing warehouse, -3 not enough stock, -4 batch product: bad request from the caller.
377 if (in_array((int) $addResult, array(-1, -3, -4), true)) {
378 throw new RestException(400, $msg);
379 }
380 throw new RestException(500, $msg);
381 }
382
383 // addline() only fills $this->shipment->lines; persist the line just stacked.
384 $line = end($this->shipment->lines);
385 $line->fk_expedition = $this->shipment->id;
386
387 $insertRes = $line->insert(DolibarrApiAccess::$user);
388 if ($insertRes > 0) {
389 return $insertRes;
390 }
391
392 throw new RestException(500, $line->errorsToString());
393 }
394
419 public function putLine($id, $lineid, $qty = 0, $warehouse_id = 0)
420 {
421 if (!DolibarrApiAccess::$user->hasRight('expedition', 'creer')) {
422 throw new RestException(403);
423 }
424
425 $result = $this->shipment->fetch($id);
426 if (!$result) {
427 throw new RestException(404, 'Shipment not found');
428 }
429
430 if (!DolibarrApi::_checkAccessToResource('expedition', $this->shipment->id)) {
431 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
432 }
433
434 // A line can only be edited while the shipment is a draft (no stock movement yet).
435 if ((int) $this->shipment->status != Expedition::STATUS_DRAFT) {
436 throw new RestException(405, 'Only draft shipment lines can be updated');
437 }
438
439 $qty = (float) $qty;
440 if ($qty <= 0) {
441 throw new RestException(400, 'Field qty is mandatory and must be greater than 0');
442 }
443
444 $line = new ExpeditionLigne($this->db);
445 $resline = $line->fetch($lineid);
446 if ($resline <= 0) {
447 throw new RestException(404, 'Shipment line not found');
448 }
449 if ((int) $line->fk_expedition != (int) $this->shipment->id) {
450 throw new RestException(404, 'Line '.((int) $lineid).' is not a line of shipment '.((int) $id));
451 }
452
453 require_once DOL_DOCUMENT_ROOT.'/expedition/class/expeditionlinebatch.class.php';
454 $linebatch = new ExpeditionLineBatch($this->db);
455 $lots = $linebatch->fetchAll($line->id);
456 if (is_array($lots) && count($lots) > 0) {
457 throw new RestException(405, 'Update of a batch/lot managed shipment line is not supported. Delete and recreate the line instead.');
458 }
459
460 $line->qty = $qty;
461 if ($warehouse_id > 0) {
462 $line->entrepot_id = (int) $warehouse_id;
463 }
464
465 $updateRes = $line->update(DolibarrApiAccess::$user);
466 if ($updateRes > 0) {
467 return $this->get($id);
468 }
469
470 throw new RestException(500, $line->errorsToString() ? $line->errorsToString() : $this->shipment->errorsToString());
471 }
472
492 public function deleteLine($id, $lineid)
493 {
494 if (!DolibarrApiAccess::$user->hasRight('expedition', 'creer')) {
495 throw new RestException(403);
496 }
497
498 $result = $this->shipment->fetch($id);
499 if (!$result) {
500 throw new RestException(404, 'Shipment not found');
501 }
502
503 if (!DolibarrApi::_checkAccessToResource('expedition', $this->shipment->id)) {
504 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
505 }
506
507 // A line can only be deleted while the shipment is a draft (no stock movement yet).
508 if ((int) $this->shipment->status != Expedition::STATUS_DRAFT) {
509 throw new RestException(405, 'Only draft shipment lines can be deleted');
510 }
511
512 $line = new ExpeditionLigne($this->db);
513 $resline = $line->fetch($lineid);
514 if ($resline <= 0) {
515 throw new RestException(404, 'Shipment line not found');
516 }
517 if ((int) $line->fk_expedition != (int) $this->shipment->id) {
518 throw new RestException(404, 'Line '.((int) $lineid).' is not a line of shipment '.((int) $id));
519 }
520
521 $deleteRes = $this->shipment->deleteLine(DolibarrApiAccess::$user, $lineid);
522 if ($deleteRes > 0) {
523 return $this->get($id);
524 }
525
526 throw new RestException(500, $this->shipment->errorsToString() ? $this->shipment->errorsToString() : 'Error while deleting shipment line');
527 }
528
538 public function put($id, $request_data = null)
539 {
540 if (!DolibarrApiAccess::$user->hasRight('expedition', 'creer')) {
541 throw new RestException(403);
542 }
543
544 $result = $this->shipment->fetch($id);
545 if (!$result) {
546 throw new RestException(404, 'Shipment not found');
547 }
548
549 if (!DolibarrApi::_checkAccessToResource('expedition', $this->shipment->id)) {
550 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
551 }
552 foreach ($request_data as $field => $value) {
553 if ($field == 'id') {
554 continue;
555 }
556 if ($field === 'caller') {
557 // 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
558 $this->shipment->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
559 continue;
560 }
561
562 if ($field == 'array_options' && is_array($value)) {
563 foreach ($value as $index => $val) {
564 $this->shipment->array_options[$index] = $this->_checkValExtrafieldsForAPI($index, $val, $this->shipment);
565 }
566 continue;
567 }
568 $this->shipment->$field = $this->_checkValForAPI($field, $value, $this->shipment);
569 }
570
571 if ($this->shipment->update(DolibarrApiAccess::$user) > 0) {
572 return $this->get($id);
573 } else {
574 throw new RestException(500, $this->shipment->errorsToString());
575 }
576 }
577
587 public function delete($id)
588 {
589 if (!DolibarrApiAccess::$user->hasRight('expedition', 'supprimer')) {
590 throw new RestException(403);
591 }
592 $result = $this->shipment->fetch($id);
593 if (!$result) {
594 throw new RestException(404, 'Shipment not found');
595 }
596
597 if (!DolibarrApi::_checkAccessToResource('expedition', $this->shipment->id)) {
598 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
599 }
600
601 if (!$this->shipment->delete(DolibarrApiAccess::$user)) {
602 throw new RestException(500, 'Error when deleting shipment : '.$this->shipment->errorsToString());
603 }
604
605 return array(
606 'success' => array(
607 'code' => 200,
608 'message' => 'Shipment deleted'
609 )
610 );
611 }
612
632 public function validate($id, $notrigger = 0)
633 {
634 if (!DolibarrApiAccess::$user->hasRight('expedition', 'creer')) {
635 throw new RestException(403);
636 }
637 $result = $this->shipment->fetch($id);
638 if (!$result) {
639 throw new RestException(404, 'Shipment not found');
640 }
641
642 if (!DolibarrApi::_checkAccessToResource('expedition', $this->shipment->id)) {
643 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
644 }
645
646 $result = $this->shipment->valid(DolibarrApiAccess::$user, $notrigger);
647 if ($result == 0) {
648 throw new RestException(304, 'Error nothing done. May be object is already validated');
649 }
650 if ($result < 0) {
651 throw new RestException(500, 'Error when validating Shipment: '.$this->shipment->errorsToString());
652 }
653
654 // Reload shipment
655 $result = $this->shipment->fetch($id);
656
657 $this->shipment->fetchObjectLinked();
658 return $this->_cleanObjectDatas($this->shipment);
659 }
660
661
662 // /**
663 // * Classify the shipment as invoiced
664 // *
665 // * @param int $id Id of the shipment
666 // *
667 // * @url POST {id}/setinvoiced
668 // *
669 // * @return int
670 // *
671 // * @throws RestException 400
672 // * @throws RestException 401
673 // * @throws RestException 404
674 // * @throws RestException 405
675 // */
676 /*
677 public function setinvoiced($id)
678 {
679
680 if(! DolibarrApiAccess::$user->hasRight('expedition', 'creer')) {
681 throw new RestException(403);
682 }
683 if(empty($id)) {
684 throw new RestException(400, 'Shipment ID is mandatory');
685 }
686 $result = $this->shipment->fetch($id);
687 if( ! $result ) {
688 throw new RestException(404, 'Shipment not found');
689 }
690
691 $result = $this->shipment->classifyBilled(DolibarrApiAccess::$user);
692 if( $result < 0) {
693 throw new RestException(400, $this->shipment->errorsToString());
694 }
695 return $result;
696 }
697 */
698
699
700 // /**
701 // * Create a shipment using an existing order.
702 // *
703 // * @param int $orderid Id of the order
704 // *
705 // * @url POST /createfromorder/{orderid}
706 // *
707 // * @return int
708 // * @throws RestException 400
709 // * @throws RestException 401
710 // * @throws RestException 404
711 // * @throws RestException 405
712 // */
713 /*
714 public function createShipmentFromOrder($orderid)
715 {
716
717 require_once DOL_DOCUMENT_ROOT . '/commande/class/commande.class.php';
718
719 if(! DolibarrApiAccess::$user->hasRight('expedition', 'lire')) {
720 throw new RestException(403);
721 }
722 if(! DolibarrApiAccess::$user->hasRight('expedition', 'creer')) {
723 throw new RestException(403);
724 }
725 if(empty($proposalid)) {
726 throw new RestException(400, 'Order ID is mandatory');
727 }
728
729 $order = new Commande($this->db);
730 $result = $order->fetch($proposalid);
731 if( ! $result ) {
732 throw new RestException(404, 'Order not found');
733 }
734
735 $result = $this->shipment->createFromOrder($order, DolibarrApiAccess::$user);
736 if( $result < 0) {
737 throw new RestException(405, $this->shipment->errorsToString());
738 }
739 $this->shipment->fetchObjectLinked();
740 return $this->_cleanObjectDatas($this->shipment);
741 }
742 */
743
754 public function close($id, $notrigger = 0)
755 {
756 if (!DolibarrApiAccess::$user->hasRight('expedition', 'creer')) {
757 throw new RestException(403);
758 }
759
760 $result = $this->shipment->fetch($id);
761 if (!$result) {
762 throw new RestException(404, 'Shipment not found');
763 }
764
765 if (!DolibarrApi::_checkAccessToResource('expedition', $this->shipment->id)) {
766 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
767 }
768
769 $result = $this->shipment->setClosed();
770 if ($result == 0) {
771 throw new RestException(304, 'Error nothing done. May be object is already closed');
772 }
773 if ($result < 0) {
774 throw new RestException(500, 'Error when closing Order: '.$this->shipment->errorsToString());
775 }
776
777 // Reload shipment
778 $result = $this->shipment->fetch($id);
779
780 $this->shipment->fetchObjectLinked();
781
782 return $this->_cleanObjectDatas($this->shipment);
783 }
784
802 public function setToDraft($id)
803 {
804 if (!DolibarrApiAccess::$user->hasRight('expedition', 'creer')) {
805 throw new RestException(403);
806 }
807
808 $result = $this->shipment->fetch($id);
809 if (!$result) {
810 throw new RestException(404, 'Shipment not found');
811 }
812
813 if (!DolibarrApi::_checkAccessToResource('expedition', $this->shipment->id)) {
814 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
815 }
816
817 $result = $this->shipment->setDraft(DolibarrApiAccess::$user);
818 if ($result == 0) {
819 throw new RestException(304, 'Error nothing done. May be object is already draft');
820 }
821 if ($result < 0) {
822 throw new RestException(500, 'Error when setting shipment back to draft: '.$this->shipment->errorsToString());
823 }
824
825 // Reload shipment
826 $result = $this->shipment->fetch($id);
827
828 $this->shipment->fetchObjectLinked();
829
830 return $this->_cleanObjectDatas($this->shipment);
831 }
832
833 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
843 protected function _cleanObjectDatas($object)
844 {
845 // phpcs:enable
846 $object = parent::_cleanObjectDatas($object);
847
848 unset($object->canvas);
849
850 unset($object->thirdparty); // id already returned
851
852 unset($object->note);
853 unset($object->address);
854 unset($object->barcode_type);
855 unset($object->barcode_type_code);
856 unset($object->barcode_type_label);
857 unset($object->barcode_type_coder);
858
859 if (!empty($object->lines) && is_array($object->lines)) {
860 foreach ($object->lines as $line) {
861 if (is_array($line->detail_batch)) {
862 foreach ($line->detail_batch as $keytmp2 => $valtmp2) {
863 unset($line->detail_batch[$keytmp2]->db);
864 }
865 }
866 unset($line->canvas);
867
868 unset($line->tva_tx);
869 unset($line->vat_src_code);
870 unset($line->total_ht);
871 unset($line->total_ttc);
872 unset($line->total_tva);
873 unset($line->total_localtax1);
874 unset($line->total_localtax2);
875 unset($line->remise_percent);
876 }
877 }
878
879 return $object;
880 }
881
889 private function _validate($data)
890 {
891 if ($data === null) {
892 $data = array();
893 }
894 $shipment = array();
895 // A standalone shipment carries no source document, exactly as the card
896 // allows when SHIPMENT_STANDALONE is enabled: do not demand an origin the
897 // user is entitled to omit.
898 $mandatory = Shipments::$FIELDS;
899 if (getDolGlobalString('SHIPMENT_STANDALONE') && !isset($data['origin_id']) && !isset($data['origin_type'])) {
900 $mandatory = array_values(array_diff($mandatory, array('origin_id', 'origin_type')));
901 }
902 foreach ($mandatory as $field) {
903 if (!isset($data[$field])) {
904 throw new RestException(400, "$field field missing");
905 }
906 $shipment[$field] = $data[$field];
907 }
908 return $shipment;
909 }
910}
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Class for API REST v1.
Definition api.class.php:35
_checkValExtrafieldsForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
_filterObjectProperties($object, $properties)
Filter properties that will be returned on object.
_checkValForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
static _checkAccessToResource($resource, $resource_id=0, $dbtablename='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $parenttableforentity='')
Check access by user to a given resource.
const STATUS_DRAFT
Draft status.
Class to manage lines of shipment.
CRUD class for batch number management within shipment.
Class to manage order lines.
close($id, $notrigger=0)
Classify the shipment as invoiced.
_validate($data)
Validate fields before create or update object.
postLine($id, $fk_origin_line=0, $qty=0, $warehouse_id=0, $fk_product=0)
Add a line to a given shipment.
setToDraft($id)
Set a shipment back to draft status.
put($id, $request_data=null)
Update shipment general fields (won't touch lines of shipment)
putLine($id, $lineid, $qty=0, $warehouse_id=0)
Update a line of a given shipment.
index($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0, $thirdparty_ids='', $sqlfilters='', $properties='', $pagination_data=false)
List shipments.
validate($id, $notrigger=0)
Validate a shipment.
__construct()
Constructor.
post($request_data=null)
Create shipment object.
getLines($id)
Get lines of a shipment.
_cleanObjectDatas($object)
Clean sensible object datas @phpstan-template T.
deleteLine($id, $lineid)
Delete a line of a given shipment.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0, $forbiddenfields=array())
forgeSQLFromUniversalSearchCriteria
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
sanitizeVal($out='', $check='alphanohtml', $filter=null, $options=null)
Return a sanitized or empty value after checking value against a rule.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.