Passed
Pull Request — master (#2)
by
unknown
26:19
created

Invoices::put()   B

Complexity

Conditions 9
Paths 18

Size

Total Lines 33
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 16
nc 18
nop 2
dl 0
loc 33
rs 8.0555
c 0
b 0
f 0
1
<?php
2
/* Copyright (C) 2015   Jean-François Ferry     <[email protected]>
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
use Luracast\Restler\RestException;
19
20
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
21
22
/**
23
 * API class for invoices
24
 *
25
 * @access protected
26
 * @class  DolibarrApiAccess {@requires user,external}
27
 */
28
class Invoices extends DolibarrApi
29
{
30
    /**
31
     *
32
     * @var array   $FIELDS     Mandatory fields, checked when create and update object
33
     */
34
    static $FIELDS = array(
35
        'socid',
36
    );
37
38
    /**
39
     * @var Facture $invoice {@type Facture}
40
     */
41
    public $invoice;
42
43
    /**
44
     * Constructor
45
     */
46
    function __construct()
47
    {
48
		global $db, $conf;
49
		$this->db = $db;
50
        $this->invoice = new Facture($this->db);
51
    }
52
53
    /**
54
     * Get properties of a invoice object
55
     *
56
     * Return an array with invoice informations
57
     *
58
     * @param 	int 	$id ID of invoice
59
     * @return 	array|mixed data without useless information
60
     *
61
     * @throws 	RestException
62
     */
63
	function get($id)
64
	{
65
		if(! DolibarrApiAccess::$user->rights->facture->lire) {
66
			throw new RestException(401);
67
		}
68
69
		$result = $this->invoice->fetch($id);
70
		if (! $result) {
71
			throw new RestException(404, 'Invoice not found');
72
		}
73
74
		// Get payment details
75
		$this->invoice->totalpaye = $this->invoice->getSommePaiement();
76
		$this->invoice->totalcreditnotes = $this->invoice->getSumCreditNotesUsed();
77
		$this->invoice->totaldeposits = $this->invoice->getSumDepositsUsed();
78
		$this->invoice->resteapayer = price2num($this->invoice->total_ttc - $this->invoice->totalpaye - $this->invoice->totalcreditnotes - $this->invoice->totaldeposits, 'MT');
79
80
		if (! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
81
			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
82
		}
83
84
		// Add external contacts ids
85
		$this->invoice->contacts_ids = $this->invoice->liste_contact(-1,'external',1);
0 ignored issues
show
Bug introduced by
The property contacts_ids does not exist on Facture. Did you mean contact?
Loading history...
86
87
		$this->invoice->fetchObjectLinked();
88
		return $this->_cleanObjectDatas($this->invoice);
89
	}
90
91
    /**
92
     * List invoices
93
     *
94
     * Get a list of invoices
95
     *
96
     * @param string	$sortfield	      Sort field
97
     * @param string	$sortorder	      Sort order
98
     * @param int		$limit		      Limit for list
99
     * @param int		$page		      Page number
100
     * @param string   	$thirdparty_ids	  Thirdparty ids to filter orders of. {@example '1' or '1,2,3'} {@pattern /^[0-9,]*$/i}
101
     * @param string	$status		      Filter by invoice status : draft | unpaid | paid | cancelled
102
     * @param string    $sqlfilters       Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
103
     * @return array                      Array of invoice objects
104
     *
105
	 * @throws RestException
106
     */
107
    function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids='', $status='', $sqlfilters = '')
108
    {
109
        global $db, $conf;
110
111
        $obj_ret = array();
112
113
        // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
114
        $socids = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $thirdparty_ids;
115
116
        // If the internal user must only see his customers, force searching by him
117
        $search_sale = 0;
118
        if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) $search_sale = DolibarrApiAccess::$user->id;
119
120
        $sql = "SELECT t.rowid";
121
        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)
122
        $sql.= " FROM ".MAIN_DB_PREFIX."facture as t";
123
124
        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
125
126
        $sql.= ' WHERE t.entity IN ('.getEntity('invoice').')';
127
        if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc";
128
        if ($socids) $sql.= " AND t.fk_soc IN (".$socids.")";
129
130
        if ($search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc";		// Join for the needed table to filter by sale
131
132
		// Filter by status
133
        if ($status == 'draft')     $sql.= " AND t.fk_statut IN (0)";
134
        if ($status == 'unpaid')    $sql.= " AND t.fk_statut IN (1)";
135
        if ($status == 'paid')      $sql.= " AND t.fk_statut IN (2)";
136
        if ($status == 'cancelled') $sql.= " AND t.fk_statut IN (3)";
137
        // Insert sale filter
138
        if ($search_sale > 0)
139
        {
140
            $sql .= " AND sc.fk_user = ".$search_sale;
141
        }
142
        // Add sql filters
143
        if ($sqlfilters)
144
        {
145
            if (! DolibarrApi::_checkFilters($sqlfilters))
146
            {
147
                throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
148
            }
149
	        $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
150
            $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
151
        }
152
153
        $sql.= $db->order($sortfield, $sortorder);
154
        if ($limit)
155
        {
156
            if ($page < 0)
157
            {
158
                $page = 0;
159
            }
160
            $offset = $limit * $page;
161
162
            $sql.= $db->plimit($limit + 1, $offset);
163
        }
164
165
        $result = $db->query($sql);
166
        if ($result)
167
        {
168
            $i=0;
169
            $num = $db->num_rows($result);
170
            $min = min($num, ($limit <= 0 ? $num : $limit));
171
            while ($i < $min)
172
            {
173
                $obj = $db->fetch_object($result);
174
                $invoice_static = new Facture($db);
175
                if ($invoice_static->fetch($obj->rowid))
176
                {
177
                	// Get payment details
178
                	$invoice_static->totalpaid = $invoice_static->getSommePaiement();
179
                	$invoice_static->totalcreditnotes = $invoice_static->getSumCreditNotesUsed();
180
                	$invoice_static->totaldeposits = $invoice_static->getSumDepositsUsed();
181
                	$invoice_static->remaintopay = price2num($invoice_static->total_ttc - $invoice_static->totalpaid - $invoice_static->totalcreditnotes - $invoice_static->totaldeposits, 'MT');
182
183
					// Add external contacts ids
184
					$invoice_static->contacts_ids = $invoice_static->liste_contact(-1,'external',1);
0 ignored issues
show
Bug introduced by
The property contacts_ids does not exist on Facture. Did you mean contact?
Loading history...
185
186
                	$obj_ret[] = $this->_cleanObjectDatas($invoice_static);
187
                }
188
                $i++;
189
            }
190
        }
191
        else {
192
            throw new RestException(503, 'Error when retrieve invoice list : '.$db->lasterror());
193
        }
194
        if( ! count($obj_ret)) {
195
            throw new RestException(404, 'No invoice found');
196
        }
197
		return $obj_ret;
198
    }
