Completed
Branch develop (451d3e)
by
unknown
27:33
created

Orders::close()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 29
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 17
nc 6
nop 2
dl 0
loc 29
rs 8.439
c 0
b 0
f 0
1
<?php
2
/* Copyright (C) 2015   Jean-François Ferry     <[email protected]>
3
 * Copyright (C) 2016	Laurent Destailleur		<[email protected]>
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 <http://www.gnu.org/licenses/>.
17
 */
18
19
 use Luracast\Restler\RestException;
20
21
 require_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
 */
29
class 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
    );
38
39
    /**
40
     * @var Commande $commande {@type Commande}
41
     */
42
    public $commande;
43
44
    /**
45
     * Constructor
46
     */
47
    function __construct()
48
    {
49
		global $db, $conf;
50
		$this->db = $db;
51
        $this->commande = new Commande($this->db);
52
    }
53
54
    /**
55
     * Get properties of an order object
56
     *
57
     * Return an array with order informations
58
     *
59
     * @param       int         $id         ID of order
60
     * @return 	array|mixed data without useless information
61
	 *
62
     * @throws 	RestException
63
     */
64
    function get($id)
65
    {
66
		if(! DolibarrApiAccess::$user->rights->commande->lire) {
67
			throw new RestException(401);
68
		}
69
70
        $result = $this->commande->fetch($id);
71
        if( ! $result ) {
72
            throw new RestException(404, 'Order not found');
73
        }
74
75
		if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
76
			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
77
		}
78
79
        $this->commande->fetchObjectLinked();
80
		return $this->_cleanObjectDatas($this->commande);
81
    }
82
83
84
85
    /**
86
     * List orders
87
     *
88
     * Get a list of orders
89
     *
90
     * @param string	       $sortfield	        Sort field
91
     * @param string	       $sortorder	        Sort order
92
     * @param int		       $limit		        Limit for list
93
     * @param int		       $page		        Page number
94
     * @param string   	       $thirdparty_ids	    Thirdparty ids to filter orders of. {@example '1' or '1,2,3'} {@pattern /^[0-9,]*$/i}
95
     * @param string           $sqlfilters          Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
96
     * @return  array                               Array of order objects
97
     *
98
	 * @throws RestException
99
     */
100
    function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '') {
101
        global $db, $conf;
102
103
        $obj_ret = array();
104
105
        // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
106
        $socids = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $thirdparty_ids;
107
108
        // If the internal user must only see his customers, force searching by him
109
        $search_sale = 0;
110
        if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) $search_sale = DolibarrApiAccess::$user->id;
111
112
        $sql = "SELECT t.rowid";
113
        if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $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)
114
        $sql.= " FROM ".MAIN_DB_PREFIX."commande as t";
115
116
        if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale
117
118
        $sql.= ' WHERE t.entity IN ('.getEntity('commande').')';
119
        if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc";
120
        if ($socids) $sql.= " AND t.fk_soc IN (".$socids.")";
121
        if ($search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc";		// Join for the needed table to filter by sale
122
        // Insert sale filter
123
        if ($search_sale > 0)
124
        {
125
            $sql .= " AND sc.fk_user = ".$search_sale;
126
        }
127
        // Add sql filters
128
        if ($sqlfilters)
129
        {
130
            if (! DolibarrApi::_checkFilters($sqlfilters))
131
            {
132
                throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
133
            }
134
	        $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
135
            $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
136
        }
137
138
        $sql.= $db->order($sortfield, $sortorder);
139
        if ($limit)	{
140
            if ($page < 0)
141
            {
142
                $page = 0;
143
            }
144
            $offset = $limit * $page;
145
146
            $sql.= $db->plimit($limit + 1, $offset);
147
        }
148
149
        dol_syslog("API Rest request");
150
        $result = $db->query($sql);
151
152
        if ($result)
153
        {
154
            $num = $db->num_rows($result);
155
            $min = min($num, ($limit <= 0 ? $num : $limit));
156
            while ($i < $min)
0 ignored issues
show
Bug introduced by
The variable $i does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
157
            {
158
                $obj = $db->fetch_object($result);
159
                $commande_static = new Commande($db);
160
                if($commande_static->fetch($obj->rowid)) {
161
                    $obj_ret[] = $this->_cleanObjectDatas($commande_static);
162
                }
163
                $i++;
164
            }
165
        }
166
        else {
167
            throw new RestException(503, 'Error when retrieve commande list : '.$db->lasterror());
168
        }
169
        if( ! count($obj_ret)) {
170
            throw new RestException(404, 'No order found');
171
        }
172
		return $obj_ret;
173
    }
