dolibarr 21.0.0-alpha
fournisseur.orderline.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2003-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
6 * Copyright (C) 2010-2020 Juanjo Menent <jmenent@2byte.es>
7 * Copyright (C) 2010-2018 Philippe Grand <philippe.grand@atoo-net.com>
8 * Copyright (C) 2012-2015 Marcos García <marcosgdf@gmail.com>
9 * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
10 * Copyright (C) 2013 Cédric Salvador <csalvador@gpcsolutions.fr>
11 * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
12 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
13 * Copyright (C) 2018-2022 Ferran Marcet <fmarcet@2byte.es>
14 * Copyright (C) 2021 Josep Lluís Amador <joseplluis@lliuretic.cat>
15 * Copyright (C) 2022 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
16 * Copyright (C) 2024 Solution Libre SAS <contact@solution-libre.fr>
17 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
18 * Copyright (C) 2024 William Mead <william.mead@manchenumerique.fr>
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 3 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program. If not, see <https://www.gnu.org/licenses/>.
32 */
33
40require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
41require_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
42
47{
51 public $element = 'commande_fournisseurdet';
52
56 public $table_element = 'commande_fournisseurdet';
57
61 public $parent_element = 'commande_fournisseur';
62
66 public $fk_parent_attribute = 'fk_commande_fournisseur';
67
71 public $oldline;
72
77 public $fk_commande;
78
79 // From llx_commande_fournisseurdet
83 public $fk_parent_line;
84
88 public $fk_facture;
89
93 public $rang = 0;
94
98 public $special_code = 0;
99
104 public $pu_ht;
105
109 public $date_start;
110
114 public $date_end;
115
119 public $fk_fournprice;
120
124 public $packaging;
125
129 public $pa_ht;
130
131 // From llx_product_fournisseur_price
132
137 public $ref_supplier;
138
144 public $ref_fourn;
145
149 public $remise;
150
151
157 public function __construct($db)
158 {
159 $this->db = $db;
160 }
161
168 public function fetch($rowid)
169 {
170 $sql = 'SELECT cd.rowid, cd.fk_commande, cd.fk_product, cd.product_type, cd.description, cd.qty, cd.tva_tx, cd.special_code,';
171 $sql .= ' cd.localtax1_tx, cd.localtax2_tx, cd.localtax1_type, cd.localtax2_type, cd.ref as ref_supplier,';
172 $sql .= ' cd.remise, cd.remise_percent, cd.subprice,';
173 $sql .= ' cd.info_bits, cd.total_ht, cd.total_tva, cd.total_ttc,';
174 $sql .= ' cd.total_localtax1, cd.total_localtax2,';
175 $sql .= ' p.ref as product_ref, p.label as product_label, p.description as product_desc,';
176 $sql .= ' cd.date_start, cd.date_end, cd.fk_unit,';
177 $sql .= ' cd.multicurrency_subprice, cd.multicurrency_total_ht, cd.multicurrency_total_tva, cd.multicurrency_total_ttc,';
178 $sql .= ' c.fk_soc as socid';
179 $sql .= ' FROM '.$this->db->prefix().'commande_fournisseur as c, '.$this->db->prefix().'commande_fournisseurdet as cd';
180 $sql .= ' LEFT JOIN '.$this->db->prefix().'product as p ON cd.fk_product = p.rowid';
181 $sql .= ' WHERE cd.fk_commande = c.rowid AND cd.rowid = '.((int) $rowid);
182
183 $result = $this->db->query($sql);
184 if ($result) {
185 $objp = $this->db->fetch_object($result);
186
187 if (!empty($objp)) {
188 $this->rowid = $objp->rowid;
189 $this->id = $objp->rowid;
190 $this->fk_commande = $objp->fk_commande;
191 $this->desc = $objp->description;
192 $this->qty = $objp->qty;
193 $this->ref_fourn = $objp->ref_supplier;
194 $this->ref_supplier = $objp->ref_supplier;
195 $this->subprice = $objp->subprice;
196 $this->tva_tx = $objp->tva_tx;
197 $this->localtax1_tx = $objp->localtax1_tx;
198 $this->localtax2_tx = $objp->localtax2_tx;
199 $this->localtax1_type = $objp->localtax1_type;
200 $this->localtax2_type = $objp->localtax2_type;
201 $this->remise = $objp->remise;
202 $this->remise_percent = $objp->remise_percent;
203 $this->fk_product = $objp->fk_product;
204 $this->info_bits = $objp->info_bits;
205 $this->total_ht = $objp->total_ht;
206 $this->total_tva = $objp->total_tva;
207 $this->total_localtax1 = $objp->total_localtax1;
208 $this->total_localtax2 = $objp->total_localtax2;
209 $this->total_ttc = $objp->total_ttc;
210 $this->product_type = $objp->product_type;
211 $this->special_code = $objp->special_code;
212
213 $this->ref = $objp->product_ref;
214
215 $this->product_ref = $objp->product_ref;
216 $this->product_label = $objp->product_label;
217 $this->product_desc = $objp->product_desc;
218
219 if (getDolGlobalInt('PRODUCT_USE_SUPPLIER_PACKAGING')) {
220 // TODO We should not fetch this properties into the fetch_lines. This is NOT properties of a line.
221 // Move this into another method and call it when required.
222
223 // Take better packaging for $objp->qty (first supplier ref quantity <= $objp->qty)
224 $sqlsearchpackage = 'SELECT rowid, packaging FROM '.$this->db->prefix()."product_fournisseur_price";
225 $sqlsearchpackage .= ' WHERE entity IN ('.getEntity('product_fournisseur_price').")";
226 $sqlsearchpackage .= " AND fk_product = ".((int) $objp->fk_product);
227 $sqlsearchpackage .= " AND ref_fourn = '".$this->db->escape($objp->ref_supplier)."'";
228 $sqlsearchpackage .= " AND quantity <= ".((float) $objp->qty); // required to be qualified
229 $sqlsearchpackage .= " AND (packaging IS NULL OR packaging = 0 OR packaging <= ".((float) $objp->qty).")"; // required to be qualified
230 $sqlsearchpackage .= " AND fk_soc = ".((int) $objp->socid);
231 $sqlsearchpackage .= " ORDER BY packaging ASC"; // Take the smaller package first
232 $sqlsearchpackage .= " LIMIT 1";
233
234 $resqlsearchpackage = $this->db->query($sqlsearchpackage);
235 if ($resqlsearchpackage) {
236 $objsearchpackage = $this->db->fetch_object($resqlsearchpackage);
237 if ($objsearchpackage) {
238 $this->fk_fournprice = $objsearchpackage->rowid;
239 $this->packaging = $objsearchpackage->packaging;
240 }
241 } else {
242 $this->error = $this->db->lasterror();
243 return -1;
244 }
245 }
246
247 $this->date_start = $this->db->jdate($objp->date_start);
248 $this->date_end = $this->db->jdate($objp->date_end);
249 $this->fk_unit = $objp->fk_unit;
250
251 $this->multicurrency_subprice = $objp->multicurrency_subprice;
252 $this->multicurrency_total_ht = $objp->multicurrency_total_ht;
253 $this->multicurrency_total_tva = $objp->multicurrency_total_tva;
254 $this->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
255
256 $this->fetch_optionals();
257
258 $this->db->free($result);
259 return 1;
260 } else {
261 $this->error = 'Supplier order line with id='.$rowid.' not found';
262 dol_syslog(get_class($this)."::fetch Error ".$this->error, LOG_ERR);
263 return 0;
264 }
265 } else {
266 dol_print_error($this->db);
267 return -1;
268 }
269 }
270
277 public function insert($notrigger = 0)
278 {
279 global $conf, $user;
280
281 $error = 0;
282
283 dol_syslog(get_class($this)."::insert rang=".$this->rang);
284
285 // Clean parameters
286 if (empty($this->tva_tx)) {
287 $this->tva_tx = 0;
288 }
289 if (empty($this->localtax1_tx)) {
290 $this->localtax1_tx = 0;
291 }
292 if (empty($this->localtax2_tx)) {
293 $this->localtax2_tx = 0;
294 }
295 if (empty($this->localtax1_type)) {
296 $this->localtax1_type = '0';
297 }
298 if (empty($this->localtax2_type)) {
299 $this->localtax2_type = '0';
300 }
301 if (empty($this->total_localtax1)) {
302 $this->total_localtax1 = 0;
303 }
304 if (empty($this->total_localtax2)) {
305 $this->total_localtax2 = 0;
306 }
307 if (empty($this->rang)) {
308 $this->rang = 0;
309 }
310 if (empty($this->remise_percent)) {
311 $this->remise_percent = 0;
312 }
313 if (empty($this->info_bits)) {
314 $this->info_bits = 0;
315 }
316 if (empty($this->special_code)) {
317 $this->special_code = 0;
318 }
319 if (empty($this->fk_parent_line)) {
320 $this->fk_parent_line = 0;
321 }
322 if (empty($this->pa_ht)) {
323 $this->pa_ht = 0;
324 }
325
326 // Multicurrency
327 if (!empty($this->multicurrency_code)) {
328 list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code);
329 }
330 if (empty($this->fk_multicurrency)) {
331 $this->multicurrency_code = $conf->currency;
332 $this->fk_multicurrency = 0;
333 $this->multicurrency_tx = 1;
334 }
335
336 // Check parameters
337 if ($this->product_type < 0) {
338 return -1;
339 }
340
341 $this->db->begin();
342
343 // Insertion dans base de la ligne
344 $sql = 'INSERT INTO '.$this->db->prefix().$this->table_element;
345 $sql .= " (fk_commande, label, description, date_start, date_end,";
346 $sql .= " fk_product, product_type, special_code, rang,";
347 $sql .= " qty, vat_src_code, tva_tx, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, remise_percent, subprice, ref,";
348 $sql .= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc, fk_unit,";
349 $sql .= " fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc,";
350 $sql .= " fk_parent_line)";
351 $sql .= " VALUES (".$this->fk_commande.", '".$this->db->escape($this->label)."','".$this->db->escape($this->desc)."',";
352 $sql .= " ".($this->date_start ? "'".$this->db->idate($this->date_start)."'" : "null").",";
353 $sql .= " ".($this->date_end ? "'".$this->db->idate($this->date_end)."'" : "null").",";
354 if ($this->fk_product) {
355 $sql .= $this->fk_product.",";
356 } else {
357 $sql .= "null,";
358 }
359 $sql .= "'".$this->db->escape($this->product_type)."',";
360 $sql .= (int) $this->special_code . ",";
361 $sql .= "'".$this->db->escape($this->rang)."',";
362 $sql .= "'".$this->db->escape($this->qty)."', ";
363 $sql .= " ".(empty($this->vat_src_code) ? "''" : "'".$this->db->escape($this->vat_src_code)."'").",";
364 $sql .= " ".price2num($this->tva_tx).", ";
365 $sql .= " ".price2num($this->localtax1_tx).",";
366 $sql .= " ".price2num($this->localtax2_tx).",";
367 $sql .= " '".$this->db->escape($this->localtax1_type)."',";
368 $sql .= " '".$this->db->escape($this->localtax2_type)."',";
369 $sql .= " ".((float) $this->remise_percent).", ".price2num($this->subprice, 'MU').", '".$this->db->escape($this->ref_supplier)."',";
370 $sql .= " ".price2num($this->total_ht).",";
371 $sql .= " ".price2num($this->total_tva).",";
372 $sql .= " ".price2num($this->total_localtax1).",";
373 $sql .= " ".price2num($this->total_localtax2).",";
374 $sql .= " ".price2num($this->total_ttc).",";
375 $sql .= ($this->fk_unit ? "'".$this->db->escape($this->fk_unit)."'" : "null");
376 $sql .= ", ".($this->fk_multicurrency ? ((int) $this->fk_multicurrency) : "null");
377 $sql .= ", '".$this->db->escape($this->multicurrency_code)."'";
378 $sql .= ", ".($this->multicurrency_subprice ? price2num($this->multicurrency_subprice) : '0');
379 $sql .= ", ".($this->multicurrency_total_ht ? price2num($this->multicurrency_total_ht) : '0');
380 $sql .= ", ".($this->multicurrency_total_tva ? price2num($this->multicurrency_total_tva) : '0');
381 $sql .= ", ".($this->multicurrency_total_ttc ? price2num($this->multicurrency_total_ttc) : '0');
382 $sql .= ", ".((!empty($this->fk_parent_line) && $this->fk_parent_line > 0) ? $this->fk_parent_line : 'null');
383 $sql .= ")";
384
385 dol_syslog(get_class($this)."::insert", LOG_DEBUG);
386 $resql = $this->db->query($sql);
387 if ($resql) {
388 $this->id = $this->db->last_insert_id($this->db->prefix().$this->table_element);
389 $this->rowid = $this->id;
390
391 if (!$error) {
392 $result = $this->insertExtraFields();
393 if ($result < 0) {
394 $error++;
395 }
396 }
397
398 if (!$error && !$notrigger) {
399 // Call trigger
400 $result = $this->call_trigger('LINEORDER_SUPPLIER_CREATE', $user);
401 if ($result < 0) {
402 $error++;
403 }
404 // End call triggers
405 }
406
407 if (!$error) {
408 $this->db->commit();
409 return 1;
410 }
411
412 foreach ($this->errors as $errmsg) {
413 dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
414 $this->errors[] = ($this->errors ? ', '.$errmsg : $errmsg);
415 }
416 $this->db->rollback();
417 return -1 * $error;
418 } else {
419 $this->errors[] = $this->db->error();
420 $this->db->rollback();
421 return -2;
422 }
423 }
430 public function update($notrigger = 0)
431 {
432 global $user;
433
434 $error = 0;
435
436 $this->db->begin();
437
438 $sql = "UPDATE ".$this->db->prefix().$this->table_element." SET";
439 $sql .= " description='".$this->db->escape($this->desc)."'";
440 $sql .= ", ref='".$this->db->escape($this->ref_supplier)."'";
441 $sql .= ", subprice='".price2num($this->subprice)."'";
442 //$sql.= ",remise='".price2num($remise)."'";
443 $sql .= ", remise_percent='".price2num($this->remise_percent)."'";
444
445 $sql .= ", vat_src_code = '".(empty($this->vat_src_code) ? '' : $this->vat_src_code)."'";
446 $sql .= ", tva_tx='".price2num($this->tva_tx)."'";
447 $sql .= ", localtax1_tx='".price2num($this->localtax1_tx)."'";
448 $sql .= ", localtax2_tx='".price2num($this->localtax2_tx)."'";
449 $sql .= ", localtax1_type='".$this->db->escape($this->localtax1_type)."'";
450 $sql .= ", localtax2_type='".$this->db->escape($this->localtax2_type)."'";
451 $sql .= ", qty='".price2num($this->qty)."'";
452 $sql .= ", date_start=".(!empty($this->date_start) ? "'".$this->db->idate($this->date_start)."'" : "null");
453 $sql .= ", date_end=".(!empty($this->date_end) ? "'".$this->db->idate($this->date_end)."'" : "null");
454 $sql .= ", info_bits='".$this->db->escape($this->info_bits)."'";
455 $sql .= ", total_ht='".price2num($this->total_ht)."'";
456 $sql .= ", total_tva='".price2num($this->total_tva)."'";
457 $sql .= ", total_localtax1='".price2num($this->total_localtax1)."'";
458 $sql .= ", total_localtax2='".price2num($this->total_localtax2)."'";
459 $sql .= ", total_ttc='".price2num($this->total_ttc)."'";
460 $sql .= ", product_type=".$this->product_type;
461 $sql .= ", special_code=".(!empty($this->special_code) ? $this->special_code : 0);
462 $sql .= ($this->fk_unit ? ", fk_unit='".$this->db->escape($this->fk_unit)."'" : ", fk_unit=null");
463
464 // Multicurrency
465 $sql .= ", multicurrency_subprice=".price2num($this->multicurrency_subprice);
466 $sql .= ", multicurrency_total_ht=".price2num($this->multicurrency_total_ht);
467 $sql .= ", multicurrency_total_tva=".price2num($this->multicurrency_total_tva);
468 $sql .= ", multicurrency_total_ttc=".price2num($this->multicurrency_total_ttc);
469
470 $sql .= " WHERE rowid = ".((int) $this->id);
471
472 dol_syslog(get_class($this)."::updateline", LOG_DEBUG);
473 $resql = $this->db->query($sql);
474 if ($resql) {
475 if (!$error) {
476 $result = $this->insertExtraFields();
477 if ($result < 0) {
478 $error++;
479 }
480 }
481
482 if (!$error && !$notrigger) {
483 // Call trigger
484 $result = $this->call_trigger('LINEORDER_SUPPLIER_MODIFY', $user);
485 if ($result < 0) {
486 $this->db->rollback();
487 return -1;
488 }
489 // End call triggers
490 }
491
492 if (!$error) {
493 $this->db->commit();
494 return 1;
495 } else {
496 $this->db->rollback();
497 return -1;
498 }
499 } else {
500 $this->error = $this->db->lasterror();
501 $this->db->rollback();
502 return -1;
503 }
504 }
505
513 public function delete($user, $notrigger = 0)
514 {
515 if (empty($user)) {
516 global $user;
517 }
518
519 $error = 0;
520
521 $this->db->begin();
522
523 // extrafields
524 $result = $this->deleteExtraFields();
525 if ($result < 0) {
526 $this->db->rollback();
527 return -1;
528 }
529
530 $sql1 = 'UPDATE '.$this->db->prefix()."commandedet SET fk_commandefourndet = NULL WHERE fk_commandefourndet = ".((int) $this->id);
531 $resql = $this->db->query($sql1);
532 if (!$resql) {
533 $this->db->rollback();
534 return -1;
535 }
536
537 $sql2 = 'DELETE FROM '.$this->db->prefix()."commande_fournisseurdet WHERE rowid = ".((int) $this->id);
538
539 dol_syslog(__METHOD__, LOG_DEBUG);
540 $resql = $this->db->query($sql2);
541 if ($resql) {
542 if (!$notrigger) {
543 // Call trigger
544 $result = $this->call_trigger('LINEORDER_SUPPLIER_DELETE', $user);
545 if ($result < 0) {
546 $error++;
547 }
548 // End call triggers
549 }
550
551 if (!$error) {
552 $this->db->commit();
553 return 1;
554 }
555
556 foreach ($this->errors as $errmsg) {
557 dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
558 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
559 }
560 $this->db->rollback();
561 return -1 * $error;
562 } else {
563 $this->error = $this->db->lasterror();
564 return -1;
565 }
566 }
567}
$object ref
Definition info.php:79
Class to manage line orders.
update($notrigger=0)
Update the line object into db.
insert($notrigger=0)
Insert line into database.
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
deleteExtraFields()
Delete all extra fields values for the current object.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Superclass for orders classes.
static getIdAndTxFromCode($dbs, $code, $date_document='')
Get id and rate of currency from code.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.