199
200
    /**
201
     * Create invoice object
202
     *
203
     * @param array $request_data   Request datas
204
     * @return int                  ID of invoice
205
     */
206
    function post($request_data = null)
207
    {
208
        if(! DolibarrApiAccess::$user->rights->facture->creer) {
209
			throw new RestException(401, "Insuffisant rights");
210
		}
211
        // Check mandatory fields
212
        $result = $this->_validate($request_data);
213
214
        foreach($request_data as $field => $value) {
215
            $this->invoice->$field = $value;
216
        }
217
        if(! array_key_exists('date', $request_data)) {
218
            $this->invoice->date = dol_now();
219
        }
220
        /* We keep lines as an array
221
         if (isset($request_data["lines"])) {
222
            $lines = array();
223
            foreach ($request_data["lines"] as $line) {
224
                array_push($lines, (object) $line);
225
            }
226
            $this->invoice->lines = $lines;
227
        }*/
228
229
        if ($this->invoice->create(DolibarrApiAccess::$user) < 0) {
230
            throw new RestException(500, "Error creating invoice", array_merge(array($this->invoice->error), $this->invoice->errors));
231
        }
232
        return $this->invoice->id;
233
    }
234
235
     /**
236
     * Create an invoice using an existing order.
237
     *
238
     *
239
     * @param int   $orderid       Id of the order
240
     *
241
     * @url     POST /createfromorder/{orderid}
242
     *
243
     * @return int
244
     * @throws 400
245
     * @throws 401
246
     * @throws 404
247
     * @throws 405
248
     */
249
    function createInvoiceFromOrder($orderid)
250
    {
251
252
        require_once DOL_DOCUMENT_ROOT . '/commande/class/commande.class.php';
253
254
        if(! DolibarrApiAccess::$user->rights->commande->lire) {
255
            throw new RestException(401);
256
        }
257
        if(! DolibarrApiAccess::$user->rights->facture->creer) {
258
            throw new RestException(401);
259
        }
260
        if(empty($orderid)) {
261
            throw new RestException(400, 'Order ID is mandatory');
262
        }
263
264
        $order = new Commande($this->db);
265
        $result = $order->fetch($orderid);
266
        if( ! $result ) {
267
            throw new RestException(404, 'Order not found');
268
        }
269
270
        $result = $this->invoice->createFromOrder($order, DolibarrApiAccess::$user);
271
        if( $result < 0) {
272
            throw new RestException(405, $this->invoice->error);
273
        }
274
        $this->invoice->fetchObjectLinked();
275
        return $this->_cleanObjectDatas($this->invoice);
276
    }
277
278
    /**
279
     * Get lines of an invoice
280
     *
281
     * @param int   $id             Id of invoice
282
     *
283
     * @url	GET {id}/lines
284
     *
285
     * @return int
286
     */
287
    function getLines($id)
288
    {
289
    	if(! DolibarrApiAccess::$user->rights->facture->lire) {
290
    		throw new RestException(401);
291
    	}
292
293
    	$result = $this->invoice->fetch($id);
294
    	if( ! $result ) {
295
    		throw new RestException(404, 'Invoice not found');
296
    	}
297
298
    	if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
299
    		throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
300
    	}
301
    	$this->invoice->getLinesArray();
302
    	$result = array();
303
    	foreach ($this->invoice->lines as $line) {
304
    		array_push($result,$this->_cleanObjectDatas($line));
305
    	}
306
    	return $result;
307
    }
308
309
    /**
310
     * Update a line to a given invoice
311
     *
312
     * @param int   $id             Id of invoice to update
313
     * @param int   $lineid         Id of line to update
314
     * @param array $request_data   InvoiceLine data
315
     *
316
     * @url	PUT {id}/lines/{lineid}
317
     *
318
     * @return object
319
     *
320
     * @throws 200
321
     * @throws 304
322
     * @throws 401
323
     * @throws 404
324
     */
325
    function putLine($id, $lineid, $request_data = null)
326
    {
327
    	if(! DolibarrApiAccess::$user->rights->facture->creer) {
328
    		throw new RestException(401);
329
    	}
330
331
    	$result = $this->invoice->fetch($id);
332
    	if( ! $result ) {
333
    		throw new RestException(404, 'Invoice not found');
334
    	}
335
336
    	if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
337
    		throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
338
    	}