174
175
    /**
176
     * Create order object
177
     *
178
     * @param   array   $request_data   Request data
179
     * @return  int     ID of order
180
     */
181
    function post($request_data = NULL)
182
    {
183
      if(! DolibarrApiAccess::$user->rights->commande->creer) {
184
			  throw new RestException(401, "Insuffisant rights");
185
		  }
186
        // Check mandatory fields
187
        $result = $this->_validate($request_data);
188
189
        foreach($request_data as $field => $value) {
190
            $this->commande->$field = $value;
191
        }
192
        /*if (isset($request_data["lines"])) {
193
          $lines = array();
194
          foreach ($request_data["lines"] as $line) {
195
            array_push($lines, (object) $line);
196
          }
197
          $this->commande->lines = $lines;
198
        }*/
199
200
        if ($this->commande->create(DolibarrApiAccess::$user) < 0) {
201
            throw new RestException(500, "Error creating order", array_merge(array($this->commande->error), $this->commande->errors));
202
        }
203
204
        return $this->commande->id;
205
    }
206
207
    /**
208
     * Get lines of an order
209
     *
210
     * @param int   $id             Id of order
211
     *
212
     * @url	GET {id}/lines
213
     *
214
     * @return int
215
     */
216
    function getLines($id) {
217
      if(! DolibarrApiAccess::$user->rights->commande->lire) {
218
		  	throw new RestException(401);
219
		  }
220
221
      $result = $this->commande->fetch($id);
222
      if( ! $result ) {
223
         throw new RestException(404, 'Order not found');
224
      }
225
226
		  if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
227
			  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
228
      }
229
      $this->commande->getLinesArray();
230
      $result = array();
231
      foreach ($this->commande->lines as $line) {
232
        array_push($result,$this->_cleanObjectDatas($line));
233
      }
234
      return $result;
235
    }
236
237
    /**
238
     * Add a line to given order
239
     *
240
     * @param int   $id             Id of order to update
241
     * @param array $request_data   OrderLine data
242
     *
243
     * @url	POST {id}/lines
244
     *
245
     * @return int
246
     */
247
    function postLine($id, $request_data = NULL) {
248
      if(! DolibarrApiAccess::$user->rights->commande->creer) {
249
		  	throw new RestException(401);
250
		  }
251
252
      $result = $this->commande->fetch($id);
253
      if( ! $result ) {
254
         throw new RestException(404, 'Order not found');
255
      }
256
257
		  if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
258
			  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
259
      }
260
			$request_data = (object) $request_data;
261
      $updateRes = $this->commande->addline(
262
                        $request_data->desc,
263
                        $request_data->subprice,
264
                        $request_data->qty,
265
                        $request_data->tva_tx,
266
                        $request_data->localtax1_tx,
267
                        $request_data->localtax2_tx,
268
                        $request_data->fk_product,
269
                        $request_data->remise_percent,
270
                        $request_data->info_bits,
271
                        $request_data->fk_remise_except,
272
                        'HT',
273
                        0,
274
                        $request_data->date_start,
275
                        $request_data->date_end,
276
                        $request_data->product_type,
277
                        $request_data->rang,
278
                        $request_data->special_code,
279
                        $fk_parent_line,
0 ignored issues
show
Bug introduced by
The variable $fk_parent_line does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
280
                        $request_data->fk_fournprice,
281
                        $request_data->pa_ht,
282
                        $request_data->label,
283
                        $request_data->array_options,
284
                        $request_data->fk_unit,
285
                        $request_data->origin,
286
                        $request_data->origin_id,
287
                        $request_data->multicurrency_subprice
288
      );
289
290
      if ($updateRes > 0) {
291
        return $updateRes;
292
293
      }
294
      return false;
295
    }
296
297
    /**
298
     * Update a line to given order
299
     *
300
     * @param int   $id             Id of order to update
301
     * @param int   $lineid         Id of line to update
302
     * @param array $request_data   OrderLine data
303
     *
304
     * @url	PUT {id}/lines/{lineid}
305
     *
306
     * @return object
307
     */
308
    function putLine($id, $lineid, $request_data = NULL) {
309
      if(! DolibarrApiAccess::$user->rights->commande->creer) {
310
		  	throw new RestException(401);
311
		  }
312
313
      $result = $this->commande->fetch($id);
314
      if( ! $result ) {
315
         throw new RestException(404, 'Order not found');
316
      }
317
318
		  if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
319
			  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
320
      }
321
			$request_data = (object) $request_data;
