dolibarr  9.0.0
fournisseur.facture.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2002-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2004 Christophe Combelles <ccomb@free.fr>
5  * Copyright (C) 2005 Marc Barilley <marc@ocebo.com>
6  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
7  * Copyright (C) 2010-2017 Juanjo Menent <jmenent@2byte.es>
8  * Copyright (C) 2013-2018 Philippe Grand <philippe.grand@atoo-net.com>
9  * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
10  * Copyright (C) 2014-2016 Marcos García <marcosgdf@gmail.com>
11  * Copyright (C) 2015 Bahfir Abbes <bafbes@gmail.com>
12  * Copyright (C) 2015 Ferran Marcet <fmarcet@2byte.es>
13  * Copyright (C) 2016 Alexandre Spangaro <aspangaro@zendsi.com>
14  * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
15  * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 3 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program. If not, see <http://www.gnu.org/licenses/>.
29  */
30 
37 include_once DOL_DOCUMENT_ROOT.'/core/class/commoninvoice.class.php';
38 require_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
39 
44 {
48  public $element='invoice_supplier';
49 
53  public $table_element='facture_fourn';
54 
58  public $table_element_line='facture_fourn_det';
59 
63  public $fk_element='fk_facture_fourn';
64 
65  public $picto='bill';
66 
71  public $ismultientitymanaged = 1;
72 
77  public $restrictiononfksoc = 1;
78 
82  protected $table_ref_field = 'ref';
83 
87  public $rowid;
88 
92  public $ref;
93 
94  public $product_ref;
95  public $ref_supplier;
96  public $socid;
97  //Check constants for types
98  public $type = self::TYPE_STANDARD;
99 
105  public $statut;
106 
112  public $paye;
113 
114  public $author;
115  public $libelle;
116  public $datec; // Creation date
117  public $tms; // Last update date
118  public $date; // Invoice date
119  public $date_echeance; // Max payment date
120  public $amount=0;
121  public $remise=0;
122  public $tva=0;
123  public $localtax1;
124  public $localtax2;
125  public $total_ht=0;
126  public $total_tva=0;
127  public $total_localtax1=0;
128  public $total_localtax2=0;
129  public $total_ttc=0;
130 
135  public $note;
136 
137  public $note_private;
138  public $note_public;
139  public $propalid;
140  public $cond_reglement_id;
141  public $cond_reglement_code;
142 
146  public $fk_account;
147 
148  public $mode_reglement_id;
149  public $mode_reglement_code;
150 
155  public $lines = array();
156 
160  public $fournisseur;
161 
165  public $fk_incoterms;
166 
167  public $location_incoterms;
168  public $libelle_incoterms; //Used into tooltip
169 
170  public $extraparams=array();
171 
172  // Multicurrency
176  public $fk_multicurrency;
177 
178  public $multicurrency_code;
179  public $multicurrency_tx;
180  public $multicurrency_total_ht;
181  public $multicurrency_total_tva;
182  public $multicurrency_total_ttc;
184 
187  public $fk_facture_source;
188 
192  const TYPE_STANDARD = 0;
193 
197  const TYPE_REPLACEMENT = 1;
198 
202  const TYPE_CREDIT_NOTE = 2;
203 
207  const TYPE_DEPOSIT = 3;
208 
212  const STATUS_DRAFT = 0;
213 
217  const STATUS_VALIDATED = 1;
218 
226  const STATUS_CLOSED = 2;
227 
235  const STATUS_ABANDONED = 3;
236 
237  const CLOSECODE_DISCOUNTVAT = 'discount_vat';
238  const CLOSECODE_BADCREDIT = 'badsupplier';
239  const CLOSECODE_ABANDONED = 'abandon';
240  const CLOSECODE_REPLACED = 'replaced';
241 
247  public function __construct($db)
248  {
249  $this->db = $db;
250 
251  $this->products = array();
252  }
253 
260  public function create($user)
261  {
262  global $langs,$conf,$hookmanager;
263 
264  $error=0;
265  $now=dol_now();
266 
267  // Clean parameters
268  if (isset($this->ref_supplier)) $this->ref_supplier=trim($this->ref_supplier);
269  if (empty($this->type)) $this->type = self::TYPE_STANDARD;
270  if (empty($this->date)) $this->date=$now;
271 
272  $socid = $this->socid;
273  $ref_supplier = $this->ref_supplier;
274  $amount = $this->amount;
275  $remise = $this->remise;
276 
277  // Multicurrency (test on $this->multicurrency_tx because we should take the default rate only if not using origin rate)
278  if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) list($this->fk_multicurrency,$this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code);
279  else $this->fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $this->multicurrency_code);
280  if (empty($this->fk_multicurrency))
281  {
282  $this->multicurrency_code = $conf->currency;
283  $this->fk_multicurrency = 0;
284  $this->multicurrency_tx = 1;
285  }
286 
287  $this->db->begin();
288 
289  if (! $remise) $remise = 0 ;
290  $totalht = ($amount - $remise);
291 
292  $sql = "INSERT INTO ".MAIN_DB_PREFIX."facture_fourn (";
293  $sql.= "ref";
294  $sql.= ", ref_supplier";
295  $sql.= ", entity";
296  $sql.= ", type";
297  $sql.= ", libelle";
298  $sql.= ", fk_soc";
299  $sql.= ", datec";
300  $sql.= ", datef";
301  $sql.= ", fk_projet";
302  $sql.= ", fk_cond_reglement";
303  $sql.= ", fk_mode_reglement";
304  $sql.= ", fk_account";
305  $sql.= ", note_private";
306  $sql.= ", note_public";
307  $sql.= ", fk_user_author";
308  $sql.= ", date_lim_reglement";
309  $sql.= ", fk_incoterms, location_incoterms";
310  $sql.= ", fk_multicurrency";
311  $sql.= ", multicurrency_code";
312  $sql.= ", multicurrency_tx";
313  $sql.= ", fk_facture_source";
314  $sql.= ")";
315  $sql.= " VALUES (";
316  $sql.= "'(PROV)'";
317  $sql.= ", '".$this->db->escape($this->ref_supplier)."'";
318  $sql.= ", ".$conf->entity;
319  $sql.= ", '".$this->db->escape($this->type)."'";
320  $sql.= ", '".$this->db->escape($this->libelle)."'";
321  $sql.= ", ".$this->socid;
322  $sql.= ", '".$this->db->idate($now)."'";
323  $sql.= ", '".$this->db->idate($this->date)."'";
324  $sql.= ", ".($this->fk_project > 0 ? $this->fk_project:"null");
325  $sql.= ", ".($this->cond_reglement_id > 0 ? $this->cond_reglement_id:"null");
326  $sql.= ", ".($this->mode_reglement_id > 0 ? $this->mode_reglement_id:"null");
327  $sql.= ", ".($this->fk_account>0?$this->fk_account:'NULL');
328  $sql.= ", '".$this->db->escape($this->note_private)."'";
329  $sql.= ", '".$this->db->escape($this->note_public)."'";
330  $sql.= ", ".$user->id.",";
331  $sql.= $this->date_echeance!=''?"'".$this->db->idate($this->date_echeance)."'":"null";
332  $sql.= ", ".(int) $this->fk_incoterms;
333  $sql.= ", '".$this->db->escape($this->location_incoterms)."'";
334  $sql.= ", ".(int) $this->fk_multicurrency;
335  $sql.= ", '".$this->db->escape($this->multicurrency_code)."'";
336  $sql.= ", ".(double) $this->multicurrency_tx;
337  $sql.= ", ".(isset($this->fk_facture_source)?$this->fk_facture_source:"NULL");
338  $sql.= ")";
339 
340  dol_syslog(get_class($this)."::create", LOG_DEBUG);
341  $resql=$this->db->query($sql);
342  if ($resql)
343  {
344  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'facture_fourn');
345 
346  // Update ref with new one
347  $this->ref='(PROV'.$this->id.')';
348  $sql = 'UPDATE '.MAIN_DB_PREFIX."facture_fourn SET ref='".$this->db->escape($this->ref)."' WHERE rowid=".$this->id;
349 
350  dol_syslog(get_class($this)."::create", LOG_DEBUG);
351  $resql=$this->db->query($sql);
352  if (! $resql) $error++;
353 
354  if (! empty($this->linkedObjectsIds) && empty($this->linked_objects)) // To use new linkedObjectsIds instead of old linked_objects
355  {
356  $this->linked_objects = $this->linkedObjectsIds; // TODO Replace linked_objects with linkedObjectsIds
357  }
358 
359  // Add object linked
360  if (! $error && $this->id && is_array($this->linked_objects) && ! empty($this->linked_objects))
361  {
362  foreach($this->linked_objects as $origin => $tmp_origin_id)
363  {
364  if (is_array($tmp_origin_id)) // New behaviour, if linked_object can have several links per type, so is something like array('contract'=>array(id1, id2, ...))
365  {
366  foreach($tmp_origin_id as $origin_id)
367  {
368  $ret = $this->add_object_linked($origin, $origin_id);
369  if (! $ret)
370  {
371  dol_print_error($this->db);
372  $error++;
373  }
374  }
375  }
376  else // Old behaviour, if linked_object has only one link per type, so is something like array('contract'=>id1))
377  {
378  $origin_id = $tmp_origin_id;
379  $ret = $this->add_object_linked($origin, $origin_id);
380  if (! $ret)
381  {
382  dol_print_error($this->db);
383  $error++;
384  }
385  }
386  }
387  }
388 
389  // Add linked object (deprecated, use ->linkedObjectsIds instead)
390  if (! $error && $this->id && ! empty($this->origin) && ! empty($this->origin_id))
391  {
392  $ret = $this->add_object_linked();
393  if (! $ret)
394  {
395  dol_print_error($this->db);
396  $error++;
397  }
398  }
399 
400  if (count($this->lines) && is_object($this->lines[0])) // If this->lines is array of InvoiceLines (preferred mode)
401  {
402  dol_syslog("There is ".count($this->lines)." lines that are invoice lines objects");
403  foreach ($this->lines as $i => $val)
404  {
405  $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'facture_fourn_det (fk_facture_fourn, special_code)';
406  $sql .= ' VALUES ('.$this->id.','.intval($this->lines[$i]->special_code).')';
407 
408  $resql_insert=$this->db->query($sql);
409  if ($resql_insert)
410  {
411  $idligne = $this->db->last_insert_id(MAIN_DB_PREFIX.'facture_fourn_det');
412 
413  $this->updateline(
414  $idligne,
415  $this->lines[$i]->description,
416  $this->lines[$i]->pu_ht,
417  $this->lines[$i]->tva_tx,
418  $this->lines[$i]->localtax1_tx,
419  $this->lines[$i]->localtax2_tx,
420  $this->lines[$i]->qty,
421  $this->lines[$i]->fk_product,
422  'HT',
423  (! empty($this->lines[$i]->info_bits)?$this->lines[$i]->info_bits:''),
424  $this->lines[$i]->product_type,
425  $this->lines[$i]->remise_percent,
426  false,
427  $this->lines[$i]->date_start,
428  $this->lines[$i]->date_end,
429  $this->lines[$i]->array_options,
430  $this->lines[$i]->fk_unit,
431  $this->lines[$i]->pu_ht_devise
432  );
433  }
434  else
435  {
436  $this->error=$this->db->lasterror();
437  $this->db->rollback();
438  return -5;
439  }
440  }
441  }
442  else // If this->lines is an array of invoice line arrays
443  {
444  dol_syslog("There is ".count($this->lines)." lines that are array lines");
445  foreach ($this->lines as $i => $val)
446  {
447  $line = $this->lines[$i];
448 
449  // Test and convert into object this->lines[$i]. When coming from REST API, we may still have an array
450  //if (! is_object($line)) $line=json_decode(json_encode($line), false); // convert recursively array into object.
451  if (! is_object($line)) $line = (object) $line;
452 
453  $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'facture_fourn_det (fk_facture_fourn, special_code)';
454  $sql .= ' VALUES ('.$this->id.','.intval($this->lines[$i]->special_code).')';
455 
456  $resql_insert=$this->db->query($sql);
457  if ($resql_insert)
458  {
459  $idligne = $this->db->last_insert_id(MAIN_DB_PREFIX.'facture_fourn_det');
460 
461  $this->updateline(
462  $idligne,
463  $line->description,
464  $line->pu_ht,
465  $line->tva_tx,
466  $line->localtax1_tx,
467  $line->localtax2_tx,
468  $line->qty,
469  $line->fk_product,
470  'HT',
471  (! empty($line->info_bits)?$line->info_bits:''),
472  $line->product_type
473  );
474  }
475  else
476  {
477  $this->error=$this->db->lasterror();
478  $this->db->rollback();
479  return -5;
480  }
481  }
482  }
483 
484  // Update total price
485  $result=$this->update_price();
486  if ($result > 0)
487  {
488  $action='create';
489 
490  // Actions on extra fields
491  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
492  {
493  $result=$this->insertExtraFields(); // This also set $this->error or $this->errors if errors are found
494  if ($result < 0)
495  {
496  $error++;
497  }
498  }
499 
500  if (! $error)
501  {
502  // Call trigger
503  $result=$this->call_trigger('BILL_SUPPLIER_CREATE',$user);
504  if ($result < 0) $error++;
505  // End call triggers
506  }
507 
508  if (! $error)
509  {
510  $this->db->commit();
511  return $this->id;
512  }
513  else
514  {
515  $this->db->rollback();
516  return -4;
517  }
518  }
519  else
520  {
521  $this->error=$langs->trans('FailedToUpdatePrice');
522  $this->db->rollback();
523  return -3;
524  }
525  }
526  else
527  {
528  if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS')
529  {
530  $this->error=$langs->trans('ErrorRefAlreadyExists');
531  $this->db->rollback();
532  return -1;
533  }
534  else
535  {
536  $this->error=$this->db->lasterror();
537  $this->db->rollback();
538  return -2;
539  }
540  }
541  }
542 
550  public function fetch($id='',$ref='')
551  {
552  global $langs;
553 
554  $sql = "SELECT";
555  $sql.= " t.rowid,";
556  $sql.= " t.ref,";
557  $sql.= " t.ref_supplier,";
558  $sql.= " t.entity,";
559  $sql.= " t.type,";
560  $sql.= " t.fk_soc,";
561  $sql.= " t.datec,";
562  $sql.= " t.datef,";
563  $sql.= " t.tms,";
564  $sql.= " t.libelle,";
565  $sql.= " t.paye,";
566  $sql.= " t.amount,";
567  $sql.= " t.remise,";
568  $sql.= " t.close_code,";
569  $sql.= " t.close_note,";
570  $sql.= " t.tva,";
571  $sql.= " t.localtax1,";
572  $sql.= " t.localtax2,";
573  //$sql.= " t.total,";
574  $sql.= " t.total_ht,";
575  $sql.= " t.total_tva,";
576  $sql.= " t.total_ttc,";
577  $sql.= " t.fk_statut,";
578  $sql.= " t.fk_user_author,";
579  $sql.= " t.fk_user_valid,";
580  $sql.= " t.fk_facture_source,";
581  $sql.= " t.fk_projet,";
582  $sql.= " t.fk_cond_reglement,";
583  $sql.= " t.fk_account,";
584  $sql.= " t.fk_mode_reglement,";
585  $sql.= " t.date_lim_reglement,";
586  $sql.= " t.note_private,";
587  $sql.= " t.note_public,";
588  $sql.= " t.model_pdf,";
589  $sql.= " t.import_key,";
590  $sql.= " t.extraparams,";
591  $sql.= " cr.code as cond_reglement_code, cr.libelle as cond_reglement_libelle,";
592  $sql.= " p.code as mode_reglement_code, p.libelle as mode_reglement_libelle,";
593  $sql.= ' s.nom as socnom, s.rowid as socid,';
594  $sql.= ' t.fk_incoterms, t.location_incoterms,';
595  $sql.= " i.libelle as libelle_incoterms,";
596  $sql.= ' t.fk_multicurrency, t.multicurrency_code, t.multicurrency_tx, t.multicurrency_total_ht, t.multicurrency_total_tva, t.multicurrency_total_ttc';
597  $sql.= ' FROM '.MAIN_DB_PREFIX.'facture_fourn as t';
598  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON (t.fk_soc = s.rowid)";
599  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_payment_term as cr ON t.fk_cond_reglement = cr.rowid";
600  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as p ON t.fk_mode_reglement = p.id";
601  $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_incoterms as i ON t.fk_incoterms = i.rowid';
602  if ($id) $sql.= " WHERE t.rowid=".$id;
603  if ($ref) $sql.= " WHERE t.ref='".$this->db->escape($ref)."'";
604 
605  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
606  $resql=$this->db->query($sql);
607  if ($resql)
608  {
609  if ($this->db->num_rows($resql))
610  {
611  $obj = $this->db->fetch_object($resql);
612 
613  $this->id = $obj->rowid;
614  $this->ref = $obj->ref?$obj->ref:$obj->rowid; // We take rowid if ref is empty for backward compatibility
615 
616  $this->ref_supplier = $obj->ref_supplier;
617  $this->entity = $obj->entity;
618  $this->type = empty($obj->type)? self::TYPE_STANDARD:$obj->type;
619  $this->fk_soc = $obj->fk_soc;
620  $this->datec = $this->db->jdate($obj->datec);
621  $this->date = $this->db->jdate($obj->datef);
622  $this->datep = $this->db->jdate($obj->datef);
623  $this->tms = $this->db->jdate($obj->tms);
624  $this->libelle = $obj->libelle;
625  $this->label = $obj->libelle;
626  $this->paye = $obj->paye;
627  $this->amount = $obj->amount;
628  $this->remise = $obj->remise;
629  $this->close_code = $obj->close_code;
630  $this->close_note = $obj->close_note;
631  $this->tva = $obj->tva;
632  $this->total_localtax1 = $obj->localtax1;
633  $this->total_localtax2 = $obj->localtax2;
634  //$this->total = $obj->total;
635  $this->total_ht = $obj->total_ht;
636  $this->total_tva = $obj->total_tva;
637  $this->total_ttc = $obj->total_ttc;
638  $this->fk_statut = $obj->fk_statut;
639  $this->statut = $obj->fk_statut;
640  $this->fk_user_author = $obj->fk_user_author;
641  $this->author = $obj->fk_user_author;
642  $this->fk_user_valid = $obj->fk_user_valid;
643  $this->fk_facture_source = $obj->fk_facture_source;
644  $this->fk_project = $obj->fk_projet;
645  $this->cond_reglement_id = $obj->fk_cond_reglement;
646  $this->cond_reglement_code = $obj->cond_reglement_code;
647  $this->cond_reglement = $obj->cond_reglement_libelle;
648  $this->cond_reglement_doc = $obj->cond_reglement_libelle;
649  $this->fk_account = $obj->fk_account;
650  $this->mode_reglement_id = $obj->fk_mode_reglement;
651  $this->mode_reglement_code = $obj->mode_reglement_code;
652  $this->mode_reglement = $obj->mode_reglement_libelle;
653  $this->date_echeance = $this->db->jdate($obj->date_lim_reglement);
654  $this->note = $obj->note_private; // deprecated
655  $this->note_private = $obj->note_private;
656  $this->note_public = $obj->note_public;
657  $this->model_pdf = $obj->model_pdf;
658  $this->modelpdf = $obj->model_pdf;
659  $this->import_key = $obj->import_key;
660 
661  //Incoterms
662  $this->fk_incoterms = $obj->fk_incoterms;
663  $this->location_incoterms = $obj->location_incoterms;
664  $this->libelle_incoterms = $obj->libelle_incoterms;
665 
666  // Multicurrency
667  $this->fk_multicurrency = $obj->fk_multicurrency;
668  $this->multicurrency_code = $obj->multicurrency_code;
669  $this->multicurrency_tx = $obj->multicurrency_tx;
670  $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
671  $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
672  $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
673 
674  $this->extraparams = (array) json_decode($obj->extraparams, true);
675 
676  $this->socid = $obj->socid;
677  $this->socnom = $obj->socnom;
678 
679  // Retreive all extrafield
680  // fetch optionals attributes and labels
681  $this->fetch_optionals();
682 
683  if ($this->statut == self::STATUS_DRAFT) $this->brouillon = 1;
684 
685  $result=$this->fetch_lines();
686  if ($result < 0)
687  {
688  $this->error=$this->db->lasterror();
689  return -3;
690  }
691  }
692  else
693  {
694  $this->error='Bill with id '.$id.' not found';
695  dol_syslog(get_class($this).'::fetch '.$this->error);
696  return 0;
697  }
698 
699  $this->db->free($resql);
700  return 1;
701  }
702  else
703  {
704  $this->error="Error ".$this->db->lasterror();
705  return -1;
706  }
707  }
708 
709 
710  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
716  function fetch_lines()
717  {
718  // phpcs:enable
719  $this->lines = array();
720 
721  $sql = 'SELECT f.rowid, f.ref as ref_supplier, f.description, f.date_start, f.date_end, f.pu_ht, f.pu_ttc, f.qty, f.remise_percent, f.vat_src_code, f.tva_tx';
722  $sql.= ', f.localtax1_tx, f.localtax2_tx, f.localtax1_type, f.localtax2_type, f.total_localtax1, f.total_localtax2, f.fk_facture_fourn ';
723  $sql.= ', f.total_ht, f.tva as total_tva, f.total_ttc, f.fk_product, f.product_type, f.info_bits, f.rang, f.special_code, f.fk_parent_line, f.fk_unit';
724  $sql.= ', p.rowid as product_id, p.ref as product_ref, p.label as label, p.description as product_desc';
725  $sql.= ', f.fk_multicurrency, f.multicurrency_code, f.multicurrency_subprice, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc';
726  $sql.= ' FROM '.MAIN_DB_PREFIX.'facture_fourn_det as f';
727  $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON f.fk_product = p.rowid';
728  $sql.= ' WHERE fk_facture_fourn='.$this->id;
729  $sql.= ' ORDER BY f.rang, f.rowid';
730 
731  dol_syslog(get_class($this)."::fetch_lines", LOG_DEBUG);
732  $resql_rows = $this->db->query($sql);
733  if ($resql_rows)
734  {
735  $num_rows = $this->db->num_rows($resql_rows);
736  if ($num_rows)
737  {
738  $i = 0;
739  while ($i < $num_rows)
740  {
741  $obj = $this->db->fetch_object($resql_rows);
742 
743  $line = new SupplierInvoiceLine($this->db);
744 
745  $line->id = $obj->rowid;
746  $line->rowid = $obj->rowid;
747  $line->description = $obj->description;
748  $line->date_start = $obj->date_start;
749  $line->date_end = $obj->date_end;
750 
751  $line->product_ref = $obj->product_ref;
752  $line->ref = $obj->product_ref;
753  $line->ref_supplier = $obj->ref_supplier;
754  $line->libelle = $obj->label;
755  $line->label = $obj->label;
756  $line->product_desc = $obj->product_desc;
757  $line->subprice = $obj->pu_ht;
758  $line->pu_ht = $obj->pu_ht;
759  $line->pu_ttc = $obj->pu_ttc;
760 
761  $line->vat_src_code = $obj->vat_src_code;
762  $line->tva_tx = $obj->tva_tx;
763  $line->localtax1_tx = $obj->localtax1_tx;
764  $line->localtax2_tx = $obj->localtax2_tx;
765  $line->localtax1_type = $obj->localtax1_type;
766  $line->localtax2_type = $obj->localtax2_type;
767  $line->qty = $obj->qty;
768  $line->remise_percent = $obj->remise_percent;
769  $line->tva = $obj->total_tva;
770  $line->total_ht = $obj->total_ht;
771  $line->total_tva = $obj->total_tva;
772  $line->total_localtax1 = $obj->total_localtax1;
773  $line->total_localtax2 = $obj->total_localtax2;
774  $line->fk_facture_fourn = $obj->fk_facture_fourn;
775  $line->total_ttc = $obj->total_ttc;
776  $line->fk_product = $obj->fk_product;
777  $line->product_type = $obj->product_type;
778  $line->product_label = $obj->label;
779  $line->info_bits = $obj->info_bits;
780  $line->fk_parent_line = $obj->fk_parent_line;
781  $line->special_code = $obj->special_code;
782  $line->rang = $obj->rang;
783  $line->fk_unit = $obj->fk_unit;
784 
785  // Multicurrency
786  $line->fk_multicurrency = $obj->fk_multicurrency;
787  $line->multicurrency_code = $obj->multicurrency_code;
788  $line->multicurrency_subprice = $obj->multicurrency_subprice;
789  $line->multicurrency_total_ht = $obj->multicurrency_total_ht;
790  $line->multicurrency_total_tva = $obj->multicurrency_total_tva;
791  $line->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
792 
793  $this->lines[$i] = $line;
794 
795  $i++;
796  }
797  }
798  $this->db->free($resql_rows);
799  return 1;
800  }
801  else
802  {
803  $this->error=$this->db->error();
804  return -3;
805  }
806  }
807 
808 
816  public function update($user=null, $notrigger=0)
817  {
818  global $conf, $langs;
819  $error=0;
820 
821  // Clean parameters
822  if (empty($this->type)) $this->type= self::TYPE_STANDARD;
823  if (isset($this->ref)) $this->ref=trim($this->ref);
824  if (isset($this->ref_supplier)) $this->ref_supplier=trim($this->ref_supplier);
825  if (isset($this->entity)) $this->entity=trim($this->entity);
826  if (isset($this->type)) $this->type=trim($this->type);
827  if (isset($this->fk_soc)) $this->fk_soc=trim($this->fk_soc);
828  if (isset($this->libelle)) $this->libelle=trim($this->libelle);
829  if (isset($this->paye)) $this->paye=trim($this->paye);
830  if (isset($this->amount)) $this->amount=trim($this->amount);
831  if (isset($this->remise)) $this->remise=trim($this->remise);
832  if (isset($this->close_code)) $this->close_code=trim($this->close_code);
833  if (isset($this->close_note)) $this->close_note=trim($this->close_note);
834  if (isset($this->tva)) $this->tva=trim($this->tva);
835  if (isset($this->localtax1)) $this->localtax1=trim($this->localtax1);
836  if (isset($this->localtax2)) $this->localtax2=trim($this->localtax2);
837  if (empty($this->total_ht)) $this->total_ht=0;
838  if (empty($this->total_tva)) $this->total_tva=0;
839  // if (isset($this->total_localtax1)) $this->total_localtax1=trim($this->total_localtax1);
840  // if (isset($this->total_localtax2)) $this->total_localtax2=trim($this->total_localtax2);
841  if (isset($this->total_ttc)) $this->total_ttc=trim($this->total_ttc);
842  if (isset($this->statut)) $this->statut=(int) $this->statut;
843  if (isset($this->author)) $this->author=trim($this->author);
844  if (isset($this->fk_user_valid)) $this->fk_user_valid=trim($this->fk_user_valid);
845  if (isset($this->fk_facture_source)) $this->fk_facture_source=trim($this->fk_facture_source);
846  if (isset($this->fk_project)) $this->fk_project=trim($this->fk_project);
847  if (isset($this->cond_reglement_id)) $this->cond_reglement_id=trim($this->cond_reglement_id);
848  if (isset($this->note_private)) $this->note=trim($this->note_private);
849  if (isset($this->note_public)) $this->note_public=trim($this->note_public);
850  if (isset($this->model_pdf)) $this->model_pdf=trim($this->model_pdf);
851  if (isset($this->import_key)) $this->import_key=trim($this->import_key);
852 
853 
854  // Check parameters
855  // Put here code to add control on parameters values
856 
857  // Update request
858  $sql = "UPDATE ".MAIN_DB_PREFIX."facture_fourn SET";
859  $sql.= " ref=".(isset($this->ref)?"'".$this->db->escape($this->ref)."'":"null").",";
860  $sql.= " ref_supplier=".(isset($this->ref_supplier)?"'".$this->db->escape($this->ref_supplier)."'":"null").",";
861  $sql.= " entity=".(isset($this->entity)?$this->entity:"null").",";
862  $sql.= " type=".(isset($this->type)?$this->type:"null").",";
863  $sql.= " fk_soc=".(isset($this->fk_soc)?$this->fk_soc:"null").",";
864  $sql.= " datec=".(dol_strlen($this->datec)!=0 ? "'".$this->db->idate($this->datec)."'" : 'null').",";
865  $sql.= " datef=".(dol_strlen($this->date)!=0 ? "'".$this->db->idate($this->date)."'" : 'null').",";
866  if (dol_strlen($this->tms) != 0) $sql.= " tms=".(dol_strlen($this->tms)!=0 ? "'".$this->db->idate($this->tms)."'" : 'null').",";
867  $sql.= " libelle=".(isset($this->label)?"'".$this->db->escape($this->label)."'":"null").",";
868  $sql.= " paye=".(isset($this->paye)?$this->paye:"null").",";
869  $sql.= " amount=".(isset($this->amount)?$this->amount:"null").",";
870  $sql.= " remise=".(isset($this->remise)?$this->remise:"null").",";
871  $sql.= " close_code=".(isset($this->close_code)?"'".$this->db->escape($this->close_code)."'":"null").",";
872  $sql.= " close_note=".(isset($this->close_note)?"'".$this->db->escape($this->close_note)."'":"null").",";
873  $sql.= " tva=".(isset($this->tva)?$this->tva:"null").",";
874  $sql.= " localtax1=".(isset($this->localtax1)?$this->localtax1:"null").",";
875  $sql.= " localtax2=".(isset($this->localtax2)?$this->localtax2:"null").",";
876  //$sql.= " total=".(isset($this->total)?$this->total:"null").",";
877  $sql.= " total_ht=".(isset($this->total_ht)?$this->total_ht:"null").",";
878  $sql.= " total_tva=".(isset($this->total_tva)?$this->total_tva:"null").",";
879  $sql.= " total_ttc=".(isset($this->total_ttc)?$this->total_ttc:"null").",";
880  $sql.= " fk_statut=".(isset($this->statut)?$this->statut:"null").",";
881  $sql.= " fk_user_author=".(isset($this->author)?$this->author:"null").",";
882  $sql.= " fk_user_valid=".(isset($this->fk_user_valid)?$this->fk_user_valid:"null").",";
883  $sql.= " fk_facture_source=".(isset($this->fk_facture_source)?$this->fk_facture_source:"null").",";
884  $sql.= " fk_projet=".(isset($this->fk_project)?$this->fk_project:"null").",";
885  $sql.= " fk_cond_reglement=".(isset($this->cond_reglement_id)?$this->cond_reglement_id:"null").",";
886  $sql.= " date_lim_reglement=".(dol_strlen($this->date_echeance)!=0 ? "'".$this->db->idate($this->date_echeance)."'" : 'null').",";
887  $sql.= " note_private=".(isset($this->note_private)?"'".$this->db->escape($this->note_private)."'":"null").",";
888  $sql.= " note_public=".(isset($this->note_public)?"'".$this->db->escape($this->note_public)."'":"null").",";
889  $sql.= " model_pdf=".(isset($this->model_pdf)?"'".$this->db->escape($this->model_pdf)."'":"null").",";
890  $sql.= " import_key=".(isset($this->import_key)?"'".$this->db->escape($this->import_key)."'":"null")."";
891  $sql.= " WHERE rowid=".$this->id;
892 
893  $this->db->begin();
894 
895  dol_syslog(get_class($this)."::update", LOG_DEBUG);
896  $resql = $this->db->query($sql);
897 
898  if (!$resql) {
899  $error++;
900 
901  if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
902  $this->errors[] = $langs->trans('ErrorRefAlreadyExists');
903  } else {
904  $this->errors[] = "Error ".$this->db->lasterror();
905  }
906  }
907 
908  if (! $error)
909  {
910  if (! $notrigger)
911  {
912  // Call trigger
913  $result=$this->call_trigger('BILL_SUPPLIER_UPDATE',$user);
914  if ($result < 0) $error++;
915  // End call triggers
916  }
917  }
918 
919  // Commit or rollback
920  if ($error)
921  {
922  foreach($this->errors as $errmsg)
923  {
924  dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
925  $this->error.=($this->error?', '.$errmsg:$errmsg);
926  }
927  $this->db->rollback();
928  return -1*$error;
929  }
930  else
931  {
932  $this->db->commit();
933  return 1;
934  }
935  }
936 
937  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
944  function insert_discount($idremise)
945  {
946  // phpcs:enable
947  global $langs;
948 
949  include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
950  include_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php';
951 
952  $this->db->begin();
953 
954  $remise=new DiscountAbsolute($this->db);
955  $result=$remise->fetch($idremise);
956 
957  if ($result > 0)
958  {
959  if ($remise->fk_invoice_supplier) // Protection against multiple submission
960  {
961  $this->error=$langs->trans("ErrorDiscountAlreadyUsed");
962  $this->db->rollback();
963  return -5;
964  }
965 
966  $facligne=new SupplierInvoiceLine($this->db);
967  $facligne->fk_facture_fourn=$this->id;
968  $facligne->fk_remise_except=$remise->id;
969  $facligne->desc=$remise->description; // Description ligne
970  $facligne->vat_src_code=$remise->vat_src_code;
971  $facligne->tva_tx=$remise->tva_tx;
972  $facligne->subprice = -$remise->amount_ht;
973  $facligne->fk_product=0; // Id produit predefini
974  $facligne->product_type=0;
975  $facligne->qty=1;
976  $facligne->remise_percent=0;
977  $facligne->rang=-1;
978  $facligne->info_bits=2;
979 
980  // Get buy/cost price of invoice that is source of discount
981  if ($remise->fk_invoice_supplier_source > 0)
982  {
983  $srcinvoice=new FactureFournisseur($this->db);
984  $srcinvoice->fetch($remise->fk_invoice_supplier_source);
985  $totalcostpriceofinvoice=0;
986  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmargin.class.php'; // TODO Move this into commonobject
987  $formmargin=new FormMargin($this->db);
988  $arraytmp=$formmargin->getMarginInfosArray($srcinvoice, false);
989  $facligne->pa_ht = $arraytmp['pa_total'];
990  }
991 
992  $facligne->total_ht = -$remise->amount_ht;
993  $facligne->total_tva = -$remise->amount_tva;
994  $facligne->total_ttc = -$remise->amount_ttc;
995 
996  $facligne->multicurrency_subprice = -$remise->multicurrency_subprice;
997  $facligne->multicurrency_total_ht = -$remise->multicurrency_total_ht;
998  $facligne->multicurrency_total_tva = -$remise->multicurrency_total_tva;
999  $facligne->multicurrency_total_ttc = -$remise->multicurrency_total_ttc;
1000 
1001  $lineid=$facligne->insert();
1002  if ($lineid > 0)
1003  {
1004  $result=$this->update_price(1);
1005  if ($result > 0)
1006  {
1007  // Create link between discount and invoice line
1008  $result=$remise->link_to_invoice($lineid,0,'supplier');
1009  if ($result < 0)
1010  {
1011  $this->error=$remise->error;
1012  $this->db->rollback();
1013  return -4;
1014  }
1015 
1016  $this->db->commit();
1017  return 1;
1018  }
1019  else
1020  {
1021  $this->error=$facligne->error;
1022  $this->db->rollback();
1023  return -1;
1024  }
1025  }
1026  else
1027  {
1028  $this->error=$facligne->error;
1029  $this->db->rollback();
1030  return -2;
1031  }
1032  }
1033  else
1034  {
1035  $this->db->rollback();
1036  return -3;
1037  }
1038  }
1039 
1040 
1048  public function delete(User $user, $notrigger=0)
1049  {
1050  global $langs,$conf;
1051 
1052  $rowid=$this->id;
1053 
1054  dol_syslog("FactureFournisseur::delete rowid=".$rowid, LOG_DEBUG);
1055 
1056  // TODO Test if there is at least on payment. If yes, refuse to delete.
1057 
1058  $error=0;
1059  $this->db->begin();
1060 
1061  if (! $error && ! $notrigger)
1062  {
1063  // Call trigger
1064  $result=$this->call_trigger('BILL_SUPPLIER_DELETE',$user);
1065  if ($result < 0)
1066  {
1067  $this->db->rollback();
1068  return -1;
1069  }
1070  // Fin appel triggers
1071  }
1072 
1073  if (! $error) {
1074  // If invoice was converted into a discount not yet consumed, we remove discount
1075  $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . 'societe_remise_except';
1076  $sql .= ' WHERE fk_invoice_supplier_source = ' . $rowid;
1077  $sql .= ' AND fk_invoice_supplier_line IS NULL';
1078  $resql = $this->db->query($sql);
1079 
1080  // If invoice has consumned discounts
1081  $this->fetch_lines();
1082  $list_rowid_det = array ();
1083  foreach ($this->lines as $key => $invoiceline) {
1084  $list_rowid_det[] = $invoiceline->rowid;
1085  }
1086 
1087  // Consumned discounts are freed
1088  if (count($list_rowid_det)) {
1089  $sql = 'UPDATE ' . MAIN_DB_PREFIX . 'societe_remise_except';
1090  $sql .= ' SET fk_invoice_supplier = NULL, fk_invoice_supplier_line = NULL';
1091  $sql .= ' WHERE fk_invoice_supplier_line IN (' . join(',', $list_rowid_det) . ')';
1092 
1093  dol_syslog(get_class($this) . "::delete", LOG_DEBUG);
1094  if (! $this->db->query($sql)) {
1095  $error ++;
1096  }
1097  }
1098  }
1099 
1100  if (! $error)
1101  {
1102  $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'facture_fourn_det WHERE fk_facture_fourn = '.$rowid.';';
1103  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1104  $resql = $this->db->query($sql);
1105  if ($resql)
1106  {
1107  $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'facture_fourn WHERE rowid = '.$rowid;
1108  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1109  $resql2 = $this->db->query($sql);
1110  if (! $resql2) {
1111  $error++;
1112  }
1113  }
1114  else {
1115  $error++;
1116  }
1117  }
1118 
1119  if (! $error)
1120  {
1121  // Delete linked object
1122  $res = $this->deleteObjectLinked();
1123  if ($res < 0) $error++;
1124  }
1125 
1126  if (! $error)
1127  {
1128  // Delete linked object
1129  $res = $this->deleteObjectLinked();
1130  if ($res < 0) $error++;
1131  }
1132 
1133  if (! $error)
1134  {
1135  // We remove directory
1136  if ($conf->fournisseur->facture->dir_output)
1137  {
1138  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1139 
1140  $ref = dol_sanitizeFileName($this->ref);
1141  $dir = $conf->fournisseur->facture->dir_output.'/'.get_exdir($this->id, 2, 0, 0, $this, 'invoive_supplier').$ref;
1142  $file = $dir . "/" . $ref . ".pdf";
1143  if (file_exists($file))
1144  {
1145  if (! dol_delete_file($file,0,0,0,$this)) // For triggers
1146  {
1147  $this->error='ErrorFailToDeleteFile';
1148  $error++;
1149  }
1150  }
1151  if (file_exists($dir))
1152  {
1153  $res=@dol_delete_dir_recursive($dir);
1154 
1155  if (! $res)
1156  {
1157  $this->error='ErrorFailToDeleteDir';
1158  $error++;
1159  }
1160  }
1161  }
1162  }
1163 
1164  // Remove extrafields
1165  if ((! $error) && (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))) // For avoid conflicts if trigger used
1166  {
1167  $result=$this->deleteExtraFields();
1168  if ($result < 0)
1169  {
1170  $error++;
1171  dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
1172  }
1173  }
1174 
1175  if (! $error)
1176  {
1177  dol_syslog(get_class($this)."::delete $this->id by $user->id", LOG_DEBUG);
1178  $this->db->commit();
1179  return 1;
1180  }
1181  else
1182  {
1183  $this->error=$this->db->lasterror();
1184  $this->db->rollback();
1185  return -$error;
1186  }
1187  }
1188 
1189 
1190  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1199  function set_paid($user, $close_code='', $close_note='')
1200  {
1201  // phpcs:enable
1202  global $conf,$langs;
1203  $error=0;
1204 
1205  $this->db->begin();
1206 
1207  $sql = 'UPDATE '.MAIN_DB_PREFIX.'facture_fourn';
1208  $sql.= ' SET paye = 1, fk_statut=2';
1209  $sql.= ' WHERE rowid = '.$this->id;
1210 
1211  dol_syslog("FactureFournisseur::set_paid", LOG_DEBUG);
1212  $resql = $this->db->query($sql);
1213  if ($resql)
1214  {
1215  // Call trigger
1216  $result=$this->call_trigger('BILL_SUPPLIER_PAYED',$user);
1217  if ($result < 0) $error++;
1218  // End call triggers
1219  }
1220  else
1221  {
1222  $error++;
1223  $this->error=$this->db->error();
1224  dol_print_error($this->db);
1225  }
1226 
1227  if (! $error)
1228  {
1229  $this->db->commit();
1230  return 1;
1231  }
1232  else
1233  {
1234  $this->db->rollback();
1235  return -1;
1236  }
1237  }
1238 
1239 
1240  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1249  function set_unpaid($user)
1250  {
1251  // phpcs:enable
1252  global $conf,$langs;
1253  $error=0;
1254 
1255  $this->db->begin();
1256 
1257  $sql = 'UPDATE '.MAIN_DB_PREFIX.'facture_fourn';
1258  $sql.= ' SET paye=0, fk_statut=1, close_code=null, close_note=null';
1259  $sql.= ' WHERE rowid = '.$this->id;
1260 
1261  dol_syslog("FactureFournisseur::set_unpaid", LOG_DEBUG);
1262  $resql = $this->db->query($sql);
1263  if ($resql)
1264  {
1265  // Call trigger
1266  $result=$this->call_trigger('BILL_SUPPLIER_UNPAYED',$user);
1267  if ($result < 0) $error++;
1268  // End call triggers
1269  }
1270  else
1271  {
1272  $error++;
1273  $this->error=$this->db->lasterror();
1274  dol_syslog("FactureFournisseur::set_unpaid ".$this->error);
1275  }
1276 
1277  if (! $error)
1278  {
1279  $this->db->commit();
1280  return 1;
1281  }
1282  else
1283  {
1284  $this->db->rollback();
1285  return -1;
1286  }
1287  }
1288 
1298  public function validate($user, $force_number='', $idwarehouse=0, $notrigger=0)
1299  {
1300  global $conf,$langs;
1301  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1302 
1303  $now=dol_now();
1304 
1305  $error=0;
1306  dol_syslog(get_class($this).'::validate user='.$user->id.', force_number='.$force_number.', idwarehouse='.$idwarehouse);
1307 
1308  // Force to have object complete for checks
1309  $this->fetch_thirdparty();
1310  $this->fetch_lines();
1311 
1312  // Check parameters
1313  if ($this->statut > self::STATUS_DRAFT) // This is to avoid to validate twice (avoid errors on logs and stock management)
1314  {
1315  dol_syslog(get_class($this)."::validate no draft status", LOG_WARNING);
1316  return 0;
1317  }
1318  if (preg_match('/^'.preg_quote($langs->trans("CopyOf").' ').'/', $this->ref_supplier))
1319  {
1320  $langs->load("errors");
1321  $this->error=$langs->trans("ErrorFieldFormat",$langs->transnoentities("RefSupplier")).'. '.$langs->trans('RemoveString',$langs->transnoentitiesnoconv("CopyOf"));
1322  return -1;
1323  }
1324  if (count($this->lines) <= 0)
1325  {
1326  $langs->load("errors");
1327  $this->error=$langs->trans("ErrorObjectMustHaveLinesToBeValidated", $this->ref);
1328  return -1;
1329  }
1330 
1331  $this->db->begin();
1332 
1333  // Define new ref
1334  if ($force_number)
1335  {
1336  $num = $force_number;
1337  }
1338  else if (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref)) // empty should not happened, but when it occurs, the test save life
1339  {
1340  $num = $this->getNextNumRef($this->thirdparty);
1341  }
1342  else
1343  {
1344  $num = $this->ref;
1345  }
1346  $this->newref = $num;
1347 
1348  $sql = "UPDATE ".MAIN_DB_PREFIX."facture_fourn";
1349  $sql.= " SET ref='".$num."', fk_statut = 1, fk_user_valid = ".$user->id.", date_valid = '".$this->db->idate($now)."'";
1350  $sql.= " WHERE rowid = ".$this->id;
1351 
1352  dol_syslog(get_class($this)."::validate", LOG_DEBUG);
1353  $resql = $this->db->query($sql);
1354  if ($resql)
1355  {
1356  // Si on incrémente le produit principal et ses composants à la validation de facture fournisseur
1357  if (! $error && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL))
1358  {
1359  require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
1360  $langs->load("agenda");
1361 
1362  $cpt=count($this->lines);
1363  for ($i = 0; $i < $cpt; $i++)
1364  {
1365  if ($this->lines[$i]->fk_product > 0)
1366  {
1367  $this->line = $this->lines[$i];
1368  $mouvP = new MouvementStock($this->db);
1369  $mouvP->origin = &$this;
1370  // We increase stock for product
1371  $up_ht_disc=$this->lines[$i]->pu_ht;
1372  if (! empty($this->lines[$i]->remise_percent) && empty($conf->global->STOCK_EXCLUDE_DISCOUNT_FOR_PMP)) $up_ht_disc=price2num($up_ht_disc * (100 - $this->lines[$i]->remise_percent) / 100, 'MU');
1373  $result=$mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $up_ht_disc, $langs->trans("InvoiceValidatedInDolibarr",$num));
1374  if ($result < 0) { $error++; }
1375  unset($this->line);
1376  }
1377  }
1378  }
1379 
1380  // Triggers call
1381  if (! $error && empty($notrigger))
1382  {
1383  // Call trigger
1384  $result=$this->call_trigger('BILL_SUPPLIER_VALIDATE',$user);
1385  if ($result < 0) $error++;
1386  // End call triggers
1387  }
1388 
1389  if (! $error)
1390  {
1391  $this->oldref = $this->ref;
1392 
1393  // Rename directory if dir was a temporary ref
1394  if (preg_match('/^[\(]?PROV/i', $this->ref))
1395  {
1396  // On renomme repertoire facture ($this->ref = ancienne ref, $num = nouvelle ref)
1397  // in order not to lose the attached files
1398  $oldref = dol_sanitizeFileName($this->ref);
1399  $newref = dol_sanitizeFileName($num);
1400 
1401  $dirsource = $conf->fournisseur->facture->dir_output.'/'.get_exdir($this->id,2,0,0, $this, 'invoice_supplier').$oldref;
1402  $dirdest = $conf->fournisseur->facture->dir_output.'/'.get_exdir($this->id,2,0,0, $this, 'invoice_supplier').$newref;
1403  if (file_exists($dirsource))
1404  {
1405  dol_syslog(get_class($this)."::validate rename dir ".$dirsource." into ".$dirdest);
1406 
1407  if (@rename($dirsource, $dirdest))
1408  {
1409  dol_syslog("Rename ok");
1410  // Rename docs starting with $oldref with $newref
1411  $listoffiles=dol_dir_list($conf->fournisseur->facture->dir_output.'/'.get_exdir($this->id,2,0,0, $this, 'invoice_supplier').$newref, 'files', 1, '^'.preg_quote($oldref,'/'));
1412  foreach($listoffiles as $fileentry)
1413  {
1414  $dirsource=$fileentry['name'];
1415  $dirdest=preg_replace('/^'.preg_quote($oldref,'/').'/',$newref, $dirsource);
1416  $dirsource=$fileentry['path'].'/'.$dirsource;
1417  $dirdest=$fileentry['path'].'/'.$dirdest;
1418  @rename($dirsource, $dirdest);
1419  }
1420  }
1421  }
1422  }
1423  }
1424 
1425  // Set new ref and define current statut
1426  if (! $error)
1427  {
1428  $this->ref = $num;
1429  $this->statut=self::STATUS_VALIDATED;
1430  //$this->date_validation=$now; this is stored into log table
1431  }
1432 
1433  if (! $error)
1434  {
1435  $this->db->commit();
1436  return 1;
1437  }
1438  else
1439  {
1440  $this->db->rollback();
1441  return -1;
1442  }
1443  }
1444  else
1445  {
1446  $this->error=$this->db->error();
1447  $this->db->rollback();
1448  return -1;
1449  }
1450  }
1451 
1452 
1453  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1461  function set_draft($user, $idwarehouse=-1)
1462  {
1463  // phpcs:enable
1464  global $conf,$langs;
1465 
1466  $error=0;
1467 
1468  if ($this->statut == self::STATUS_DRAFT)
1469  {
1470  dol_syslog(get_class($this)."::set_draft already draft status", LOG_WARNING);
1471  return 0;
1472  }
1473 
1474  $this->db->begin();
1475 
1476  $sql = "UPDATE ".MAIN_DB_PREFIX."facture_fourn";
1477  $sql.= " SET fk_statut = 0";
1478  $sql.= " WHERE rowid = ".$this->id;
1479 
1480  dol_syslog(get_class($this)."::set_draft", LOG_DEBUG);
1481  $result=$this->db->query($sql);
1482  if ($result)
1483  {
1484  // Si on incremente le produit principal et ses composants a la validation de facture fournisseur, on decremente
1485  if ($result >= 0 && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL))
1486  {
1487  require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
1488  $langs->load("agenda");
1489 
1490  $cpt=count($this->lines);
1491  for ($i = 0; $i < $cpt; $i++)
1492  {
1493  if ($this->lines[$i]->fk_product > 0)
1494  {
1495  $mouvP = new MouvementStock($this->db);
1496  $mouvP->origin = &$this;
1497  // We increase stock for product
1498  $result=$mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans("InvoiceBackToDraftInDolibarr", $this->ref));
1499  }
1500  }
1501  }
1502  // Triggers call
1503  if (! $error && empty($notrigger))
1504  {
1505  // Call trigger
1506  $result=$this->call_trigger('BILL_SUPPLIER_UNVALIDATE',$user);
1507  if ($result < 0) $error++;
1508  // End call triggers
1509  }
1510  if ($error == 0)
1511  {
1512  $this->db->commit();
1513  return 1;
1514  }
1515  else
1516  {
1517  $this->db->rollback();
1518  return -1;
1519  }
1520  }
1521  else
1522  {
1523  $this->error=$this->db->error();
1524  $this->db->rollback();
1525  return -1;
1526  }
1527  }
1528 
1529 
1560  public function addline($desc, $pu, $txtva, $txlocaltax1, $txlocaltax2, $qty, $fk_product=0, $remise_percent=0, $date_start='', $date_end='', $ventil=0, $info_bits='', $price_base_type='HT', $type=0, $rang=-1, $notrigger=false, $array_options=0, $fk_unit=null, $origin_id=0, $pu_ht_devise=0, $ref_supplier='')
1561  {
1562  global $langs, $mysoc, $conf;
1563 
1564  dol_syslog(get_class($this)."::addline $desc,$pu,$qty,$txtva,$fk_product,$remise_percent,$date_start,$date_end,$ventil,$info_bits,$price_base_type,$type,$fk_unit", LOG_DEBUG);
1565  include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
1566 
1567  if ($this->statut == self::STATUS_DRAFT)
1568  {
1569  // Clean parameters
1570  if (empty($remise_percent)) $remise_percent=0;
1571  if (empty($qty)) $qty=0;
1572  if (empty($info_bits)) $info_bits=0;
1573  if (empty($rang)) $rang=0;
1574  if (empty($ventil)) $ventil=0;
1575  if (empty($txtva)) $txtva=0;
1576  if (empty($txlocaltax1)) $txlocaltax1=0;
1577  if (empty($txlocaltax2)) $txlocaltax2=0;
1578 
1579  $remise_percent=price2num($remise_percent);
1580  $qty=price2num($qty);
1581  $pu=price2num($pu);
1582  $txlocaltax1=price2num($txlocaltax1);
1583  $txlocaltax2=price2num($txlocaltax2);
1584  if (!preg_match('/\((.*)\)/', $txtva)) {
1585  $txtva = price2num($txtva); // $txtva can have format '5,1' or '5.1' or '5.1(XXX)', we must clean only if '5,1'
1586  }
1587 
1588  $this->db->begin();
1589 
1590  if ($fk_product > 0)
1591  {
1592  if (! empty($conf->global->SUPPLIER_INVOICE_WITH_PREDEFINED_PRICES_ONLY))
1593  {
1594  // Check quantity is enough
1595  dol_syslog(get_class($this)."::addline we check supplier prices fk_product=".$fk_product." qty=".$qty." ref_supplier=".$ref_supplier);
1596  $prod = new Product($this->db, $fk_product);
1597  if ($prod->fetch($fk_product) > 0)
1598  {
1599  $product_type = $prod->type;
1600  $label = $prod->label;
1601  $fk_prod_fourn_price = 0;
1602 
1603  // We use 'none' instead of $ref_supplier, because $ref_supplier may not exists anymore. So we will take the first supplier price ok.
1604  // If we want a dedicated supplier price, we must provide $fk_prod_fourn_price.
1605  $result=$prod->get_buyprice($fk_prod_fourn_price, $qty, $fk_product, 'none', ($this->fk_soc?$this->fk_soc:$this->socid)); // Search on couple $fk_prod_fourn_price/$qty first, then on triplet $qty/$fk_product/$ref_supplier/$this->fk_soc
1606  if ($result > 0)
1607  {
1608  $pu = $prod->fourn_pu; // Unit price supplier price set by get_buyprice
1609  $ref_supplier = $prod->ref_supplier; // Ref supplier price set by get_buyprice
1610  // is remise percent not keyed but present for the product we add it
1611  if ($remise_percent == 0 && $prod->remise_percent !=0)
1612  $remise_percent =$prod->remise_percent;
1613  }
1614  if ($result == 0) // If result == 0, we failed to found the supplier reference price
1615  {
1616  $langs->load("errors");
1617  $this->error = "Ref " . $prod->ref . " " . $langs->trans("ErrorQtyTooLowForThisSupplier");
1618  $this->db->rollback();
1619  dol_syslog(get_class($this)."::addline we did not found supplier price, so we can't guess unit price");
1620  //$pu = $prod->fourn_pu; // We do not overwrite unit price
1621  //$ref = $prod->ref_fourn; // We do not overwrite ref supplier price
1622  return -1;
1623  }
1624  if ($result == -1)
1625  {
1626  $langs->load("errors");
1627  $this->error = "Ref " . $prod->ref . " " . $langs->trans("ErrorQtyTooLowForThisSupplier");
1628  $this->db->rollback();
1629  dol_syslog(get_class($this)."::addline result=".$result." - ".$this->error, LOG_DEBUG);
1630  return -1;
1631  }
1632  if ($result < -1)
1633  {
1634  $this->error=$prod->error;
1635  $this->db->rollback();
1636  dol_syslog(get_class($this)."::addline result=".$result." - ".$this->error, LOG_ERR);
1637  return -1;
1638  }
1639  }
1640  else
1641  {
1642  $this->error=$prod->error;
1643  $this->db->rollback();
1644  return -1;
1645  }
1646  }
1647  }
1648  else
1649  {
1650  $product_type = $type;
1651  }
1652 
1653  if ($conf->multicurrency->enabled && $pu_ht_devise > 0) {
1654  $pu = 0;
1655  }
1656 
1657  $localtaxes_type=getLocalTaxesFromRate($txtva, 0, $mysoc, $this->thirdparty);
1658 
1659  // Clean vat code
1660  $vat_src_code='';
1661  if (preg_match('/\((.*)\)/', $txtva, $reg))
1662  {
1663  $vat_src_code = $reg[1];
1664  $txtva = preg_replace('/\s*\(.*\)/', '', $txtva); // Remove code into vatrate.
1665  }
1666 
1667  // Calcul du total TTC et de la TVA pour la ligne a partir de
1668  // qty, pu, remise_percent et txtva
1669  // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
1670  // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
1671 
1672  $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $this->thirdparty, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
1673  $total_ht = $tabprice[0];
1674  $total_tva = $tabprice[1];
1675  $total_ttc = $tabprice[2];
1676  $total_localtax1 = $tabprice[9];
1677  $total_localtax2 = $tabprice[10];
1678  $pu_ht = $tabprice[3];
1679 
1680  // MultiCurrency
1681  $multicurrency_total_ht = $tabprice[16];
1682  $multicurrency_total_tva = $tabprice[17];
1683  $multicurrency_total_ttc = $tabprice[18];
1684  $pu_ht_devise = $tabprice[19];
1685 
1686  // Check parameters
1687  if ($type < 0) return -1;
1688 
1689  if ($rang < 0)
1690  {
1691  $rangmax = $this->line_max();
1692  $rang = $rangmax + 1;
1693  }
1694 
1695  // Insert line
1696  $this->line=new SupplierInvoiceLine($this->db);
1697 
1698  $this->line->context = $this->context;
1699 
1700  $this->line->fk_facture_fourn=$this->id;
1701  //$this->line->label=$label; // deprecated
1702  $this->line->desc=$desc;
1703  $this->line->qty= ($this->type==self::TYPE_CREDIT_NOTE?abs($qty):$qty); // For credit note, quantity is always positive and unit price negative
1704  $this->line->ref_supplier=$ref_supplier;
1705 
1706  $this->line->vat_src_code=$vat_src_code;
1707  $this->line->tva_tx=$txtva;
1708  $this->line->localtax1_tx=($total_localtax1?$localtaxes_type[1]:0);
1709  $this->line->localtax2_tx=($total_localtax2?$localtaxes_type[3]:0);
1710  $this->line->localtax1_type = $localtaxes_type[0];
1711  $this->line->localtax2_type = $localtaxes_type[2];
1712  $this->line->fk_product=$fk_product;
1713  $this->line->product_type=$type;
1714  $this->line->remise_percent=$remise_percent;
1715  $this->line->subprice= ($this->type==self::TYPE_CREDIT_NOTE?-abs($pu_ht):$pu_ht); // For credit note, unit price always negative, always positive otherwise
1716  $this->line->date_start=$date_start;
1717  $this->line->date_end=$date_end;
1718  $this->line->ventil=$ventil;
1719  $this->line->rang=$rang;
1720  $this->line->info_bits=$info_bits;
1721  $this->line->total_ht= (($this->type==self::TYPE_CREDIT_NOTE||$qty<0)?-abs($total_ht):$total_ht); // For credit note and if qty is negative, total is negative
1722  $this->line->total_tva= $total_tva;
1723  $this->line->total_localtax1=$total_localtax1;
1724  $this->line->total_localtax2=$total_localtax2;
1725  $this->line->total_ttc= (($this->type==self::TYPE_CREDIT_NOTE||$qty<0)?-abs($total_ttc):$total_ttc);
1726  $this->line->special_code=$this->special_code;
1727  $this->line->fk_parent_line=$this->fk_parent_line;
1728  $this->line->origin=$this->origin;
1729  $this->line->origin_id=$origin_id;
1730  $this->line->fk_unit=$fk_unit;
1731 
1732  // Multicurrency
1733  $this->line->fk_multicurrency = $this->fk_multicurrency;
1734  $this->line->multicurrency_code = $this->multicurrency_code;
1735  $this->line->multicurrency_subprice = $pu_ht_devise;
1736  $this->line->multicurrency_total_ht = $multicurrency_total_ht;
1737  $this->line->multicurrency_total_tva = $multicurrency_total_tva;
1738  $this->line->multicurrency_total_ttc = $multicurrency_total_ttc;
1739 
1740  if (is_array($array_options) && count($array_options)>0) {
1741  $this->line->array_options=$array_options;
1742  }
1743 
1744  $result=$this->line->insert($notrigger);
1745  if ($result > 0)
1746  {
1747  // Reorder if child line
1748  if (! empty($fk_parent_line)) $this->line_order(true,'DESC');
1749 
1750  // Mise a jour informations denormalisees au niveau de la facture meme
1751  $result=$this->update_price(1,'auto',0,$this->thirdparty); // The addline method is designed to add line from user input so total calculation with update_price must be done using 'auto' mode.
1752  if ($result > 0)
1753  {
1754  $this->db->commit();
1755  return $this->line->id;
1756  }
1757  else
1758  {
1759  $this->error=$this->db->error();
1760  $this->db->rollback();
1761  return -1;
1762  }
1763  }
1764  else
1765  {
1766  $this->error=$this->line->error;
1767  $this->errors=$this->line->errors;
1768  $this->db->rollback();
1769  return -2;
1770  }
1771  }
1772  else
1773  {
1774  return 0;
1775  }
1776  }
1777 
1802  public function updateline($id, $desc, $pu, $vatrate, $txlocaltax1=0, $txlocaltax2=0, $qty=1, $idproduct=0, $price_base_type='HT', $info_bits=0, $type=0, $remise_percent=0, $notrigger=false, $date_start='', $date_end='', $array_options=0, $fk_unit = null, $pu_ht_devise=0, $ref_supplier='')
1803  {
1804  global $mysoc;
1805  dol_syslog(get_class($this)."::updateline $id,$desc,$pu,$vatrate,$qty,$idproduct,$price_base_type,$info_bits,$type,$remise_percent,$notrigger,$date_start,$date_end,$fk_unit,$pu_ht_devise,$ref_supplier", LOG_DEBUG);
1806  include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
1807 
1808  $pu = price2num($pu);
1809  $qty = price2num($qty);
1810  $remise_percent=price2num($remise_percent);
1811  $pu_ht_devise = price2num($pu_ht_devise);
1812 
1813  // Check parameters
1814  //if (! is_numeric($pu) || ! is_numeric($qty)) return -1;
1815  if ($type < 0) return -1;
1816 
1817  // Clean parameters
1818  if (empty($vatrate)) $vatrate=0;
1819  if (empty($txlocaltax1)) $txlocaltax1=0;
1820  if (empty($txlocaltax2)) $txlocaltax2=0;
1821 
1822  $txlocaltax1=price2num($txlocaltax1);
1823  $txlocaltax2=price2num($txlocaltax2);
1824 
1825  $localtaxes_type = array($txlocaltax1,$txlocaltax2);
1826 
1827  // Calcul du total TTC et de la TVA pour la ligne a partir de
1828  // qty, pu, remise_percent et txtva
1829  // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
1830  // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
1831 
1832  $localtaxes_type=getLocalTaxesFromRate($vatrate,0,$mysoc, $this->thirdparty);
1833 
1834  // Clean vat code
1835  $vat_src_code='';
1836  if (preg_match('/\((.*)\)/', $vatrate, $reg))
1837  {
1838  $vat_src_code = $reg[1];
1839  $vatrate = preg_replace('/\s*\(.*\)/', '', $vatrate); // Remove code into vatrate.
1840  }
1841 
1842  $tabprice = calcul_price_total($qty, $pu, $remise_percent, $vatrate, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $this->thirdparty, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
1843  $total_ht = $tabprice[0];
1844  $total_tva = $tabprice[1];
1845  $total_ttc = $tabprice[2];
1846  $pu_ht = $tabprice[3];
1847  $pu_tva = $tabprice[4];
1848  $pu_ttc = $tabprice[5];
1849  $total_localtax1 = $tabprice[9];
1850  $total_localtax2 = $tabprice[10];
1851 
1852  // MultiCurrency
1853  $multicurrency_total_ht = $tabprice[16];
1854  $multicurrency_total_tva = $tabprice[17];
1855  $multicurrency_total_ttc = $tabprice[18];
1856  $pu_ht_devise = $tabprice[19];
1857 
1858  if (empty($info_bits)) $info_bits=0;
1859 
1860  if ($idproduct)
1861  {
1862  $product=new Product($this->db);
1863  $result=$product->fetch($idproduct);
1864  $product_type = $product->type;
1865  }
1866  else
1867  {
1868  $product_type = $type;
1869  }
1870 
1871  $line = new SupplierInvoiceLine($this->db);
1872 
1873  if ($line->fetch($id) < 1) {
1874  return -1;
1875  }
1876 
1877  $line->description = $desc;
1878  $line->subprice = $pu_ht;
1879  $line->pu_ht = $pu_ht;
1880  $line->pu_ttc = $pu_ttc;
1881  $line->qty = $qty;
1882  $line->remise_percent = $remise_percent;
1883  $line->ref_supplier = $ref_supplier;
1884 
1885  $line->date_start = $date_start;
1886  $line->date_end = $date_end;
1887 
1888  $line->vat_src_code=$vat_src_code;
1889  $line->tva_tx = $vatrate;
1890  $line->localtax1_tx = $txlocaltax1;
1891  $line->localtax2_tx = $txlocaltax2;
1892  $line->localtax1_type = $localtaxes_type[0];
1893  $line->localtax2_type = $localtaxes_type[2];
1894  $line->total_ht = $total_ht;
1895  $line->total_tva = $total_tva;
1896  $line->total_localtax1 = $total_localtax1;
1897  $line->total_localtax2 = $total_localtax2;
1898  $line->total_ttc = $total_ttc;
1899  $line->fk_product = $idproduct;
1900  $line->product_type = $product_type;
1901  $line->info_bits = $info_bits;
1902  $line->fk_unit = $fk_unit;
1903  $line->array_options = $array_options;
1904 
1905  // Multicurrency
1906  $line->multicurrency_subprice = $pu_ht_devise;
1907  $line->multicurrency_total_ht = $multicurrency_total_ht;
1908  $line->multicurrency_total_tva = $multicurrency_total_tva;
1909  $line->multicurrency_total_ttc = $multicurrency_total_ttc;
1910 
1911  $res = $line->update($notrigger);
1912 
1913  if ($res < 1) {
1914  $this->errors[] = $line->error;
1915  } else {
1916  // Update total price into invoice record
1917  $res = $this->update_price('','auto');
1918  }
1919 
1920  return $res;
1921  }
1922 
1930  public function deleteline($rowid, $notrigger=0)
1931  {
1932  if (!$rowid) {
1933  $rowid = $this->id;
1934  }
1935 
1936  $this->db->begin();
1937 
1938  // Libere remise liee a ligne de facture
1939  $sql = 'UPDATE ' . MAIN_DB_PREFIX . 'societe_remise_except';
1940  $sql .= ' SET fk_invoice_supplier_line = NULL';
1941  $sql .= ' WHERE fk_invoice_supplier_line = ' . $rowid;
1942 
1943  dol_syslog(get_class($this) . "::deleteline", LOG_DEBUG);
1944  $result = $this->db->query($sql);
1945  if (! $result)
1946  {
1947  $this->error = $this->db->error();
1948  $this->db->rollback();
1949  return - 2;
1950  }
1951 
1952  $line = new SupplierInvoiceLine($this->db);
1953 
1954  if ($line->fetch($rowid) < 1) {
1955  return -1;
1956  }
1957 
1958  $res = $line->delete($notrigger);
1959 
1960  if ($res < 1) {
1961  $this->errors[] = $line->error;
1962  $this->db->rollback();
1963  return - 3;
1964  } else {
1965  $res = $this->update_price();
1966 
1967  if ($res > 0)
1968  {
1969  $this->db->commit();
1970  return 1;
1971  }
1972  else
1973  {
1974  $this->db->rollback();
1975  $this->error = $this->db->lasterror();
1976  return - 4;
1977  }
1978  }
1979  }
1980 
1981 
1988  public function info($id)
1989  {
1990  $sql = 'SELECT c.rowid, datec, tms as datem, ';
1991  $sql.= ' fk_user_author, fk_user_modif, fk_user_valid';
1992  $sql.= ' FROM '.MAIN_DB_PREFIX.'facture_fourn as c';
1993  $sql.= ' WHERE c.rowid = '.$id;
1994 
1995  $result=$this->db->query($sql);
1996  if ($result)
1997  {
1998  if ($this->db->num_rows($result))
1999  {
2000  $obj = $this->db->fetch_object($result);
2001  $this->id = $obj->rowid;
2002  if ($obj->fk_user_author)
2003  {
2004  $cuser = new User($this->db);
2005  $cuser->fetch($obj->fk_user_author);
2006  $this->user_creation = $cuser;
2007  }
2008  if ($obj->fk_user_valid)
2009  {
2010  $vuser = new User($this->db);
2011  $vuser->fetch($obj->fk_user_valid);
2012  $this->user_validation = $vuser;
2013  }
2014  if ($obj->fk_user_modif)
2015  {
2016  $muser = new User($this->db);
2017  $muser->fetch($obj->fk_user_modif);
2018  $this->user_modification = $muser;
2019  }
2020  $this->date_creation = $this->db->idate($obj->datec);
2021  $this->date_modification = $this->db->idate($obj->datem);
2022  //$this->date_validation = $obj->datev; // This field is not available. Should be store into log table and using this function should be replaced with showing content of log (like for supplier orders)
2023  }
2024  $this->db->free($result);
2025  }
2026  else
2027  {
2028  dol_print_error($this->db);
2029  }
2030  }
2031 
2032  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2042  {
2043  // phpcs:enable
2044  global $conf;
2045 
2046  $return = array();
2047 
2048  $sql = "SELECT f.rowid as rowid, f.ref, f.fk_statut,";
2049  $sql.= " ff.rowid as rowidnext";
2050  $sql.= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
2051  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."paiementfourn_facturefourn as pf ON f.rowid = pf.fk_facturefourn";
2052  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."facture_fourn as ff ON f.rowid = ff.fk_facture_source";
2053  $sql.= " WHERE (f.fk_statut = ".self::STATUS_VALIDATED." OR (f.fk_statut = ".self::STATUS_ABANDONED." AND f.close_code = '".self::CLOSECODE_ABANDONED."'))";
2054  $sql.= " AND f.entity = ".$conf->entity;
2055  $sql.= " AND f.paye = 0"; // Pas classee payee completement
2056  $sql.= " AND pf.fk_paiementfourn IS NULL"; // Aucun paiement deja fait
2057  $sql.= " AND ff.fk_statut IS NULL"; // Renvoi vrai si pas facture de remplacement
2058  if ($socid > 0) $sql.=" AND f.fk_soc = ".$socid;
2059  $sql.= " ORDER BY f.ref";
2060 
2061  dol_syslog(get_class($this)."::list_replacable_supplier_invoices", LOG_DEBUG);
2062  $resql=$this->db->query($sql);
2063  if ($resql)
2064  {
2065  while ($obj=$this->db->fetch_object($resql))
2066  {
2067  $return[$obj->rowid]=array(
2068  'id' => $obj->rowid,
2069  'ref' => $obj->ref,
2070  'status' => $obj->fk_statut
2071  );
2072  }
2073  //print_r($return);
2074  return $return;
2075  }
2076  else
2077  {
2078  $this->error=$this->db->error();
2079  return -1;
2080  }
2081  }
2082 
2083  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2094  {
2095  // phpcs:enable
2096  global $conf;
2097 
2098  $return = array();
2099 
2100  $sql = "SELECT f.rowid as rowid, f.ref, f.fk_statut, f.type, f.paye, pf.fk_paiementfourn";
2101  $sql.= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
2102  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."paiementfourn_facturefourn as pf ON f.rowid = pf.fk_facturefourn";
2103  $sql.= " WHERE f.entity = ".$conf->entity;
2104  $sql.= " AND f.fk_statut in (".self::STATUS_VALIDATED.",".self::STATUS_CLOSED.")";
2105  $sql.= " AND NOT EXISTS (SELECT rowid from ".MAIN_DB_PREFIX."facture_fourn as ff WHERE f.rowid = ff.fk_facture_source";
2106  $sql.= " AND ff.type=".self::TYPE_REPLACEMENT.")";
2107  $sql.= " AND f.type != ".self::TYPE_CREDIT_NOTE; // Type non 2 si facture non avoir
2108  if ($socid > 0) $sql.=" AND f.fk_soc = ".$socid;
2109  $sql.= " ORDER BY f.ref";
2110 
2111  dol_syslog(get_class($this)."::list_qualified_avoir_supplier_invoices", LOG_DEBUG);
2112  $resql=$this->db->query($sql);
2113  if ($resql)
2114  {
2115  while ($obj=$this->db->fetch_object($resql))
2116  {
2117  $qualified=0;
2118  if ($obj->fk_statut == self::STATUS_VALIDATED) $qualified=1;
2119  if ($obj->fk_statut == self::STATUS_CLOSED) $qualified=1;
2120  if ($qualified)
2121  {
2122  $paymentornot=($obj->fk_paiementfourn?1:0);
2123  $return[$obj->rowid]=array('ref'=>$obj->ref,'status'=>$obj->fk_statut,'type'=>$obj->type,'paye'=>$obj->paye,'paymentornot'=>$paymentornot);
2124  }
2125  }
2126 
2127  return $return;
2128  }
2129  else
2130  {
2131  $this->error=$this->db->error();
2132  return -1;
2133  }
2134  }
2135 
2136  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2143  function load_board($user)
2144  {
2145  // phpcs:enable
2146  global $conf, $langs;
2147 
2148  $sql = 'SELECT ff.rowid, ff.date_lim_reglement as datefin, ff.fk_statut';
2149  $sql.= ' FROM '.MAIN_DB_PREFIX.'facture_fourn as ff';
2150  if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
2151  $sql.= ' WHERE ff.paye=0';
2152  $sql.= ' AND ff.fk_statut > 0';
2153  $sql.= " AND ff.entity = ".$conf->entity;
2154  if ($user->societe_id) $sql.=' AND ff.fk_soc = '.$user->societe_id;
2155  if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND ff.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
2156 
2157  $resql=$this->db->query($sql);
2158  if ($resql)
2159  {
2160  $langs->load("bills");
2161  $now=dol_now();
2162 
2163  $response = new WorkboardResponse();
2164  $response->warning_delay=$conf->facture->fournisseur->warning_delay/60/60/24;
2165  $response->label=$langs->trans("SupplierBillsToPay");
2166 
2167  $response->url=DOL_URL_ROOT.'/fourn/facture/list.php?search_status=1&mainmenu=billing&leftmenu=suppliers_bills';
2168  $response->img=img_object($langs->trans("Bills"),"bill");
2169 
2170  $facturestatic = new FactureFournisseur($this->db);
2171 
2172  while ($obj=$this->db->fetch_object($resql))
2173  {
2174  $response->nbtodo++;
2175 
2176  $facturestatic->date_echeance = $this->db->jdate($obj->datefin);
2177  $facturestatic->statut = $obj->fk_statut;
2178 
2179  if ($facturestatic->hasDelay()) {
2180  $response->nbtodolate++;
2181  }
2182  }
2183  $this->db->free($resql);
2184  return $response;
2185  }
2186  else
2187  {
2188  dol_print_error($this->db);
2189  $this->error=$this->db->error();
2190  return -1;
2191  }
2192  }
2193 
2194 
2207  public function getNomUrl($withpicto=0, $option='',$max=0, $short=0, $moretitle='', $notooltip=0, $save_lastsearch_value=-1)
2208  {
2209  global $langs, $conf;
2210 
2211  $result='';
2212 
2213  if ($option == 'document') $url = DOL_URL_ROOT.'/fourn/facture/document.php?facid='.$this->id;
2214  else $url = DOL_URL_ROOT.'/fourn/facture/card.php?facid='.$this->id;
2215 
2216  if ($short) return $url;
2217 
2218  if ($option !== 'nolink')
2219  {
2220  // Add param to save lastsearch_values or not
2221  $add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
2222  if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
2223  if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
2224  }
2225 
2226  $picto='bill';
2227  if ($this->type == self::TYPE_REPLACEMENT) $picto.='r'; // Replacement invoice
2228  if ($this->type == self::TYPE_CREDIT_NOTE) $picto.='a'; // Credit note
2229  if ($this->type == self::TYPE_DEPOSIT) $picto.='d'; // Deposit invoice
2230 
2231  $label = '<u>' . $langs->trans("ShowSupplierInvoice") . '</u>';
2232  if (! empty($this->ref))
2233  $label .= '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
2234  if (! empty($this->ref_supplier))
2235  $label.= '<br><b>' . $langs->trans('RefSupplier') . ':</b> ' . $this->ref_supplier;
2236  if (! empty($this->libelle))
2237  $label.= '<br><b>' . $langs->trans('Label') . ':</b> ' . $this->libelle;
2238  if (! empty($this->total_ht))
2239  $label.= '<br><b>' . $langs->trans('AmountHT') . ':</b> ' . price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
2240  if (! empty($this->total_tva))
2241  $label.= '<br><b>' . $langs->trans('VAT') . ':</b> ' . price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
2242  if (! empty($this->total_ttc))
2243  $label.= '<br><b>' . $langs->trans('AmountTTC') . ':</b> ' . price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
2244  if ($this->type == self::TYPE_REPLACEMENT) $label=$langs->transnoentitiesnoconv("ShowInvoiceReplace").': '.$this->ref;
2245  if ($this->type == self::TYPE_CREDIT_NOTE) $label=$langs->transnoentitiesnoconv("ShowInvoiceAvoir").': '.$this->ref;
2246  if ($this->type == self::TYPE_DEPOSIT) $label=$langs->transnoentitiesnoconv("ShowInvoiceDeposit").': '.$this->ref;
2247  if ($moretitle) $label.=' - '.$moretitle;
2248 
2249  $ref=$this->ref;
2250  if (empty($ref)) $ref=$this->id;
2251 
2252  $linkclose='';
2253  if (empty($notooltip))
2254  {
2255  if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
2256  {
2257  $label=$langs->trans("ShowSupplierInvoice");
2258  $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"';
2259  }
2260  $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
2261  $linkclose.=' class="classfortooltip"';
2262  }
2263 
2264  $linkstart = '<a href="'.$url.'"';
2265  $linkstart.=$linkclose.'>';
2266  $linkend='</a>';
2267 
2268  $result .= $linkstart;
2269  if ($withpicto) $result.=img_object(($notooltip?'':$label), $this->picto, ($notooltip?(($withpicto != 2) ? 'class="paddingright"' : ''):'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip?0:1);
2270  if ($withpicto != 2) $result.= ($max?dol_trunc($ref,$max):$ref);
2271  $result .= $linkend;
2272 
2273  return $result;
2274  }
2275 
2284  public function getNextNumRef($soc,$mode='next')
2285  {
2286  global $db, $langs, $conf;
2287  $langs->load("orders");
2288 
2289  // Clean parameters (if not defined or using deprecated value)
2290  if (empty($conf->global->INVOICE_SUPPLIER_ADDON_NUMBER)) $conf->global->INVOICE_SUPPLIER_ADDON_NUMBER='mod_facture_fournisseur_cactus';
2291 
2292  $mybool=false;
2293 
2294  $file = $conf->global->INVOICE_SUPPLIER_ADDON_NUMBER.".php";
2295  $classname = $conf->global->INVOICE_SUPPLIER_ADDON_NUMBER;
2296 
2297  // Include file with class
2298  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
2299 
2300  foreach ($dirmodels as $reldir) {
2301 
2302  $dir = dol_buildpath($reldir."core/modules/supplier_invoice/");
2303 
2304  // Load file with numbering class (if found)
2305  $mybool|=@include_once $dir.$file;
2306  }
2307 
2308  if ($mybool === false) {
2309  dol_print_error('', "Failed to include file ".$file);
2310  return '';
2311  }
2312 
2313  $obj = new $classname();
2314  $numref = "";
2315  $numref = $obj->getNumRef($soc,$this,$mode);
2316 
2317  if ($numref != "")
2318  {
2319  return $numref;
2320  }
2321  else
2322  {
2323  $this->error=$obj->error;
2324  //dol_print_error($db,get_class($this)."::getNextNumRef ".$obj->error);
2325  return false;
2326  }
2327  }
2328 
2329 
2338  public function initAsSpecimen($option='')
2339  {
2340  global $langs,$conf;
2341  include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
2342 
2343  $now = dol_now();
2344 
2345  // Load array of products prodids
2346  $num_prods = 0;
2347  $prodids = array();
2348 
2349  $sql = "SELECT rowid";
2350  $sql.= " FROM ".MAIN_DB_PREFIX."product";
2351  $sql.= " WHERE entity IN (".getEntity('product').")";
2352 
2353  $resql = $this->db->query($sql);
2354  if ($resql)
2355  {
2356  $num_prods = $this->db->num_rows($resql);
2357  $i = 0;
2358  while ($i < $num_prods)
2359  {
2360  $i++;
2361  $row = $this->db->fetch_row($resql);
2362  $prodids[$i] = $row[0];
2363  }
2364  }
2365 
2366  // Initialise parametres
2367  $this->id=0;
2368  $this->ref = 'SPECIMEN';
2369  $this->ref_supplier = 'SUPPLIER_REF_SPECIMEN';
2370  $this->specimen=1;
2371  $this->socid = 1;
2372  $this->date = $now;
2373  $this->date_lim_reglement=$this->date+3600*24*30;
2374  $this->cond_reglement_code = 'RECEP';
2375  $this->mode_reglement_code = 'CHQ';
2376  $this->note_public='This is a comment (public)';
2377  $this->note_private='This is a comment (private)';
2378 
2379  if (empty($option) || $option != 'nolines')
2380  {
2381  // Lines
2382  $nbp = 5;
2383  $xnbp = 0;
2384  while ($xnbp < $nbp)
2385  {
2386  $line=new FactureLigne($this->db);
2387  $line->desc=$langs->trans("Description")." ".$xnbp;
2388  $line->qty=1;
2389  $line->subprice=100;
2390  $line->pu_ht=100; // the canelle template use pu_ht and not subprice
2391  $line->price=100;
2392  $line->tva_tx=19.6;
2393  $line->localtax1_tx=0;
2394  $line->localtax2_tx=0;
2395  if ($xnbp == 2)
2396  {
2397  $line->total_ht=50;
2398  $line->total_ttc=59.8;
2399  $line->total_tva=9.8;
2400  $line->remise_percent=50;
2401  }
2402  else
2403  {
2404  $line->total_ht=100;
2405  $line->total_ttc=119.6;
2406  $line->total_tva=19.6;
2407  $line->remise_percent=0;
2408  }
2409 
2410  if ($num_prods > 0)
2411  {
2412  $prodid = mt_rand(1, $num_prods);
2413  $line->fk_product=$prodids[$prodid];
2414  }
2415  $line->product_type=0;
2416 
2417  $this->lines[$xnbp]=$line;
2418 
2419  $this->total_ht += $line->total_ht;
2420  $this->total_tva += $line->total_tva;
2421  $this->total_ttc += $line->total_ttc;
2422 
2423  $xnbp++;
2424  }
2425  }
2426 
2427  $this->amount_ht = $xnbp*100;
2428  $this->total_ht = $xnbp*100;
2429  $this->total_tva = $xnbp*19.6;
2430  $this->total_ttc = $xnbp*119.6;
2431  }
2432 
2433  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2439  function load_state_board()
2440  {
2441  // phpcs:enable
2442  global $conf, $user;
2443 
2444  $this->nb=array();
2445 
2446  $clause = "WHERE";
2447 
2448  $sql = "SELECT count(f.rowid) as nb";
2449  $sql.= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
2450  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON f.fk_soc = s.rowid";
2451  if (!$user->rights->societe->client->voir && !$user->societe_id)
2452  {
2453  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc";
2454  $sql.= " WHERE sc.fk_user = " .$user->id;
2455  $clause = "AND";
2456  }
2457  $sql.= " ".$clause." f.entity = ".$conf->entity;
2458 
2459  $resql=$this->db->query($sql);
2460  if ($resql)
2461  {
2462  while ($obj=$this->db->fetch_object($resql))
2463  {
2464  $this->nb["supplier_invoices"]=$obj->nb;
2465  }
2466  $this->db->free($resql);
2467  return 1;
2468  }
2469  else
2470  {
2471  dol_print_error($this->db);
2472  $this->error=$this->db->error();
2473  return -1;
2474  }
2475  }
2476 
2484  public function createFromClone($fromid,$invertdetail=0)
2485  {
2486  global $user,$langs;
2487 
2488  $error=0;
2489 
2490  $object=new FactureFournisseur($this->db);
2491 
2492  $this->db->begin();
2493 
2494  // Load source object
2495  $object->fetch($fromid);
2496  $object->id=0;
2497  $object->statut=self::STATUS_DRAFT;
2498 
2499  // Clear fields
2500  $object->ref_supplier=$langs->trans("CopyOf").' '.$object->ref_supplier;
2501  $object->author = $user->id;
2502  $object->user_valid = '';
2503  $object->fk_facture_source = 0;
2504  $object->date_creation = '';
2505  $object->date_validation = '';
2506  $object->date = '';
2507  $object->date_echeance = '';
2508  $object->ref_client = '';
2509  $object->close_code = '';
2510  $object->close_note = '';
2511 
2512  // Loop on each line of new invoice
2513  foreach($object->lines as $i => $line)
2514  {
2515  if (isset($object->lines[$i]->info_bits) && ($object->lines[$i]->info_bits & 0x02) == 0x02) // We do not clone line of discounts
2516  {
2517  unset($object->lines[$i]);
2518  }
2519  }
2520 
2521  // Create clone
2522  $object->context['createfromclone'] = 'createfromclone';
2523  $result=$object->create($user);
2524 
2525  // Other options
2526  if ($result < 0)
2527  {
2528  $this->error=$object->error;
2529  $error++;
2530  }
2531 
2532  if (! $error)
2533  {
2534 
2535  }
2536 
2537  unset($object->context['createfromclone']);
2538 
2539  // End
2540  if (! $error)
2541  {
2542  $this->db->commit();
2543  return $object->id;
2544  }
2545  else
2546  {
2547  $this->db->rollback();
2548  return -1;
2549  }
2550  }
2551 
2563  public function generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
2564  {
2565  global $conf, $user, $langs;
2566 
2567  $langs->load("suppliers");
2568 
2569  // Set the model on the model name to use
2570  if (empty($modele))
2571  {
2572  if (! empty($conf->global->INVOICE_SUPPLIER_ADDON_PDF))
2573  {
2574  $modele = $conf->global->INVOICE_SUPPLIER_ADDON_PDF;
2575  }
2576  else
2577  {
2578  $modele = ''; // No default value. For supplier invoice, we allow to disable all PDF generation
2579  }
2580  }
2581 
2582  if (empty($modele))
2583  {
2584  return 0;
2585  }
2586  else
2587  {
2588  $modelpath = "core/modules/supplier_invoice/pdf/";
2589 
2590  return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
2591  }
2592  }
2593 
2598  public function getRights()
2599  {
2600  global $user;
2601 
2602  return $user->rights->fournisseur->facture;
2603  }
2604 
2613  public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
2614  {
2615  $tables = array(
2616  'facture_fourn'
2617  );
2618 
2619  return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2620  }
2621 
2627  public function hasDelay()
2628  {
2629  global $conf;
2630 
2631  $now = dol_now();
2632 
2633  if (!$this->date_echeance) {
2634  return false;
2635  }
2636 
2637  return ($this->statut == self::STATUS_VALIDATED) && ($this->date_echeance < ($now - $conf->facture->fournisseur->warning_delay));
2638  }
2639 }
2640 
2641 
2642 
2647 {
2651  public $element='facture_fourn_det';
2652 
2656  public $table_element='facture_fourn_det';
2657 
2658  public $oldline;
2659 
2664  public $ref;
2665 
2670  public $product_ref;
2671 
2677  public $ref_supplier;
2678 
2683  public $libelle;
2684 
2689  public $product_desc;
2690 
2697  public $pu_ht;
2698 
2699  public $subprice;
2700 
2705  public $pu_ttc;
2706 
2713  public $tva;
2714 
2715  public $total_tva;
2716 
2721  public $fk_facture_fourn;
2722 
2728  public $label;
2729 
2734  public $description;
2735 
2736  public $date_start;
2737  public $date_end;
2738 
2739  public $skip_update_total; // Skip update price total for special lines
2740 
2744  public $situation_percent;
2745 
2749  public $fk_prev_id;
2750 
2751  public $tva_tx;
2752  public $localtax1_tx;
2753  public $localtax2_tx;
2754  public $qty;
2755  public $remise_percent;
2756  public $total_ht;
2757  public $total_ttc;
2758  public $total_localtax1;
2759  public $total_localtax2;
2760 
2764  public $fk_product;
2765 
2766  public $product_type;
2767  public $product_label;
2768  public $info_bits;
2769 
2773  public $fk_parent_line;
2774 
2775  public $special_code;
2776  public $rang;
2777  public $localtax1_type;
2778  public $localtax2_type;
2779 
2780  // Multicurrency
2784  public $fk_multicurrency;
2785 
2786  public $multicurrency_code;
2787  public $multicurrency_subprice;
2788  public $multicurrency_total_ht;
2789  public $multicurrency_total_tva;
2790  public $multicurrency_total_ttc;
2791 
2797  public function __construct($db)
2798  {
2799  $this->db= $db;
2800  }
2801 
2808  public function fetch($rowid)
2809  {
2810  $sql = 'SELECT f.rowid, f.ref as ref_supplier, f.description, f.date_start, f.date_end, f.pu_ht, f.pu_ttc, f.qty, f.remise_percent, f.tva_tx';
2811  $sql.= ', f.localtax1_type, f.localtax2_type, f.localtax1_tx, f.localtax2_tx, f.total_localtax1, f.total_localtax2 ';
2812  $sql.= ', f.total_ht, f.tva as total_tva, f.total_ttc, f.fk_facture_fourn, f.fk_product, f.product_type, f.info_bits, f.rang, f.special_code, f.fk_parent_line, f.fk_unit';
2813  $sql.= ', p.rowid as product_id, p.ref as product_ref, p.label as label, p.description as product_desc';
2814  $sql.= ', f.multicurrency_subprice, f.multicurrency_total_ht, f.multicurrency_total_tva, multicurrency_total_ttc';
2815  $sql.= ' FROM '.MAIN_DB_PREFIX.'facture_fourn_det as f';
2816  $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON f.fk_product = p.rowid';
2817  $sql.= ' WHERE f.rowid = '.$rowid;
2818  $sql.= ' ORDER BY f.rang, f.rowid';
2819 
2820  $query = $this->db->query($sql);
2821 
2822  if (!$query) {
2823  $this->errors[] = $this->db->error();
2824  return -1;
2825  }
2826 
2827  if (!$this->db->num_rows($query)) {
2828  return 0;
2829  }
2830 
2831  $obj = $this->db->fetch_object($query);
2832 
2833  $this->id = $obj->rowid;
2834  $this->rowid = $obj->rowid;
2835  $this->fk_facture_fourn = $obj->fk_facture_fourn;
2836  $this->description = $obj->description;
2837  $this->date_start = $obj->date_start;
2838  $this->date_end = $obj->date_end;
2839  $this->product_ref = $obj->product_ref;
2840  $this->ref_supplier = $obj->ref_supplier;
2841  $this->libelle = $obj->label;
2842  $this->label = $obj->label;
2843  $this->product_desc = $obj->product_desc;
2844  $this->subprice = $obj->pu_ht;
2845  $this->pu_ht = $obj->pu_ht;
2846  $this->pu_ttc = $obj->pu_ttc;
2847  $this->tva_tx = $obj->tva_tx;
2848  $this->localtax1_tx = $obj->localtax1_tx;
2849  $this->localtax2_tx = $obj->localtax2_tx;
2850  $this->localtax1_type = $obj->localtax1_type;
2851  $this->localtax2_type = $obj->localtax2_type;
2852  $this->qty = $obj->qty;
2853  $this->remise_percent = $obj->remise_percent;
2854  $this->tva = $obj->total_tva;
2855  $this->total_ht = $obj->total_ht;
2856  $this->total_tva = $obj->total_tva;
2857  $this->total_localtax1 = $obj->total_localtax1;
2858  $this->total_localtax2 = $obj->total_localtax2;
2859  $this->total_ttc = $obj->total_ttc;
2860  $this->fk_product = $obj->fk_product;
2861  $this->product_type = $obj->product_type;
2862  $this->product_label = $obj->label;
2863  $this->info_bits = $obj->info_bits;
2864  $this->tva_npr = ($obj->info_bits & 1 == 1) ? 1 : 0;
2865  $this->fk_parent_line = $obj->fk_parent_line;
2866  $this->special_code = $obj->special_code;
2867  $this->rang = $obj->rang;
2868  $this->fk_unit = $obj->fk_unit;
2869 
2870  $this->multicurrency_subprice = $obj->multicurrency_subprice;
2871  $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
2872  $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
2873  $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
2874 
2875  $this->fetch_optionals();
2876 
2877  return 1;
2878  }
2879 
2886  public function delete($notrigger = 0)
2887  {
2888  global $user;
2889 
2890  dol_syslog(get_class($this)."::deleteline rowid=".$this->id, LOG_DEBUG);
2891 
2892  $error = 0;
2893 
2894  $this->db->begin();
2895 
2896  if (!$notrigger) {
2897  if ($this->call_trigger('LINEBILL_SUPPLIER_DELETE', $user) < 0) {
2898  $error++;
2899  }
2900  }
2901 
2902  if (!$error) {
2903  // Supprime ligne
2904  $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'facture_fourn_det ';
2905  $sql .= ' WHERE rowid = '.$this->id;
2906  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2907  $resql = $this->db->query($sql);
2908  if (!$resql) {
2909  $error++;
2910  $this->error = $this->db->lasterror();
2911  }
2912  }
2913 
2914  if (! $error)
2915  {
2916  $this->db->commit();
2917  return 1;
2918  }
2919  else
2920  {
2921  $this->db->rollback();
2922  return -1;
2923  }
2924  }
2925 
2932  public function update($notrigger = 0)
2933  {
2934  global $conf;
2935 
2936  $pu = price2num($this->pu_ht);
2937  $qty = price2num($this->qty);
2938 
2939  // Check parameters
2940  if (empty($this->qty)) $this->qty=0;
2941 
2942  if ($this->product_type < 0) {
2943  return -1;
2944  }
2945 
2946  // Clean parameters
2947  if (empty($this->remise_percent)) $this->remise_percent = 0;
2948  if (empty($this->tva_tx)) $this->tva_tx = 0;
2949  if (empty($this->localtax1_tx)) $this->localtax1_tx = 0;
2950  if (empty($this->localtax2_tx)) $this->localtax2_tx = 0;
2951 
2952  $this->db->begin();
2953 
2954  if (empty($this->fk_product))
2955  {
2956  $fk_product = "null";
2957  } else {
2958  $fk_product = $this->fk_product;
2959  }
2960 
2961  if (empty($this->fk_unit)) {
2962  $fk_unit = "null";
2963  } else {
2964  $fk_unit = "'".$this->db->escape($this->fk_unit)."'";
2965  }
2966 
2967  $sql = "UPDATE ".MAIN_DB_PREFIX."facture_fourn_det SET";
2968  $sql.= " description ='".$this->db->escape($this->description)."'";
2969  $sql.= ", ref ='".$this->db->escape($this->ref_supplier ? $this->ref_supplier : $this->ref)."'";
2970  $sql.= ", date_start = ".($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : "null");
2971  $sql.= ", date_end = ".($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : "null");
2972  $sql.= ", pu_ht = ".price2num($this->pu_ht);
2973  $sql.= ", pu_ttc = ".price2num($this->pu_ttc);
2974  $sql.= ", qty = ".price2num($this->qty);
2975  $sql.= ", remise_percent = ".price2num($this->remise_percent);
2976  $sql.= ", vat_src_code = '".$this->db->escape(empty($this->vat_src_code)?'':$this->vat_src_code)."'";
2977  $sql.= ", tva_tx = ".price2num($this->tva_tx);
2978  $sql.= ", localtax1_tx = ".price2num($this->localtax1_tx);
2979  $sql.= ", localtax2_tx = ".price2num($this->localtax2_tx);
2980  $sql.= ", localtax1_type = '".$this->db->escape($this->localtax1_type)."'";
2981  $sql.= ", localtax2_type = '".$this->db->escape($this->localtax2_type)."'";
2982  $sql.= ", total_ht = ".price2num($this->total_ht);
2983  $sql.= ", tva= ".price2num($this->total_tva);
2984  $sql.= ", total_localtax1= ".price2num($this->total_localtax1);
2985  $sql.= ", total_localtax2= ".price2num($this->total_localtax2);
2986  $sql.= ", total_ttc = ".price2num($this->total_ttc);
2987  $sql.= ", fk_product = ".$fk_product;
2988  $sql.= ", product_type = ".$this->product_type;
2989  $sql.= ", info_bits = ".$this->info_bits;
2990  $sql.= ", fk_unit = ".$fk_unit;
2991 
2992  // Multicurrency
2993  $sql.= " , multicurrency_subprice=".price2num($this->multicurrency_subprice)."";
2994  $sql.= " , multicurrency_total_ht=".price2num($this->multicurrency_total_ht)."";
2995  $sql.= " , multicurrency_total_tva=".price2num($this->multicurrency_total_tva)."";
2996  $sql.= " , multicurrency_total_ttc=".price2num($this->multicurrency_total_ttc)."";
2997 
2998  $sql.= " WHERE rowid = ".$this->id;
2999 
3000  dol_syslog(get_class($this)."::update", LOG_DEBUG);
3001  $resql = $this->db->query($sql);
3002 
3003  if (!$resql) {
3004  $this->db->rollback();
3005  $this->error = $this->db->lasterror();
3006  return -1;
3007  }
3008 
3009  $this->rowid = $this->id;
3010  $error = 0;
3011 
3012  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
3013  {
3014  $result = $this->insertExtraFields();
3015  if ($result < 0)
3016  {
3017  $error++;
3018  }
3019  }
3020 
3021  if (! $error && ! $notrigger)
3022  {
3023  global $langs, $user;
3024 
3025  // Call trigger
3026  if ($this->call_trigger('LINEBILL_SUPPLIER_UPDATE',$user) < 0) {
3027  $this->db->rollback();
3028  return -1;
3029  }
3030  // End call triggers
3031  }
3032 
3033  if ($error) {
3034  $this->db->rollback();
3035  return -1;
3036  }
3037 
3038  $this->db->commit();
3039  return 1;
3040  }
3041 
3048  public function insert($notrigger=0)
3049  {
3050  global $user,$conf;
3051 
3052  $error=0;
3053 
3054  dol_syslog(get_class($this)."::insert rang=".$this->rang, LOG_DEBUG);
3055 
3056  // Clean parameters
3057  $this->desc=trim($this->desc);
3058  if (empty($this->tva_tx)) $this->tva_tx=0;
3059  if (empty($this->localtax1_tx)) $this->localtax1_tx=0;
3060  if (empty($this->localtax2_tx)) $this->localtax2_tx=0;
3061  if (empty($this->localtax1_type)) $this->localtax1_type='0';
3062  if (empty($this->localtax2_type)) $this->localtax2_type='0';
3063  if (empty($this->total_localtax1)) $this->total_localtax1=0;
3064  if (empty($this->total_localtax2)) $this->total_localtax2=0;
3065  if (empty($this->rang)) $this->rang=0;
3066  if (empty($this->remise_percent)) $this->remise_percent=0;
3067  if (empty($this->info_bits)) $this->info_bits=0;
3068  if (empty($this->subprice)) $this->subprice=0;
3069  if (empty($this->special_code)) $this->special_code=0;
3070  if (empty($this->fk_parent_line)) $this->fk_parent_line=0;
3071  if (! isset($this->situation_percent) || $this->situation_percent > 100 || (string) $this->situation_percent == '') $this->situation_percent = 100;
3072 
3073  if (empty($this->pa_ht)) $this->pa_ht=0;
3074  if (empty($this->multicurrency_subprice)) $this->multicurrency_subprice=0;
3075  if (empty($this->multicurrency_total_ht)) $this->multicurrency_total_ht=0;
3076  if (empty($this->multicurrency_total_tva)) $this->multicurrency_total_tva=0;
3077  if (empty($this->multicurrency_total_ttc)) $this->multicurrency_total_ttc=0;
3078 
3079 
3080  // Check parameters
3081  if ($this->product_type < 0)
3082  {
3083  $this->error='ErrorProductTypeMustBe0orMore';
3084  return -1;
3085  }
3086  if (! empty($this->fk_product))
3087  {
3088  // Check product exists
3089  $result=Product::isExistingObject('product', $this->fk_product);
3090  if ($result <= 0)
3091  {
3092  $this->error='ErrorProductIdDoesNotExists';
3093  return -1;
3094  }
3095  }
3096 
3097  $this->db->begin();
3098 
3099  // Insertion dans base de la ligne
3100  $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element;
3101  $sql.= ' (fk_facture_fourn, fk_parent_line, label, description, ref, qty,';
3102  $sql.= ' vat_src_code, tva_tx, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type,';
3103  $sql.= ' fk_product, product_type, remise_percent, pu_ht, pu_ttc,';
3104  $sql.= ' date_start, date_end, fk_code_ventilation, rang, special_code,';
3105  $sql.= ' info_bits, total_ht, tva, total_ttc, total_localtax1, total_localtax2, fk_unit';
3106  $sql.= ', fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc';
3107  $sql.= ')';
3108  $sql.= " VALUES (".$this->fk_facture_fourn.",";
3109  $sql.= " ".($this->fk_parent_line>0?"'".$this->db->escape($this->fk_parent_line)."'":"null").",";
3110  $sql.= " ".(! empty($this->label)?"'".$this->db->escape($this->label)."'":"null").",";
3111  $sql.= " '".$this->db->escape($this->desc ? $this->desc : $this->description)."',";
3112  $sql.= " '".$this->db->escape($this->ref_supplier)."',";
3113  $sql.= " ".price2num($this->qty).",";
3114 
3115  $sql.= " ".(empty($this->vat_src_code)?"''":"'".$this->db->escape($this->vat_src_code)."'").",";
3116  $sql.= " ".price2num($this->tva_tx).",";
3117  $sql.= " ".price2num($this->localtax1_tx).",";
3118  $sql.= " ".price2num($this->localtax2_tx).",";
3119  $sql.= " '".$this->db->escape($this->localtax1_type)."',";
3120  $sql.= " '".$this->db->escape($this->localtax2_type)."',";
3121  $sql.= ' '.(! empty($this->fk_product)?$this->fk_product:"null").',';
3122  $sql.= " ".$this->product_type.",";
3123  $sql.= " ".price2num($this->remise_percent).",";
3124  $sql.= " ".price2num($this->subprice).",";
3125  $sql.= " ".(! empty($this->qty)?price2num($this->total_ttc / $this->qty):price2num($this->total_ttc)).",";
3126  $sql.= " ".(! empty($this->date_start)?"'".$this->db->idate($this->date_start)."'":"null").",";
3127  $sql.= " ".(! empty($this->date_end)?"'".$this->db->idate($this->date_end)."'":"null").",";
3128  $sql.= ' '.(! empty($this->fk_code_ventilation)?$this->fk_code_ventilation:0).',';
3129  $sql.= ' '.$this->rang.',';
3130  $sql.= ' '.$this->special_code.',';
3131  $sql.= " '".$this->db->escape($this->info_bits)."',";
3132  $sql.= " ".price2num($this->total_ht).",";
3133  $sql.= " ".price2num($this->total_tva).",";
3134  $sql.= " ".price2num($this->total_ttc).",";
3135  $sql.= " ".price2num($this->total_localtax1).",";
3136  $sql.= " ".price2num($this->total_localtax2);
3137  $sql .= ", ".(!$this->fk_unit ? 'NULL' : $this->fk_unit);
3138  $sql.= ", ".(int) $this->fk_multicurrency;
3139  $sql.= ", '".$this->db->escape($this->multicurrency_code)."'";
3140  $sql.= ", ".price2num($this->multicurrency_subprice);
3141  $sql.= ", ".price2num($this->multicurrency_total_ht);
3142  $sql.= ", ".price2num($this->multicurrency_total_tva);
3143  $sql.= ", ".price2num($this->multicurrency_total_ttc);
3144  $sql.= ')';
3145 
3146  $resql=$this->db->query($sql);
3147  if ($resql)
3148  {
3149  $this->id=$this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
3150  $this->rowid=$this->id; // backward compatibility
3151 
3152  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
3153  {
3154  $result=$this->insertExtraFields();
3155  if ($result < 0)
3156  {
3157  $error++;
3158  }
3159  }
3160 
3161  if (! $error && ! $notrigger)
3162  {
3163  // Call trigger
3164  $result=$this->call_trigger('LINEBILL_SUPPLIER_CREATE',$user);
3165  if ($result < 0)
3166  {
3167  $this->db->rollback();
3168  return -2;
3169  }
3170  // End call triggers
3171  }
3172 
3173  $this->db->commit();
3174  return $this->id;
3175  }
3176  else
3177  {
3178  $this->error=$this->db->error();
3179  $this->db->rollback();
3180  return -2;
3181  }
3182  }
3183 
3184  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
3190  function update_total()
3191  {
3192  // phpcs:enable
3193  $this->db->begin();
3194 
3195  // Mise a jour ligne en base
3196  $sql = "UPDATE ".MAIN_DB_PREFIX."facture_fourn_det SET";
3197  $sql.= " total_ht='".price2num($this->total_ht)."'";
3198  $sql.= ", tva='".price2num($this->total_tva)."'";
3199  $sql.= ", total_localtax1='".price2num($this->total_localtax1)."'";
3200  $sql.= ", total_localtax2='".price2num($this->total_localtax2)."'";
3201  $sql.= ", total_ttc='".price2num($this->total_ttc)."'";
3202  $sql.= " WHERE rowid = ".$this->rowid;
3203 
3204  dol_syslog("FactureFournisseurLigne.class.php::update_total", LOG_DEBUG);
3205 
3206  $resql=$this->db->query($sql);
3207  if ($resql)
3208  {
3209  $this->db->commit();
3210  return 1;
3211  }
3212  else
3213  {
3214  $this->error=$this->db->error();
3215  $this->db->rollback();
3216  return -2;
3217  }
3218  }
3219  }
print $object label
hash of file content (md5_file(dol_osencode($destfull))
Definition: edit.php:153
static replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
const TYPE_STANDARD
Standard invoice.
Class to manage stock movements.
update($user=null, $notrigger=0)
Update database.
insert($notrigger=0)
Insert line into database.
info($id)
Charge les informations d&#39;ordre info dans l&#39;objet facture.
initAsSpecimen($option='')
Initialise an instance with random values.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding &#39;...&#39; if string larger than length.
if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) if(! empty($conf->don->enabled) && $user->rights->societe->lire) if(! empty($conf->tax->enabled) && $user->rights->tax->charges->lire) if(! empty($conf->facture->enabled) &&! empty($conf->commande->enabled) && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1053
static getIdFromCode(&$db, $code)
Get id of currency from code.
const TYPE_DEPOSIT
Deposit invoice.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid='')
Delete all links between an object $this.
</td >< td class="liste_titre" align="right"></td ></tr >< tr class="liste_titre">< input type="checkbox" onClick="toggle(this)"/> Ref p ref Label p label Duration p duration warehouseinternal SELECT description FROM product_lang WHERE qty< br > qty qty qty StockTooLow img yes disabled img no img no< tr class="oddeven">< td >< input type="checkbox" class="check" name="' . $i . '"' . $disabled . '></td >< td >< input type="checkbox" class="check" name="choose'.$i.'"></td >< td class="nowrap"></td >< td >< input type="hidden" name="desc' . $i . '" value="' . dol_escape_htmltag($objp-> description
Only used if Module[ID]Desc translation string is not found.
Definition: replenish.php:573
list_replacable_supplier_invoices($socid=0)
Renvoi liste des factures remplacables Statut validee ou abandonnee pour raison autre + non payee + a...
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
Class to manage line invoices.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart)
Return a path to have a the directory according to object where files are stored. ...
if(! empty($search_group)) natural_search(array("g.nom" g note
Definition: list.php:123
Class to manage products or services.
Class to manage Dolibarr users.
Definition: user.class.php:41
Class to manage Dolibarr database access.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
const TYPE_REPLACEMENT
Replacement invoice.
load_board($user)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
getNextNumRef($soc, $mode='next')
Return next reference of supplier invoice not already used (or last reference) according to numbering...
dol_print_error($db='', $error='', $errors=null)
Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remonte...
const STATUS_VALIDATED
Validated (need to be paid)
Class to manage suppliers invoices.
load_state_board()
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
update_total()
Mise a jour de l&#39;objet ligne de commande en base.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
type
Definition: viewcat.php:284
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
set_unpaid($user)
Tag la facture comme non payee completement + appel trigger BILL_UNPAYED Fonction utilisee quand un p...
line_max($fk_parent_line=0)
Get max value used for position of line (rang)
getNomUrl($withpicto=0, $option='', $max=0, $short=0, $moretitle='', $notooltip=0, $save_lastsearch_value=-1)
Return clicable name (with picto eventually)
set_draft($user, $idwarehouse=-1)
Set draft status.
static isExistingObject($element, $id, $ref='', $ref_ext='')
Check an object id/ref exists If you don&#39;t need/want to instantiate object and just need to know if o...
Classe permettant la generation de composants html autre Only common components are here...
update_price($exclspec=0, $roundingadjust='none', $nodatabaseupdate=0, $seller=null)
Update total_ht, total_ttc, total_vat, total_localtax1, total_localtax2 for an object (sum of lines)...
static commonReplaceThirdparty(DoliDB $db, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
list_qualified_avoir_supplier_invoices($socid=0)
Renvoi liste des factures qualifiables pour correction par avoir Les factures qui respectent les regl...
getRights()
Returns the rights used for this class.
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories) ...
Definition: files.lib.php:1273
fetch($rowid)
Retrieves a supplier invoice line.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1)
Remove a file or several files with a mask.
Definition: files.lib.php:1139
deleteExtraFields()
Delete all extra fields values for the current object.
insert_discount($idremise)
Add a discount line into an invoice (as an invoice line) using an existing absolute discount (Consume...
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:59
dol_now($mode='gmt')
Return date for now.
update($notrigger=0)
Update a supplier invoice line.
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...
set_paid($user, $close_code='', $close_note='')
Tag invoice as a payed invoice.
deleteline($rowid, $notrigger=0)
Delete a detail line from database.
calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller='', $localtaxes_array='', $progress=100, $multicurrency_tx=1, $pu_devise=0)
Calculate totals (net, vat, ...) of a line.
Definition: price.lib.php:85
Superclass for invoices classes.
const STATUS_CLOSED
Classified paid.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages...
const TYPE_CREDIT_NOTE
Credit note invoice.
validate($user, $force_number='', $idwarehouse=0, $notrigger=0)
Tag invoice as validated + call trigger BILL_VALIDATE.
line_order($renum=false, $rowidorder='ASC', $fk_parent_line=true)
Save a new position (field rang) for details lines.
Class to manage absolute discounts.
hasDelay()
Is the payment of the supplier invoice having a delay?
const STATUS_ABANDONED
Classified abandoned and no payment done.
fetch($id='', $ref='')
Load object in memory from database.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template model.
call_trigger($trigger_name, $user)
Call trigger based on this instance.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
createFromClone($fromid, $invertdetail=0)
Load an object from its id and create a new one in database.
add_object_linked($origin=null, $origin_id=null)
Add objects linked in llx_element_element.
addline($desc, $pu, $txtva, $txlocaltax1, $txlocaltax2, $qty, $fk_product=0, $remise_percent=0, $date_start='', $date_end='', $ventil=0, $info_bits='', $price_base_type='HT', $type=0, $rang=-1, $notrigger=false, $array_options=0, $fk_unit=null, $origin_id=0, $pu_ht_devise=0, $ref_supplier='')
Ajoute une ligne de facture (associe a aucun produit/service predefini) Les parametres sont deja cens...
create($user)
Create supplier invoice into database.
updateline($id, $desc, $pu, $vatrate, $txlocaltax1=0, $txlocaltax2=0, $qty=1, $idproduct=0, $price_base_type='HT', $info_bits=0, $type=0, $remise_percent=0, $notrigger=false, $date_start='', $date_end='', $array_options=0, $fk_unit=null, $pu_ht_devise=0, $ref_supplier='')
Update a line detail into database.
price2num($amount, $rounding='', $alreadysqlnb=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
fetch_lines()
Load this->lines.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
Class to manage invoice lines.
static getIdAndTxFromCode(&$db, $code, $date_document='')
Get id and rate of currency from code.