339
    	$request_data = (object) $request_data;
340
    	$updateRes = $this->invoice->updateline(
341
    		$lineid,
342
    		$request_data->desc,
343
    		$request_data->subprice,
344
    		$request_data->qty,
345
    		$request_data->remise_percent,
346
    		$request_data->date_start,
347
    		$request_data->date_end,
348
    		$request_data->tva_tx,
349
    		$request_data->localtax1_tx,
350
    		$request_data->localtax2_tx,
351
    		'HT',
352
    		$request_data->info_bits,
353
    		$request_data->product_type,
354
    		$request_data->fk_parent_line,
355
    		0,
356
    		$request_data->fk_fournprice,
357
    		$request_data->pa_ht,
358
    		$request_data->label,
359
    		$request_data->special_code,
360
    		$request_data->array_options,
361
    		$request_data->situation_percent,
362
    		$request_data->fk_unit,
363
    		$request_data->multicurrency_subprice
364
    		);
365
366
    	if ($updateRes > 0) {
367
    		$result = $this->get($id);
368
    		unset($result->line);
369
    		return $this->_cleanObjectDatas($result);
370
	    } else {
371
	    	throw new RestException(304, $this->invoice->error);
372
    	}
373
    }
374
375
    /**
376
     * Deletes a line of a given invoice
377
     *
378
     * @param int   $id             Id of invoice
379
     * @param int   $lineid 		Id of the line to delete
380
     *
381
     * @url     DELETE {id}/lines/{lineid}
382
     *
383
     * @return array
384
     *
385
     * @throws 400
386
     * @throws 401
387
     * @throws 404
388
     * @throws 405
389
     */
390
    function deleteLine($id, $lineid)
391
    {
392
393
    	if(! DolibarrApiAccess::$user->rights->facture->creer) {
394
    		throw new RestException(401);
395
    	}
396
    	if(empty($lineid)) {
397
    		throw new RestException(400, 'Line ID is mandatory');
398
    	}
399
400
    	if( ! DolibarrApi::_checkAccessToResource('facture',$id)) {
401
    		throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
402
    	}
403
404
    	$result = $this->invoice->fetch($id);
405
    	if( ! $result ) {
406
    		throw new RestException(404, 'Invoice not found');
407
    	}
408
409
    	// TODO Check the lineid $lineid is a line of ojbect
410
411
    	$updateRes = $this->invoice->deleteline($lineid);
412
    	if ($updateRes > 0) {
413
    		return $this->get($id);
414
    	}
415
    	else
416
    	{
417
    		throw new RestException(405, $this->invoice->error);
418
    	}
419
    }
420
421
    /**
422
     * Update invoice
423
     *
424
     * @param int   $id             Id of invoice to update
425
     * @param array $request_data   Datas
426
     * @return int
427
     */
428
    function put($id, $request_data = null)
429
    {
430
        if(! DolibarrApiAccess::$user->rights->facture->creer) {
431
			throw new RestException(401);
432
		}
433
434
        $result = $this->invoice->fetch($id);
435
        if( ! $result ) {
436
            throw new RestException(404, 'Invoice not found');
437
        }
438
439
		if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
440
			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
441
		}
442
443
        foreach($request_data as $field => $value) {
444
            if ($field == 'id') continue;
445
            $this->invoice->$field = $value;
446
        }
447
448
        // update bank account
449
        if (!empty($this->invoice->fk_account))
450
        {
451
             if($this->invoice->setBankAccount($this->invoice->fk_account) == 0)
452
             {
453
                 throw new RestException(400,$this->invoice->error);
454
             }
455
        }
456
457
        if($this->invoice->update($id, DolibarrApiAccess::$user))
458
            return $this->get($id);
459
460
        return false;
461
    }
462
463
    /**
464
     * Delete invoice
465
     *
466
     * @param int   $id Invoice ID
467
     * @return array
468
     */
469
    function delete($id)
470
    {
471
        if(! DolibarrApiAccess::$user->rights->facture->supprimer) {
472
			throw new RestException(401);
473
		}
474
        $result = $this->invoice->fetch($id);
475
        if( ! $result ) {
476
            throw new RestException(404, 'Invoice not found');
477
        }
478
479
		if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
480
			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
481
		}
482
483
        if( $this->invoice->delete($id) < 0)
484
        {
485
            throw new RestException(500);
486
        }
487
488
         return array(
489
            'success' => array(
490
                'code' => 200,
491
                'message' => 'Invoice deleted'
492
            )
493
        );
494
    }
495
496
    /**
497
     * Add a line to a given invoice
498
     *
499
     * Exemple of POST query :
500
     * {
501
     *     "desc": "Desc", "subprice": "1.00000000", "qty": "1", "tva_tx": "20.000", "localtax1_tx": "0.000", "localtax2_tx": "0.000",
502
     *     "fk_product": "1", "remise_percent": "0", "date_start": "", "date_end": "", "fk_code_ventilation": 0,  "info_bits": "0",
503
     *     "fk_remise_except": null,  "product_type": "1", "rang": "-1", "special_code": "0", "fk_parent_line": null, "fk_fournprice": null,
504
     *     "pa_ht": "0.00000000", "label": "", "array_options": [], "situation_percent": "100", "fk_prev_id": null, "fk_unit": null
505
     * }
506
     *
507
     * @param int   $id             Id of invoice
508
     * @param array $request_data   InvoiceLine data
509
     *
510
     * @url     POST {id}/lines
511
     *
512
     * @return int
513
     *
514
     * @throws 200
515
     * @throws 401
516
     * @throws 404
517
     * @throws 400
518
     */