322
      $updateRes = $this->commande->updateline(
323
                        $lineid,
324
                        $request_data->desc,
325
                        $request_data->subprice,
326
                        $request_data->qty,
327
                        $request_data->remise_percent,
328
                        $request_data->tva_tx,
329
                        $request_data->localtax1_tx,
330
                        $request_data->localtax2_tx,
331
                        'HT',
332
                        $request_data->info_bits,
333
                        $request_data->date_start,
334
                        $request_data->date_end,
335
                        $request_data->product_type,
336
                        $request_data->fk_parent_line,
337
                        0,
338
                        $request_data->fk_fournprice,
339
                        $request_data->pa_ht,
340
                        $request_data->label,
341
                        $request_data->special_code,
342
                        $request_data->array_options,
343
                        $request_data->fk_unit,
344
      					$request_data->multicurrency_subprice
345
      );
346
347
      if ($updateRes > 0) {
348
        $result = $this->get($id);
349
        unset($result->line);
350
        return $this->_cleanObjectDatas($result);
351
      }
352
      return false;
353
    }
354
355
    /**
356
     * Delete a line to given order
357
     *
358
     *
359
     * @param int   $id             Id of order to update
360
     * @param int   $lineid         Id of line to delete
361
     *
362
     * @url	DELETE {id}/lines/{lineid}
363
     *
364
     * @return int
365
     * @throws 401
366
     * @throws 404
367
     */
368
    function deleteLine($id, $lineid) {
369
      if(! DolibarrApiAccess::$user->rights->commande->creer) {
370
		  	throw new RestException(401);
371
		  }
372
373
      $result = $this->commande->fetch($id);
374
      if( ! $result ) {
375
         throw new RestException(404, 'Commande not found');
376
      }
377
378
		  if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
379
			  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
380
      }
381
382
      $request_data = (object) $request_data;
0 ignored issues
show
Bug introduced by
The variable $request_data seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
383
      $updateRes = $this->commande->deleteline(DolibarrApiAccess::$user,$lineid);
384
      if ($updateRes > 0) {
385
        return $this->get($id);
386
      }
387
      return false;
388
    }
389
390
    /**
391
     * Update order general fields (won't touch lines of order)
392
     *
393
     * @param int   $id             Id of order to update
394
     * @param array $request_data   Datas
395
     *
396
     * @return int
397
     */
398
    function put($id, $request_data = NULL) {
399
      if (! DolibarrApiAccess::$user->rights->commande->creer) {
400
		  	throw new RestException(401);
401
		  }
402
403
        $result = $this->commande->fetch($id);
404
        if (! $result) {
405
            throw new RestException(404, 'Order not found');
406
        }
407
408
		if (! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
409
			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
410
		}
411
        foreach($request_data as $field => $value) {
412
            if ($field == 'id') continue;
413
            $this->commande->$field = $value;
414
        }
415
416
	// Update availability
417
	if (!empty($this->commande->availability_id)) {
418
	    if ($this->commande->availability($this->commande->availability_id) < 0)
419
		throw new RestException(400, 'Error while updating availability');
420
	}
421
422
        if ($this->commande->update($id, DolibarrApiAccess::$user, 1, '', '', 'update'))
423
            return $this->get($id);
424
425
        return false;
426
    }
427
428
    /**
429
     * Delete order
430
     *
431
     * @param   int     $id         Order ID
432
     *
433
     * @return  array
434
     */
435
    function delete($id)
436
    {
437
        if(! DolibarrApiAccess::$user->rights->commande->supprimer) {
438
			throw new RestException(401);
439
		}
440
        $result = $this->commande->fetch($id);
441
        if( ! $result ) {
442
            throw new RestException(404, 'Order not found');
443
        }
444
445
		if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
446
			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
447
		}
448
449
        if( ! $this->commande->delete(DolibarrApiAccess::$user)) {
450
            throw new RestException(500, 'Error when delete order : '.$this->commande->error);
451
        }
452
453
        return array(
454
            'success' => array(
455
                'code' => 200,
456
                'message' => 'Order deleted'
457
            )
458
        );
459
460
    }
461
462
    /**
463
     * Validate an order
464
     *
465
     * @param   int $id             Order ID
466
     * @param   int $idwarehouse    Warehouse ID
467
     * @param   int $notrigger      1=Does not execute triggers, 0= execute triggers
468
     *
469
     * @url POST    {id}/validate
470
     *
471
     * @return  array
472
     * FIXME An error 403 is returned if the request has an empty body.
473
     * Error message: "Forbidden: Content type `text/plain` is not supported."
474
     * Workaround: send this in the body
475
     * {
476
     *   "idwarehouse": 0,
477
     *   "notrigger": 0
478
     * }
479
     */
480
    function validate($id, $idwarehouse=0, $notrigger=0)