519
    function postLine($id, $request_data = null)
520
    {
521
        if(! DolibarrApiAccess::$user->rights->facture->creer) {
522
            throw new RestException(401);
523
        }
524
525
        $result = $this->invoice->fetch($id);
526
        if( ! $result ) {
527
            throw new RestException(404, 'Invoice not found');
528
        }
529
530
        if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
531
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
532
        }
533
534
        $request_data = (object) $request_data;
535
536
        // Reset fk_parent_line for no child products and special product
537
        if (($request_data->product_type != 9 && empty($request_data->fk_parent_line)) || $request_data->product_type == 9) {
538
            $request_data->fk_parent_line = 0;
539
        }
540
541
        // calculate pa_ht
542
        $marginInfos = getMarginInfos($request_data->subprice, $request_data->remise_percent, $request_data->tva_tx, $request_data->localtax1_tx, $request_data->localtax2_tx, $request_data->fk_fournprice, $request_data->pa_ht);
543
        $pa_ht = $marginInfos[0];
544
545
        $updateRes = $this->invoice->addline(
546
            $request_data->desc,
547
            $request_data->subprice,
548
            $request_data->qty,
549
            $request_data->tva_tx,
550
            $request_data->localtax1_tx,
551
            $request_data->localtax2_tx,
552
            $request_data->fk_product,
553
            $request_data->remise_percent,
554
            $request_data->date_start,
555
            $request_data->date_end,
556
            $request_data->fk_code_ventilation,
557
            $request_data->info_bits,
558
            $request_data->fk_remise_except,
559
            'HT',
560
            0,
561
            $request_data->product_type,
562
            $request_data->rang,
563
            $request_data->special_code,
564
            $request_data->origin,
565
            $request_data->origin_id,
566
            $request_data->fk_parent_line,
567
            empty($request_data->fk_fournprice)?null:$request_data->fk_fournprice,
568
            $pa_ht,
569
            $request_data->label,
570
            $request_data->array_options,
571
            $request_data->situation_percent,
572
            $request_data->fk_prev_id,
573
            $request_data->fk_unit
574
        );
575
576
        if ($updateRes < 0) {
577
            throw new RestException(400, 'Unable to insert the new line. Check your inputs. '.$this->invoice->error);
578
        }
579
580
        return $updateRes;
581
    }
582
583
    /**
584
     * Adds a contact to an invoice
585
     *
586
     * @param   int 	$id             	Order ID
587
     * @param   int 	$fk_socpeople       	Id of thirdparty contact (if source = 'external') or id of user (if souce = 'internal') to link
588
     * @param   string 	$type_contact           Type of contact (code). Must a code found into table llx_c_type_contact. For example: BILLING
589
     * @param   string  $source             	external=Contact extern (llx_socpeople), internal=Contact intern (llx_user)
590
     * @param   int     $notrigger              Disable all triggers
591
     *
592
     * @url POST    {id}/contacts
593
     *
594
     * @return  array
595
     *
596
     * @throws 200
597
     * @throws 304
598
     * @throws 401
599
     * @throws 404
600
     * @throws 500
601
     *
602
     */
603
    function addContact($id, $fk_socpeople, $type_contact, $source, $notrigger=0)
604
    {
605
        if(! DolibarrApiAccess::$user->rights->facture->creer) {
606
                throw new RestException(401);
607
        }
608
        $result = $this->invoice->fetch($id);
609
        if( ! $result ) {
610
                throw new RestException(404, 'Invoice not found');
611
        }
612
613
        if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
614
                throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
615
        }
616
617
        $result = $this->invoice->add_contact($fk_socpeople,$type_contact,$source,$notrigger);
618
        if ($result < 0) {
619
                throw new RestException(500, 'Error : '.$this->invoice->error);
620
        }
621
622
        $result = $this->invoice->fetch($id);
623
        if( ! $result ) {
624
            throw new RestException(404, 'Invoice not found');
625
        }
626
627
        if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
628
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
629
        }
630
631
        return $this->_cleanObjectDatas($this->invoice);
632
    }
633
634
635
636
    /**
637
     * Sets an invoice as draft
638
     *
639
     * @param   int $id             Order ID
640
     * @param   int $idwarehouse    Warehouse ID
641
     *
642
     * @url POST    {id}/settodraft
643
     *
644
     * @return  array
645
     *
646
     * @throws 200
647
     * @throws 304
648
     * @throws 401
649
     * @throws 404
650
     * @throws 500
651
     *
652
     */
653
    function settodraft($id, $idwarehouse=-1)
654
    {
655
        if(! DolibarrApiAccess::$user->rights->facture->creer) {
656
            throw new RestException(401);
657
        }
658
        $result = $this->invoice->fetch($id);
659
        if( ! $result ) {
660
            throw new RestException(404, 'Invoice not found');
661
        }
662
663
        if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
664
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
665
        }
666
667
        $result = $this->invoice->set_draft(DolibarrApiAccess::$user, $idwarehouse);
668
        if ($result == 0) {
669
            throw new RestException(304, 'Nothing done.');
670
        }
671
        if ($result < 0) {
672
            throw new RestException(500, 'Error : '.$this->invoice->error);
673
        }
674
675
        $result = $this->invoice->fetch($id);
676
        if( ! $result ) {
677
            throw new RestException(404, 'Invoice not found');
678
        }
679
680
        if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
681
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
682
        }
683
684
        return $this->_cleanObjectDatas($this->invoice);
685
    }
686
687
688
    /**
689
     * Validate an invoice
690
     *
691
	 * If you get a bad value for param notrigger check that ou provide this in body
692
     * {
693
     *   "idwarehouse": 0,
694
     *   "notrigger": 0
695
     * }
696
     *
697
     * @param   int $id             Invoice 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
     * @return  array
704
     */
705
    function validate($id, $idwarehouse=0, $notrigger=0)
706
    {
707
    	if(! DolibarrApiAccess::$user->rights->facture->creer) {
708
    		throw new RestException(401);
709
    	}
710
    	$result = $this->invoice->fetch($id);
711
    	if( ! $result ) {
712
    		throw new RestException(404, 'Invoice not found');
713
    	}
714
715
    	if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
716
    		throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
717
    	}
718
719
    	$result = $this->invoice->validate(DolibarrApiAccess::$user, '', $idwarehouse, $notrigger);
720
    	if ($result == 0) {
721
    		throw new RestException(304, 'Error nothing done. May be object is already validated');
722
    	}
723
    	if ($result < 0) {
724
    		throw new RestException(500, 'Error when validating Invoice: '.$this->invoice->error);
725
    	}
726
727
        $result = $this->invoice->fetch($id);
728
        if( ! $result ) {
729
            throw new RestException(404, 'Invoice not found');
730
        }
731
732
        if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
733
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
734
        }
735
736
        return $this->_cleanObjectDatas($this->invoice);
737
    }
738
739
    /**
740
     * Sets an invoice as paid
741
     *
742
     * @param   int 	$id            Order ID
743
     * @param   string 	$close_code    Code renseigne si on classe a payee completement alors que paiement incomplet (cas escompte par exemple)
744
     * @param   string 	$close_note    Commentaire renseigne si on classe a payee alors que paiement incomplet (cas escompte par exemple)
745
     *
746
     * @url POST    {id}/settopaid
747
     *
748
     * @return  array 	An invoice object
749
     *
750
     * @throws 200
751
     * @throws 304
752
     * @throws 401
753
     * @throws 404
754
     * @throws 500
755
     */
756
    function settopaid($id, $close_code='', $close_note='')
757
    {
758
        if(! DolibarrApiAccess::$user->rights->facture->creer) {
759
            throw new RestException(401);
760
        }
761
        $result = $this->invoice->fetch($id);
762
        if( ! $result ) {
763
            throw new RestException(404, 'Invoice not found');
764
        }
765
766
        if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
767
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
768
        }
769
770
        $result = $this->invoice->set_paid(DolibarrApiAccess::$user, $close_code, $close_note);
771
        if ($result == 0) {
772
            throw new RestException(304, 'Error nothing done. May be object is already validated');
773
        }
774
        if ($result < 0) {
775
            throw new RestException(500, 'Error : '.$this->invoice->error);
776
        }
777
778
779
        $result = $this->invoice->fetch($id);
780
        if( ! $result ) {
781
            throw new RestException(404, 'Invoice not found');
782
        }
783
784
        if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
785
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
786
        }
787
788
        return $this->_cleanObjectDatas($this->invoice);
789
    }
790
791
792
    /**
793
     * Sets an invoice as unpaid
794
     *
795
     * @param   int     $id            Order ID
796
     *
797
     * @url POST    {id}/settounpaid
798
     *
799
     * @return  array   An invoice object
800
     *
801
     * @throws 200
802
     * @throws 304
803
     * @throws 401
804
     * @throws 404
805
     * @throws 500
806
     */
807
    function settounpaid($id)
808
    {
809
        if(! DolibarrApiAccess::$user->rights->facture->creer) {
810
            throw new RestException(401);
811
        }
812
        $result = $this->invoice->fetch($id);
813
        if( ! $result ) {
814
            throw new RestException(404, 'Invoice not found');
815
        }
816
817
        if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
818
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
819
        }
820
821
        $result = $this->invoice->set_unpaid(DolibarrApiAccess::$user);
822
        if ($result == 0) {
823
            throw new RestException(304, 'Nothing done');
824
        }
825
        if ($result < 0) {
826
            throw new RestException(500, 'Error : '.$this->invoice->error);
827
        }
828
829
830
        $result = $this->invoice->fetch($id);
831
        if( ! $result ) {
832
            throw new RestException(404, 'Invoice not found');
833
        }
834
835
        if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
836
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
837
        }
838
839
        return $this->_cleanObjectDatas($this->invoice);
840
    }
841
842
     /**
843
     * Add a discount line into an invoice (as an invoice line) using an existing absolute discount
844
     *
845
     * Note that this consume the discount.
846
     *
847
     * @param int   $id             Id of invoice
848
     * @param int   $discountid     Id of discount
849
     *
850
     * @url     POST {id}/usediscount/{discountid}
851
     *
852
     * @return int
853
     * @throws 400
854
     * @throws 401
855
     * @throws 404
856
     * @throws 405
857
     */
858
    function useDiscount($id, $discountid)