481
    {
482
        if(! DolibarrApiAccess::$user->rights->commande->creer) {
483
			throw new RestException(401);
484
		}
485
        $result = $this->commande->fetch($id);
486
        if( ! $result ) {
487
            throw new RestException(404, 'Order not found');
488
        }
489
490
		if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
491
			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
492
		}
493
494
		$result = $this->commande->valid(DolibarrApiAccess::$user, $idwarehouse, $notrigger);
495
		if ($result == 0) {
496
		    throw new RestException(304, 'Error nothing done. May be object is already validated');
497
		}
498
		if ($result < 0) {
499
		    throw new RestException(500, 'Error when validating Order: '.$this->commande->error);
500
		}
501
	$result = $this->commande->fetch($id);
502
        if( ! $result ) {
503
            throw new RestException(404, 'Order not found');
504
        }
505
506
	if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
507
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
508
       }
509
510
        $this->commande->fetchObjectLinked();
511
        return $this->_cleanObjectDatas($this->commande);
512
    }
513
514
    /**
515
     * Close an order (Classify it as "Delivered")
516
     *
517
     * @param   int     $id             Order ID
518
     * @param   int     $notrigger      Disabled triggers
519
     *
520
     * @url POST    {id}/close
521
     *
522
     * @return  array
523
     */
524
    function close($id, $notrigger=0)
525
    {
526
    	if(! DolibarrApiAccess::$user->rights->commande->creer) {
527
    		throw new RestException(401);
528
    	}
529
    	$result = $this->commande->fetch($id);
530
    	if( ! $result ) {
531
    		throw new RestException(404, 'Order not found');
532
    	}
533
534
    	if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
535
    		throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
536
    	}
537
538
    	$result = $this->commande->cloture(DolibarrApiAccess::$user, $notrigger);
539
    	if ($result == 0) {
540
    		throw new RestException(304, 'Error nothing done. May be object is already closed');
541
    	}
542
    	if ($result < 0) {
543
    		throw new RestException(500, 'Error when closing Order: '.$this->commande->error);
544
    	}
545
546
    	return array(
547
    	'success' => array(
548
	    	'code' => 200,
549
	    	'message' => 'Order closed (Ref='.$this->commande->ref.')'
550
	    	)
551
    	);
552
    }
553
554
    /**
555
     * Set an order to draft
556
     *
557
     * @param   int     $id             Order ID
558
     * @param   int 	$idwarehouse    Warehouse ID to use for stock change (Used only if option STOCK_CALCULATE_ON_VALIDATE_ORDER is on)
559
     *
560
     * @url POST    {id}/settodraft
561
     *
562
     * @return  array
563
     */
564
    function settodraft($id, $idwarehouse=-1)
565
    {
566
        if(! DolibarrApiAccess::$user->rights->commande->creer) {
567
                throw new RestException(401);
568
        }
569
        $result = $this->commande->fetch($id);
570
        if( ! $result ) {
571
                throw new RestException(404, 'Order not found');
572
        }
573
574
        if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
575
                throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
576
        }
577
578
        $result = $this->commande->set_draft(DolibarrApiAccess::$user, $idwarehouse);
579
        if ($result == 0) {
580
                throw new RestException(304, 'Nothing done. May be object is already closed');
581
        }
582
        if ($result < 0) {
583
                throw new RestException(500, 'Error when closing Order: '.$this->commande->error);
584
        }
585
586
		$result = $this->commande->fetch($id);
587
        if( ! $result ) {
588
            throw new RestException(404, 'Order not found');
589
        }
590
591
        if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
592
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
593
        }
594
595
        $this->commande->fetchObjectLinked();
596
        return $this->_cleanObjectDatas($this->commande);
597
    }
598
599
600
    /**
601
     * Clean sensible object datas
602
     *
603
     * @param   object  $object    Object to clean
604
     * @return    array    Array of cleaned object properties
605
     */
606
    function _cleanObjectDatas($object) {
607
608
        $object = parent::_cleanObjectDatas($object);
609
610
        unset($object->note);
611
        unset($object->address);
612
        unset($object->barcode_type);
613
        unset($object->barcode_type_code);
614
        unset($object->barcode_type_label);
615
        unset($object->barcode_type_coder);
616
617
        return $object;
618
    }
619
620
    /**
621
     * Validate fields before create or update object
622
     *
623
     * @param   array           $data   Array with data to verify
624
     * @return  array
625
     * @throws  RestException
626
     */
627
    function _validate($data)
628
    {
629
        $commande = array();
630
        foreach (Orders::$FIELDS as $field) {
631
            if (!isset($data[$field]))
632
                throw new RestException(400, "$field field missing");
633
            $commande[$field] = $data[$field];
634
635
        }
636
        return $commande;
637
    }
638
}
639