859
    {
860
861
        if(! DolibarrApiAccess::$user->rights->facture->creer) {
862
            throw new RestException(401);
863
        }
864
        if(empty($id)) {
865
            throw new RestException(400, 'Invoice ID is mandatory');
866
        }
867
        if(empty($discountid)) {
868
            throw new RestException(400, 'Discount ID is mandatory');
869
        }
870
871
        if( ! DolibarrApi::_checkAccessToResource('facture',$id)) {
872
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
873
        }
874
875
        $result = $this->invoice->fetch($id);
876
        if( ! $result ) {
877
            throw new RestException(404, 'Invoice not found');
878
        }
879
880
        $result = $this->invoice->insert_discount($discountid);
881
        if( $result < 0) {
882
            throw new RestException(405, $this->invoice->error);
883
        }
884
885
        return $result;
886
    }
887
888
     /**
889
     * Add an available credit note discount to payments of an existing invoice.
890
     *
891
     *  Note that this consume the credit note.
892
     *
893
     * @param int   $id            Id of invoice
894
     * @param int   $discountid    Id of a discount coming from a credit note
895
     *
896
     * @url     POST {id}/usecreditnote/{discountid}
897
     *
898
     * @return int
899
     * @throws 400
900
     * @throws 401
901
     * @throws 404
902
     * @throws 405
903
     */
904
    function useCreditNote($id, $discountid)
905
    {
906
907
        require_once DOL_DOCUMENT_ROOT . '/core/class/discount.class.php';
908
909
        if(! DolibarrApiAccess::$user->rights->facture->creer) {
910
            throw new RestException(401);
911
        }
912
        if(empty($id)) {
913
            throw new RestException(400, 'Invoice ID is mandatory');
914
        }
915
        if(empty($discountid)) {
916
            throw new RestException(400, 'Credit ID is mandatory');
917
        }
918
919
        if( ! DolibarrApi::_checkAccessToResource('facture',$id)) {
920
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
921
        }
922
        $discount = new DiscountAbsolute($this->db);
923
        $result = $discount->fetch($discountid);
924
        if( ! $result ) {
925
            throw new RestException(404, 'Credit not found');
926
        }
927
928
        $result = $discount->link_to_invoice(0, $id);
929
        if( $result < 0) {
930
            throw new RestException(405, $discount->error);
931
        }
932
933
        return $result;
934
    }
935
936
    /**
937
     * Get list of payments of a given invoice
938
     *
939
     * @param int   $id             Id of invoice
940
     *
941
     * @url     GET {id}/payments
942
     *
943
     * @return array
944
     * @throws 400
945
     * @throws 401
946
     * @throws 404
947
     * @throws 405
948
     */
949
    function getPayments($id)
950
    {
951
952
        if(! DolibarrApiAccess::$user->rights->facture->lire) {
953
            throw new RestException(401);
954
        }
955
        if(empty($id)) {
956
            throw new RestException(400, 'Invoice ID is mandatory');
957
        }
958
959
        if( ! DolibarrApi::_checkAccessToResource('facture',$id)) {
960
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
961
        }
962
963
        $result = $this->invoice->fetch($id);
964
        if( ! $result ) {
965
            throw new RestException(404, 'Invoice not found');
966
        }
967
968
        $result = $this->invoice->getListOfPayments();
969
        if( $result < 0) {
970
            throw new RestException(405, $this->invoice->error);
971
        }
972
973
        return $result;
974
    }
975
976
977
    /**
978
     * Add payment line to a specific invoice with the remain to pay as amount.
979
     *
980
     * @param int     $id                               Id of invoice
981
     * @param string  $datepaye           {@from body}  Payment date        {@type timestamp}
982
     * @param int     $paiementid         {@from body}  Payment mode Id {@min 1}
983
     * @param string  $closepaidinvoices  {@from body}  Close paid invoices {@choice yes,no}
984
     * @param int     $accountid          {@from body}  Account Id {@min 1}
985
     * @param string  $num_paiement       {@from body}  Payment number (optional)
986
     * @param string  $comment            {@from body}  Note (optional)
987
     * @param string  $chqemetteur        {@from body}  Payment issuer (mandatory if paiementcode = 'CHQ')
988
     * @param string  $chqbank            {@from body}  Issuer bank name (optional)
989
     *
990
     * @url     POST {id}/payments
991
     *
992
     * @return int  Payment ID
993
     * @throws 400
994
     * @throws 401
995
     * @throws 404
996
     */
997
    function addPayment($id, $datepaye, $paiementid, $closepaidinvoices, $accountid, $num_paiement='', $comment='', $chqemetteur='', $chqbank='')
998
    {
999
        global $conf;
1000
1001
    	require_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php';
1002
1003
    	if(! DolibarrApiAccess::$user->rights->facture->creer) {
1004
    		throw new RestException(403);
1005
    	}
1006
    	if(empty($id)) {
1007
    		throw new RestException(400, 'Invoice ID is mandatory');
1008
    	}
1009
1010
    	if( ! DolibarrApi::_checkAccessToResource('facture',$id)) {
1011
    		throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
1012
    	}
1013
1014
    	if (! empty($conf->banque->enabled)) {
1015
    		if(empty($accountid)) {
1016
    			throw new RestException(400, 'Account ID is mandatory');
1017
    		}
1018
    	}
1019
1020
    	if(empty($paiementid)) {
1021
    		throw new RestException(400, 'Paiement ID or Paiement Code is mandatory');
1022
    	}
1023
1024
1025
    	$result = $this->invoice->fetch($id);
1026
    	if( ! $result ) {
1027
    		throw new RestException(404, 'Invoice not found');
1028
    	}
1029
1030
    	// Calculate amount to pay
1031
    	$totalpaye = $this->invoice->getSommePaiement();
1032
    	$totalcreditnotes = $this->invoice->getSumCreditNotesUsed();
1033
    	$totaldeposits = $this->invoice->getSumDepositsUsed();
1034
    	$resteapayer = price2num($this->invoice->total_ttc - $totalpaye - $totalcreditnotes - $totaldeposits, 'MT');
1035
1036
    	$this->db->begin();
1037
1038
    	$amounts = array();
1039
    	$multicurrency_amounts = array();
1040
1041
    	// Clean parameters amount if payment is for a credit note
1042
    	if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE) {
1043
    		$resteapayer = price2num($resteapayer,'MT');
1044
    		$amounts[$id] = -$resteapayer;
1045
    		// Multicurrency
1046
    		$newvalue = price2num($this->invoice->multicurrency_total_ttc,'MT');
1047
    		$multicurrency_amounts[$id] = -$newvalue;
1048
    	} else {
1049
    		$resteapayer = price2num($resteapayer,'MT');
1050
    		$amounts[$id] = $resteapayer;
1051
    		// Multicurrency
1052
    		$newvalue = price2num($this->invoice->multicurrency_total_ttc,'MT');
1053
    		$multicurrency_amounts[$id] = $newvalue;
1054
    	}
1055
1056
1057
    	// Creation of payment line
1058
    	$paiement = new Paiement($this->db);
1059
    	$paiement->datepaye     = $datepaye;
1060
    	$paiement->amounts      = $amounts;                           // Array with all payments dispatching with invoice id
1061
    	$paiement->multicurrency_amounts = $multicurrency_amounts;    // Array with all payments dispatching
1062
    	$paiement->paiementid   = $paiementid;
1063
    	$paiement->paiementcode = dol_getIdFromCode($this->db,$paiementid,'c_paiement','id','code',1);
0 ignored issues
show
Bug introduced by
The property paiementcode does not exist on Paiement. Did you mean paiementid?
Loading history...
1064
    	$paiement->num_paiement = $num_paiement;
1065
    	$paiement->note         = $comment;
1066
1067
    	$paiement_id = $paiement->create(DolibarrApiAccess::$user, ($closepaidinvoices=='yes'?1:0));    // This include closing invoices
1068
    	if ($paiement_id < 0)
1069
    	{
1070
    		$this->db->rollback();
1071
    		throw new RestException(400, 'Payment error : '.$paiement->error);
1072
    	}
1073
1074
    	if (! empty($conf->banque->enabled)) {
1075
    		$label='(CustomerInvoicePayment)';
1076
1077
    		if($paiement->paiementcode == 'CHQ' && empty($chqemetteur)) {
1078
    			throw new RestException(400, 'Emetteur is mandatory when payment code is '.$paiement->paiementcode);
1079
    		}
1080
    		if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE) $label='(CustomerInvoicePaymentBack)';  // Refund of a credit note
1081
    		$result=$paiement->addPaymentToBank(DolibarrApiAccess::$user,'payment',$label,$accountid,$chqemetteur,$chqbank);
1082
    		if ($result < 0)
1083
    		{
1084
    			$this->db->rollback();
1085
    			throw new RestException(400, 'Add payment to bank error : '.$paiement->error);
1086
    		}
1087
    	}
1088
1089
    	$this->db->commit();
1090
1091
    	return $paiement_id;
1092
    }
1093
1094
    /**
1095
     * Add a payment to pay partially or completely one or several invoices.
1096
     * Warning: Take care that all invoices are owned by the same customer.
1097
     * Example of value for parameter arrayofamounts: {"1": "99.99", "2": "10"}
1098
     *
1099
     * @param array   $arrayofamounts     {@from body}  Array with id of invoices with amount to pay for each invoice
1100
     * @param string  $datepaye           {@from body}  Payment date        {@type timestamp}
1101
     * @param int     $paiementid         {@from body}  Payment mode Id {@min 1}
1102
     * @param string  $closepaidinvoices  {@from body}  Close paid invoices {@choice yes,no}
1103
     * @param int     $accountid          {@from body}  Account Id {@min 1}
1104
     * @param string  $num_paiement       {@from body}  Payment number (optional)
1105
     * @param string  $comment            {@from body}  Note (optional)
1106
     * @param string  $chqemetteur        {@from body}  Payment issuer (mandatory if paiementcode = 'CHQ')
1107
     * @param string  $chqbank            {@from body}  Issuer bank name (optional)
1108
     *
1109
     * @url     POST /paymentsdistributed
1110
     *
1111
     * @return int  Payment ID
1112
     * @throws 400
1113
     * @throws 401
1114
     * @throws 403
1115
     * @throws 404
1116
     */
1117
    function addPaymentDistributed($arrayofamounts, $datepaye, $paiementid, $closepaidinvoices, $accountid, $num_paiement='', $comment='', $chqemetteur='', $chqbank='')
1118
    {
1119
        global $conf;
1120
1121
        require_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php';
1122
1123
        if(! DolibarrApiAccess::$user->rights->facture->creer) {
1124
            throw new RestException(403);
1125
        }
1126
        foreach($arrayofamounts as $id => $amount) {
1127
        	if(empty($id)) {
1128
        		throw new RestException(400, 'Invoice ID is mandatory. Fill the invoice id and amount into arrayofamounts parameter. For example: {"1": "99.99", "2": "10"}');
1129
        	}
1130
        	if( ! DolibarrApi::_checkAccessToResource('facture',$id)) {
1131
        		throw new RestException(403, 'Access not allowed on invoice ID '.$id.' for login '.DolibarrApiAccess::$user->login);
1132
        	}
1133
        }
1134
1135
        if (! empty($conf->banque->enabled)) {
1136
        	if(empty($accountid)) {
1137
        		throw new RestException(400, 'Account ID is mandatory');
1138
        	}
1139
        }
1140
        if(empty($paiementid)) {
1141
        	throw new RestException(400, 'Paiement ID or Paiement Code is mandatory');
1142
        }
1143
1144
        $this->db->begin();
1145
1146
        $amounts = array();
1147
        $multicurrency_amounts = array();
1148
1149
        // Loop on each invoice to pay
1150
        foreach($arrayofamounts as $id => $amount)
1151
        {
1152
        	$result = $this->invoice->fetch($id);
1153
        	if( ! $result ) {
1154
        		$this->db->rollback();
1155
        		throw new RestException(404, 'Invoice ID '.$id.' not found');
1156
        	}
1157
1158
        	// Calculate amount to pay
1159
        	$totalpaye = $this->invoice->getSommePaiement();
1160
        	$totalcreditnotes = $this->invoice->getSumCreditNotesUsed();
1161
        	$totaldeposits = $this->invoice->getSumDepositsUsed();
1162
        	$resteapayer = price2num($this->invoice->total_ttc - $totalpaye - $totalcreditnotes - $totaldeposits, 'MT');
1163
        	if ($amount != 'remain')
1164
        	{
1165
        		if ($amount > $resteapayer)
1166
        		{
1167
        			$this->db->rollback();
1168
        			throw new RestException(400, 'Payment amount on invoice ID '.$id.' ('.$amount.') is higher than remain to pay ('.$resteapayer.')');
1169
        		}
1170
        		$resteapayer = $amount;
1171
        	}
1172
            // Clean parameters amount if payment is for a credit note
1173
            if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE) {
1174
                $resteapayer = price2num($resteapayer,'MT');
1175
                $amounts[$id] = -$resteapayer;
1176
                // Multicurrency
1177
                $newvalue = price2num($this->invoice->multicurrency_total_ttc,'MT');
1178
                $multicurrency_amounts[$id] = -$newvalue;
1179
            } else {
1180
                $resteapayer = price2num($resteapayer,'MT');
1181
                $amounts[$id] = $resteapayer;
1182
                // Multicurrency
1183
                $newvalue = price2num($this->invoice->multicurrency_total_ttc,'MT');
1184
                $multicurrency_amounts[$id] = $newvalue;
1185
            }
1186
        }
1187
1188
        // Creation of payment line
1189
        $paiement = new Paiement($this->db);
1190
        $paiement->datepaye     = $datepaye;
1191
        $paiement->amounts      = $amounts;                           // Array with all payments dispatching with invoice id
1192
        $paiement->multicurrency_amounts = $multicurrency_amounts;    // Array with all payments dispatching
1193
        $paiement->paiementid   = $paiementid;
1194
        $paiement->paiementcode = dol_getIdFromCode($this->db,$paiementid,'c_paiement','id','code',1);
0 ignored issues
show
Bug introduced by
The property paiementcode does not exist on Paiement. Did you mean paiementid?
Loading history...
1195
        $paiement->num_paiement = $num_paiement;
1196
        $paiement->note         = $comment;
1197
        $paiement_id = $paiement->create(DolibarrApiAccess::$user, ($closepaidinvoices=='yes'?1:0));    // This include closing invoices
1198
        if ($paiement_id < 0)
1199
        {
1200
            $this->db->rollback();
1201
            throw new RestException(400, 'Payment error : '.$paiement->error);
1202
        }
1203
        if (! empty($conf->banque->enabled)) {
1204
            $label='(CustomerInvoicePayment)';
1205
            if($paiement->paiementcode == 'CHQ' && empty($chqemetteur)) {
1206
                  throw new RestException(400, 'Emetteur is mandatory when payment code is '.$paiement->paiementcode);
1207
            }
1208
            if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE) $label='(CustomerInvoicePaymentBack)';  // Refund of a credit note
1209
            $result=$paiement->addPaymentToBank(DolibarrApiAccess::$user,'payment',$label,$accountid,$chqemetteur,$chqbank);
1210
            if ($result < 0)
1211
            {
1212
                $this->db->rollback();
1213
                throw new RestException(400, 'Add payment to bank error : '.$paiement->error);
1214
            }
1215
        }
1216
1217
        $this->db->commit();
1218
1219
        return $paiement_id;
1220
    }
1221
1222
    /**
1223
     * Clean sensible object datas
1224
     *
1225
     * @param   object  $object    Object to clean
1226
     * @return    array    Array of cleaned object properties
1227
     */
1228
    function _cleanObjectDatas($object)
1229
    {
1230
1231
        $object = parent::_cleanObjectDatas($object);
1232
1233
        unset($object->note);
1234
        unset($object->address);
1235
        unset($object->barcode_type);
1236
        unset($object->barcode_type_code);
1237
        unset($object->barcode_type_label);
1238
        unset($object->barcode_type_coder);
1239
1240
        return $object;
1241
    }
1242
1243
    /**
1244
     * Validate fields before create or update object
1245
     *
1246
     * @param array|null    $data       Datas to validate
1247
     * @return array
1248
     *
1249
     * @throws RestException
1250
     */
1251
    function _validate($data)
1252
    {
1253
        $invoice = array();
1254
        foreach (Invoices::$FIELDS as $field) {
1255
            if (!isset($data[$field])) {
1256
                throw new RestException(400, "$field field missing");
1257
            }
1258
            $invoice[$field] = $data[$field];
1259
        }
1260
        return $invoice;
1261
    }
1262
}
1263