44require_once DOL_DOCUMENT_ROOT.
'/core/class/commoninvoice.class.php';
45require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobjectline.class.php';
46require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
47require_once DOL_DOCUMENT_ROOT.
'/societe/class/client.class.php';
48require_once DOL_DOCUMENT_ROOT.
'/margin/lib/margins.lib.php';
49require_once DOL_DOCUMENT_ROOT.
'/multicurrency/class/multicurrency.class.php';
51if (isModEnabled(
'accounting')) {
52 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formaccounting.class.php';
54if (isModEnabled(
'accounting')) {
55 require_once DOL_DOCUMENT_ROOT.
'/accountancy/class/accountingaccount.class.php';
66 public $element =
'facture';
71 public $table_element =
'facture';
76 public $table_element_line =
'facturedet';
81 public $class_element_line =
'FactureLigne';
86 public $fk_element =
'fk_facture';
91 public $picto =
'bill';
97 public $ismultientitymanaged = 1;
102 public $isextrafieldmanaged = 1;
108 public $restrictiononfksoc = 1;
127 public $fk_user_author;
139 public $fk_user_valid;
144 public $fk_user_modif;
151 public $delivery_date;
163 public $ref_customer;
167 public $total_localtax1;
168 public $total_localtax2;
170 public $revenuestamp;
187 public $linked_objects = array();
197 public $lines = array();
203 public $extraparams = array();
210 public $date_pointoftax;
216 public $situation_cycle_ref;
221 public $situation_counter;
226 public $situation_final;
231 public $tab_previous_situation_invoice = array();
236 public $tab_next_situation_invoice = array();
246 public $retained_warranty;
251 public $retained_warranty_date_limit;
256 public $retained_warranty_fk_cond_reglement;
261 public $availability_id;
263 public $date_closing;
273 public $remise_percent;
304 public $fields = array(
305 'rowid' =>array(
'type'=>
'integer',
'label'=>
'TechnicalID',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>1),
306 'ref' =>array(
'type'=>
'varchar(30)',
'label'=>
'Ref',
'enabled'=>1,
'visible'=>1,
'notnull'=>1,
'showoncombobox'=>1,
'position'=>5),
307 'entity' =>array(
'type'=>
'integer',
'label'=>
'Entity',
'default'=>1,
'enabled'=>1,
'visible'=>-2,
'notnull'=>1,
'position'=>20,
'index'=>1),
308 'ref_client' =>array(
'type'=>
'varchar(255)',
'label'=>
'RefCustomer',
'enabled'=>1,
'visible'=>-1,
'position'=>10),
309 'ref_ext' =>array(
'type'=>
'varchar(255)',
'label'=>
'Ref ext',
'enabled'=>1,
'visible'=>0,
'position'=>12),
310 'type' =>array(
'type'=>
'smallint(6)',
'label'=>
'Type',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>15),
311 'subtype' =>array(
'type'=>
'smallint(6)',
'label'=>
'InvoiceSubtype',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>15),
313 'fk_soc' =>array(
'type'=>
'integer:Societe:societe/class/societe.class.php',
'label'=>
'ThirdParty',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>50),
314 'datef' =>array(
'type'=>
'date',
'label'=>
'DateInvoice',
'enabled'=>1,
'visible'=>1,
'position'=>20),
315 'date_valid' =>array(
'type'=>
'date',
'label'=>
'DateValidation',
'enabled'=>1,
'visible'=>-1,
'position'=>22),
316 'date_lim_reglement' =>array(
'type'=>
'date',
'label'=>
'DateDue',
'enabled'=>1,
'visible'=>1,
'position'=>25),
317 'date_closing' =>array(
'type'=>
'datetime',
'label'=>
'Date closing',
'enabled'=>1,
'visible'=>-1,
'position'=>30),
318 'paye' =>array(
'type'=>
'smallint(6)',
'label'=>
'InvoicePaidCompletely',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>80),
323 'close_code' =>array(
'type'=>
'varchar(16)',
'label'=>
'EarlyClosingReason',
'enabled'=>1,
'visible'=>-1,
'position'=>92),
324 'close_note' =>array(
'type'=>
'varchar(128)',
'label'=>
'EarlyClosingComment',
'enabled'=>1,
'visible'=>-1,
'position'=>93),
325 'total_ht' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountHT',
'enabled'=>1,
'visible'=>1,
'position'=>95,
'isameasure'=>1),
326 'total_tva' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountVAT',
'enabled'=>1,
'visible'=>-1,
'position'=>100,
'isameasure'=>1),
327 'localtax1' =>array(
'type'=>
'double(24,8)',
'label'=>
'LT1',
'enabled'=>1,
'visible'=>-1,
'position'=>110,
'isameasure'=>1),
328 'localtax2' =>array(
'type'=>
'double(24,8)',
'label'=>
'LT2',
'enabled'=>1,
'visible'=>-1,
'position'=>120,
'isameasure'=>1),
329 'revenuestamp' =>array(
'type'=>
'double(24,8)',
'label'=>
'RevenueStamp',
'enabled'=>1,
'visible'=>-1,
'position'=>115,
'isameasure'=>1),
330 'total_ttc' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountTTC',
'enabled'=>1,
'visible'=>1,
'position'=>130,
'isameasure'=>1),
331 'fk_facture_source' =>array(
'type'=>
'integer',
'label'=>
'SourceInvoice',
'enabled'=>1,
'visible'=>-1,
'position'=>170),
332 'fk_projet' =>array(
'type'=>
'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)',
'label'=>
'Project',
'enabled'=>1,
'visible'=>-1,
'position'=>175),
333 'fk_account' =>array(
'type'=>
'integer',
'label'=>
'Fk account',
'enabled'=>1,
'visible'=>-1,
'position'=>180),
334 'fk_currency' =>array(
'type'=>
'varchar(3)',
'label'=>
'CurrencyCode',
'enabled'=>1,
'visible'=>-1,
'position'=>185),
335 'fk_cond_reglement' =>array(
'type'=>
'integer',
'label'=>
'PaymentTerm',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>190),
336 'fk_mode_reglement' =>array(
'type'=>
'integer',
'label'=>
'PaymentMode',
'enabled'=>1,
'visible'=>-1,
'position'=>195),
337 'note_private' =>array(
'type'=>
'html',
'label'=>
'NotePrivate',
'enabled'=>1,
'visible'=>0,
'position'=>205),
338 'note_public' =>array(
'type'=>
'html',
'label'=>
'NotePublic',
'enabled'=>1,
'visible'=>0,
'position'=>210),
339 'model_pdf' =>array(
'type'=>
'varchar(255)',
'label'=>
'Model pdf',
'enabled'=>1,
'visible'=>0,
'position'=>215),
340 'extraparams' =>array(
'type'=>
'varchar(255)',
'label'=>
'Extraparams',
'enabled'=>1,
'visible'=>-1,
'position'=>225),
341 'situation_cycle_ref' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation cycle ref',
'enabled'=>
'$conf->global->INVOICE_USE_SITUATION',
'visible'=>-1,
'position'=>230),
342 'situation_counter' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation counter',
'enabled'=>
'$conf->global->INVOICE_USE_SITUATION',
'visible'=>-1,
'position'=>235),
343 'situation_final' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation final',
'enabled'=>
'empty($conf->global->INVOICE_USE_SITUATION) ? 0 : 1',
'visible'=>-1,
'position'=>240),
344 'retained_warranty' =>array(
'type'=>
'double',
'label'=>
'Retained warranty',
'enabled'=>
'$conf->global->INVOICE_USE_RETAINED_WARRANTY',
'visible'=>-1,
'position'=>245),
345 'retained_warranty_date_limit' =>array(
'type'=>
'date',
'label'=>
'Retained warranty date limit',
'enabled'=>
'$conf->global->INVOICE_USE_RETAINED_WARRANTY',
'visible'=>-1,
'position'=>250),
346 'retained_warranty_fk_cond_reglement' =>array(
'type'=>
'integer',
'label'=>
'Retained warranty fk cond reglement',
'enabled'=>
'$conf->global->INVOICE_USE_RETAINED_WARRANTY',
'visible'=>-1,
'position'=>255),
347 'fk_incoterms' =>array(
'type'=>
'integer',
'label'=>
'IncotermCode',
'enabled'=>
'$conf->incoterm->enabled',
'visible'=>-1,
'position'=>260),
348 'location_incoterms' =>array(
'type'=>
'varchar(255)',
'label'=>
'IncotermLabel',
'enabled'=>
'$conf->incoterm->enabled',
'visible'=>-1,
'position'=>265),
349 'date_pointoftax' =>array(
'type'=>
'date',
'label'=>
'DatePointOfTax',
'enabled'=>
'$conf->global->INVOICE_POINTOFTAX_DATE',
'visible'=>-1,
'position'=>270),
350 'fk_multicurrency' =>array(
'type'=>
'integer',
'label'=>
'MulticurrencyID',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>275),
351 'multicurrency_code' =>array(
'type'=>
'varchar(255)',
'label'=>
'Currency',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>280),
352 'multicurrency_tx' =>array(
'type'=>
'double(24,8)',
'label'=>
'CurrencyRate',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>285,
'isameasure'=>1),
353 'multicurrency_total_ht' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountHT',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>290,
'isameasure'=>1),
354 'multicurrency_total_tva' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountVAT',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>291,
'isameasure'=>1),
355 'multicurrency_total_ttc' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountTTC',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>292,
'isameasure'=>1),
356 'fk_fac_rec_source' =>array(
'type'=>
'integer',
'label'=>
'RecurringInvoiceSource',
'enabled'=>1,
'visible'=>-1,
'position'=>305),
357 'last_main_doc' =>array(
'type'=>
'varchar(255)',
'label'=>
'LastMainDoc',
'enabled'=>1,
'visible'=>-1,
'position'=>310),
358 'module_source' =>array(
'type'=>
'varchar(32)',
'label'=>
'POSModule',
'enabled'=>
"(isModEnabled('cashdesk') || isModEnabled('takepos') || getDolGlobalInt('INVOICE_SHOW_POS'))",
'visible'=>-1,
'position'=>315),
359 'pos_source' =>array(
'type'=>
'varchar(32)',
'label'=>
'POSTerminal',
'enabled'=>
"(isModEnabled('cashdesk') || isModEnabled('takepos') || getDolGlobalInt('INVOICE_SHOW_POS'))",
'visible'=>-1,
'position'=>320),
360 'datec' =>array(
'type'=>
'datetime',
'label'=>
'DateCreation',
'enabled'=>1,
'visible'=>-1,
'position'=>500),
361 'tms' =>array(
'type'=>
'timestamp',
'label'=>
'DateModificationShort',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>502),
362 'fk_user_author' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserAuthor',
'enabled'=>1,
'visible'=>-1,
'position'=>506),
363 'fk_user_modif' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserModif',
'enabled'=>1,
'visible'=>-1,
'notnull'=>-1,
'position'=>508),
364 'fk_user_valid' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserValidation',
'enabled'=>1,
'visible'=>-1,
'position'=>510),
365 'fk_user_closing' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserClosing',
'enabled'=>1,
'visible'=>-1,
'position'=>512),
366 'import_key' =>array(
'type'=>
'varchar(14)',
'label'=>
'ImportId',
'enabled'=>1,
'visible'=>-2,
'position'=>900),
367 'fk_statut' =>array(
'type'=>
'smallint(6)',
'label'=>
'Status',
'enabled'=>1,
'visible'=>1,
'notnull'=>1,
'position'=>1000,
'arrayofkeyval'=>array(0=>
'Draft', 1=>
'Validated', 2=>
'Paid', 3=>
'Abandonned')),
429 const CLOSECODE_DISCOUNTVAT =
'discount_vat';
430 const CLOSECODE_BADDEBT =
'badcustomer';
431 const CLOSECODE_BANKCHARGE =
'bankcharge';
432 const CLOSECODE_OTHER =
'other';
434 const CLOSECODE_ABANDONED =
'abandon';
435 const CLOSECODE_REPLACED =
'replaced';
458 public function create(
User $user, $notrigger = 0, $forceduedate = 0)
460 global $langs, $conf, $mysoc, $hookmanager;
464 if (empty($this->
type)) {
468 $this->ref_client = trim($this->ref_client);
470 $this->note = (isset($this->note) ? trim($this->note) : trim($this->note_private));
471 $this->note_private = (isset($this->note_private) ? trim($this->note_private) :
'');
472 $this->note_public = (isset($this->note_public) ? trim($this->note_public) :
'');
473 if (!$this->cond_reglement_id) {
474 $this->cond_reglement_id = 0;
476 if (!$this->mode_reglement_id) {
477 $this->mode_reglement_id = 0;
482 if (!empty($this->multicurrency_code)) {
484 if (empty($this->multicurrency_tx)) {
492 $this->fk_multicurrency = 0;
494 if (empty($this->fk_multicurrency)) {
495 $this->multicurrency_code = $conf->currency;
496 $this->fk_multicurrency = 0;
497 $this->multicurrency_tx = 1;
500 dol_syslog(get_class($this).
"::create user=".$user->id.
" date=".$this->date);
503 if (empty($this->date)) {
504 $this->error =
"Try to create an invoice with an empty parameter (date)";
505 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
509 $result = $soc->fetch($this->socid);
511 $this->error =
"Failed to fetch company: ".$soc->error;
512 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
517 $this->date_creation = $now;
521 $originaldatewhen =
null;
522 $nextdatewhen =
null;
523 $previousdaynextdatewhen =
null;
526 if ($this->fac_rec > 0) {
527 $this->fk_fac_rec_source = $this->fac_rec;
529 require_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture-rec.class.php';
531 $result = $_facrec->fetch($this->fac_rec);
532 $result = $_facrec->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 0);
535 $originaldatewhen = $_facrec->date_when;
536 $nextdatewhen =
null;
537 $previousdaynextdatewhen =
null;
538 if ($originaldatewhen) {
539 $nextdatewhen =
dol_time_plus_duree($originaldatewhen, $_facrec->frequency, $_facrec->unit_frequency);
543 if (!empty($_facrec->frequency)) {
544 $this->socid = $_facrec->socid;
546 $this->entity = $_facrec->entity;
549 $this->fk_project =
GETPOST(
'projectid',
'int') > 0 ? ((int)
GETPOST(
'projectid',
'int')) : $_facrec->fk_project;
550 $this->note_public = GETPOSTISSET(
'note_public') ?
GETPOST(
'note_public',
'restricthtml') : $_facrec->note_public;
551 $this->note_private = GETPOSTISSET(
'note_private') ?
GETPOST(
'note_private',
'restricthtml') : $_facrec->note_private;
552 $this->model_pdf = GETPOSTISSET(
'model') ?
GETPOST(
'model',
'alpha') : $_facrec->model_pdf;
553 $this->cond_reglement_id =
GETPOST(
'cond_reglement_id',
'int') > 0 ? ((int)
GETPOST(
'cond_reglement_id',
'int')) : $_facrec->cond_reglement_id;
554 $this->mode_reglement_id =
GETPOST(
'mode_reglement_id',
'int') > 0 ? ((int)
GETPOST(
'mode_reglement_id',
'int')) : $_facrec->mode_reglement_id;
555 $this->fk_account =
GETPOST(
'fk_account') > 0 ? ((int)
GETPOST(
'fk_account')) : $_facrec->fk_account;
558 $this->total_ht = $_facrec->total_ht;
559 $this->total_ttc = $_facrec->total_ttc;
564 $this->fk_incoterms = $_facrec->fk_incoterms;
565 $this->location_incoterms = $_facrec->location_incoterms;
571 $this->ref_client = trim($this->ref_client);
572 $this->ref_customer = trim($this->ref_customer);
573 $this->note_public = trim($this->note_public);
574 $this->note_private = trim($this->note_private);
575 $this->note_private =
dol_concatdesc($this->note_private, $langs->trans(
"GeneratedFromRecurringInvoice", $_facrec->ref));
577 $this->array_options = $_facrec->array_options;
579 if (!$this->mode_reglement_id) {
580 $this->mode_reglement_id = 0;
585 $this->linked_objects = $_facrec->linkedObjectsIds;
590 if ($_facrec->frequency > 0) {
591 dol_syslog(
"This is a recurring invoice so we set date_last_gen and next date_when");
592 if (empty($_facrec->date_when)) {
593 $_facrec->date_when = $now;
595 $next_date = $_facrec->getNextDate();
596 $result = $_facrec->setValueFrom(
'date_last_gen', $now,
'',
null,
'date',
'', $user,
'');
598 $result = $_facrec->setNextDate($next_date, 1);
602 $outputlangs = $langs;
605 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && empty($newlang) && isset($this->thirdparty->default_lang)) {
606 $newlang = $this->thirdparty->default_lang;
608 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && empty($newlang) && isset($this->default_lang)) {
609 $newlang = $this->default_lang;
611 if (!empty($newlang)) {
613 $outputlangs->setDefaultLang($newlang);
619 $substitutionarray[
'__INVOICE_MONTH__'] =
dol_print_date($this->date,
'%m');
622 $substitutionarray[
'__INVOICE_MONTH_TEXT__'] =
dol_print_date($this->date,
'%B');
625 $substitutionarray[
'__INVOICE_YEAR__'] =
dol_print_date($this->date,
'%Y');
628 $substitutionarray[
'__INVOICE_DATE_NEXT_INVOICE_BEFORE_GEN__'] = (isset($originaldatewhen) ?
dol_print_date($originaldatewhen,
'dayhour') :
'');
629 $substitutionarray[
'__INVOICE_DATE_NEXT_INVOICE_AFTER_GEN__'] = (isset($nextdatewhen) ?
dol_print_date($nextdatewhen,
'dayhour') :
'');
630 $substitutionarray[
'__INVOICE_PREVIOUS_DATE_NEXT_INVOICE_AFTER_GEN__'] = (isset($previousdaynextdatewhen) ?
dol_print_date($previousdaynextdatewhen,
'dayhour') :
'');
631 $substitutionarray[
'__INVOICE_COUNTER_CURRENT__'] = $_facrec->nb_gen_done;
632 $substitutionarray[
'__INVOICE_COUNTER_MAX__'] = $_facrec->nb_gen_max;
643 if (empty($forceduedate)) {
649 $this->date_lim_reglement = $duedate;
651 $this->date_lim_reglement = $forceduedate;
655 $socid = $this->socid;
657 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"facture (";
666 $sql .=
", date_pointoftax";
667 $sql .=
", note_private";
668 $sql .=
", note_public";
669 $sql .=
", ref_client";
670 $sql .=
", fk_account";
671 $sql .=
", module_source, pos_source, fk_fac_rec_source, fk_facture_source, fk_user_author, fk_projet";
672 $sql .=
", fk_cond_reglement, fk_mode_reglement, date_lim_reglement, model_pdf";
673 $sql .=
", situation_cycle_ref, situation_counter, situation_final";
674 $sql .=
", fk_incoterms, location_incoterms";
675 $sql .=
", fk_multicurrency";
676 $sql .=
", multicurrency_code";
677 $sql .=
", multicurrency_tx";
678 $sql .=
", retained_warranty";
679 $sql .=
", retained_warranty_date_limit";
680 $sql .=
", retained_warranty_fk_cond_reglement";
684 $sql .=
", ".setEntity($this);
685 $sql .=
", ".($this->ref_ext ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
686 $sql .=
", '".$this->db->escape($this->
type).
"'";
687 $sql .=
", ".($this->subtype ?
"'".$this->db->escape($this->subtype).
"'" :
"null");
688 $sql .=
", ".((int) $socid);
689 $sql .=
", '".$this->db->idate($this->date_creation).
"'";
690 $sql .=
", '".$this->db->idate($this->date).
"'";
691 $sql .=
", ".(empty($this->date_pointoftax) ?
"null" :
"'".$this->db->idate($this->date_pointoftax).
"'");
692 $sql .=
", ".($this->note_private ?
"'".$this->db->escape($this->note_private).
"'" :
"null");
693 $sql .=
", ".($this->note_public ?
"'".$this->db->escape($this->note_public).
"'" :
"null");
694 $sql .=
", ".($this->ref_customer ?
"'".$this->db->escape($this->ref_customer).
"'" : ($this->ref_client ?
"'".$this->db->escape($this->ref_client).
"'" :
"null"));
695 $sql .=
", ".($this->fk_account > 0 ? $this->fk_account :
'NULL');
696 $sql .=
", ".($this->module_source ?
"'".$this->db->escape($this->module_source).
"'" :
"null");
697 $sql .=
", ".($this->pos_source !=
'' ?
"'".$this->db->escape($this->pos_source).
"'" :
"null");
698 $sql .=
", ".($this->fk_fac_rec_source ?
"'".$this->db->escape($this->fk_fac_rec_source).
"'" :
"null");
699 $sql .=
", ".($this->fk_facture_source ?
"'".$this->db->escape($this->fk_facture_source).
"'" :
"null");
700 $sql .=
", ".($user->id > 0 ? (int) $user->id :
"null");
701 $sql .=
", ".($this->fk_project ? $this->fk_project :
"null");
702 $sql .=
", ".((int) $this->cond_reglement_id);
703 $sql .=
", ".((int) $this->mode_reglement_id);
704 $sql .=
", '".$this->db->idate($this->date_lim_reglement).
"'";
705 $sql .=
", ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null");
706 $sql .=
", ".($this->situation_cycle_ref ?
"'".$this->db->escape($this->situation_cycle_ref).
"'" :
"null");
707 $sql .=
", ".($this->situation_counter ?
"'".$this->db->escape($this->situation_counter).
"'" :
"null");
708 $sql .=
", ".($this->situation_final ? $this->situation_final : 0);
709 $sql .=
", ".(int) $this->fk_incoterms;
710 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
711 $sql .=
", ".(int) $this->fk_multicurrency;
712 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
713 $sql .=
", ".(float) $this->multicurrency_tx;
714 $sql .=
", ".(empty($this->retained_warranty) ?
"0" : $this->db->escape($this->retained_warranty));
715 $sql .=
", ".(!empty($this->retained_warranty_date_limit) ?
"'".$this->db->idate($this->retained_warranty_date_limit).
"'" :
'NULL');
716 $sql .=
", ".(int) $this->retained_warranty_fk_cond_reglement;
719 $resql = $this->db->query($sql);
721 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
'facture');
724 $this->
ref =
'(PROV'.$this->id.
')';
725 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"facture SET ref='".$this->db->escape($this->
ref).
"' WHERE rowid=".((int) $this->
id);
727 $resql = $this->db->query($sql);
732 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {
733 $this->linked_objects = $this->linkedObjectsIds;
737 if (!$error && $this->
id && !empty($this->linked_objects) && is_array($this->linked_objects)) {
738 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
739 if (is_array($tmp_origin_id)) {
740 foreach ($tmp_origin_id as $origin_id) {
743 $this->error = $this->db->lasterror();
748 $origin_id = $tmp_origin_id;
751 $this->error = $this->db->lasterror();
759 if (!$error && $this->
id &&
getDolGlobalString(
'MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN') && !empty($this->origin) && !empty($this->origin_id)) {
760 $originforcontact = $this->origin;
761 $originidforcontact = $this->origin_id;
762 if ($originforcontact ==
'shipping') {
763 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expedition.class.php';
765 $exp->fetch($this->origin_id);
766 $exp->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 0);
767 if (count($exp->linkedObjectsIds[
'commande']) > 0) {
768 foreach ($exp->linkedObjectsIds[
'commande'] as $key => $value) {
769 $originforcontact =
'commande';
770 if (is_object($value)) {
771 $originidforcontact = $value->id;
773 $originidforcontact = $value;
780 $sqlcontact =
"SELECT ctc.code, ctc.source, ec.fk_socpeople FROM ".MAIN_DB_PREFIX.
"element_contact as ec, ".MAIN_DB_PREFIX.
"c_type_contact as ctc";
781 $sqlcontact .=
" WHERE element_id = ".((int) $originidforcontact).
" AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$this->db->escape($originforcontact).
"'";
783 $resqlcontact = $this->db->query($sqlcontact);
785 while ($objcontact = $this->db->fetch_object($resqlcontact)) {
787 $this->
add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source);
797 if (!$error && empty($this->fac_rec) && count($this->lines) && is_object($this->lines[0])) {
800 dol_syslog(
"There is ".count($this->lines).
" lines into ->lines that are InvoiceLines");
801 foreach ($this->lines as $i => $val) {
802 $newinvoiceline = $this->lines[$i];
804 $newinvoiceline->context = $this->context;
806 $newinvoiceline->fk_facture = $this->id;
808 $newinvoiceline->origin = $this->lines[$i]->element;
809 $newinvoiceline->origin_id = $this->lines[$i]->id;
812 if ($this->lines[$i]->date_start_fill == 1 && $originaldatewhen) {
813 $newinvoiceline->date_start = $originaldatewhen;
815 if ($this->lines[$i]->date_end_fill == 1 && $previousdaynextdatewhen) {
816 $newinvoiceline->date_end = $previousdaynextdatewhen;
821 if (($newinvoiceline->product_type != 9 && empty($newinvoiceline->fk_parent_line)) || $newinvoiceline->product_type == 9) {
826 $vatrate = $newinvoiceline->tva_tx;
827 if ($newinvoiceline->vat_src_code && ! preg_match(
'/\(.*\)/', $vatrate)) {
828 $vatrate.=
' ('.$newinvoiceline->vat_src_code.
')';
831 $newinvoiceline->fk_parent_line = $fk_parent_line;
835 $discount->fetch($newinvoiceline->fk_remise_except);
837 $discountId = $soc->set_remise_except($discount->amount_ht, $user, $discount->description, $discount->tva_tx);
838 $newinvoiceline->fk_remise_except = $discountId;
842 $newinvoiceline->desc,
843 $newinvoiceline->subprice,
844 $newinvoiceline->qty,
846 $newinvoiceline->localtax1_tx,
847 $newinvoiceline->localtax2_tx,
848 $newinvoiceline->fk_product,
849 $newinvoiceline->remise_percent,
850 $newinvoiceline->date_start,
851 $newinvoiceline->date_end,
852 $newinvoiceline->fk_code_ventilation,
853 $newinvoiceline->info_bits,
854 $newinvoiceline->fk_remise_except,
857 $newinvoiceline->product_type,
858 $newinvoiceline->rang,
859 $newinvoiceline->special_code,
860 $newinvoiceline->element,
863 $newinvoiceline->fk_fournprice,
864 $newinvoiceline->pa_ht,
865 $newinvoiceline->label,
866 $newinvoiceline->array_options,
867 $newinvoiceline->situation_percent,
868 $newinvoiceline->fk_prev_id,
869 $newinvoiceline->fk_unit,
870 $newinvoiceline->multicurrency_subprice,
871 $newinvoiceline->ref_ext,
876 if ($result > 0 && $newinvoiceline->product_type == 9) {
877 $fk_parent_line = $result;
881 $this->error = $newinvoiceline->error;
882 $this->errors = $newinvoiceline->errors;
887 } elseif (!$error && empty($this->fac_rec)) {
890 dol_syslog(
"There is ".count($this->lines).
" lines into ->lines as a simple array");
892 foreach ($this->lines as $i => $val) {
893 $line = $this->lines[$i];
897 if (!is_object($line)) {
898 $line = (object) $line;
903 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
908 $vatrate = $line->tva_tx;
909 if ($line->vat_src_code && !preg_match(
'/\(.*\)/', $vatrate)) {
910 $vatrate .=
' ('.$line->vat_src_code.
')';
914 $originid = $line->origin_id;
915 $origintype = $line->origin;
917 $originid = $line->id;
918 $origintype = $this->element;
922 if (empty($line->ref_ext)) {
934 $line->remise_percent,
937 $line->fk_code_ventilation,
939 $line->fk_remise_except,
948 $line->fk_fournprice,
951 $line->array_options,
952 $line->situation_percent,
955 $line->multicurrency_subprice,
960 $this->error = $this->db->lasterror();
962 $this->db->rollback();
967 if ($result > 0 && $line->product_type == 9) {
968 $fk_parent_line = $result;
977 if (!$error && $this->fac_rec > 0) {
978 dol_syslog(
"There is ".count($_facrec->lines).
" lines from recurring invoice");
981 foreach ($_facrec->lines as $i => $val) {
983 if (($_facrec->lines[$i]->product_type != 9 && empty($_facrec->lines[$i]->fk_parent_line)) || $_facrec->lines[$i]->product_type == 9) {
1000 $tva_tx = $_facrec->lines[$i]->tva_tx.($_facrec->lines[$i]->vat_src_code ?
'('.$_facrec->lines[$i]->vat_src_code.
')' :
'');
1001 $tva_npr = $_facrec->lines[$i]->info_bits;
1002 if (empty($tva_tx)) {
1005 $localtax1_tx = $_facrec->lines[$i]->localtax1_tx;
1006 $localtax2_tx = $_facrec->lines[$i]->localtax2_tx;
1008 $fk_product_fournisseur_price = empty($_facrec->lines[$i]->fk_product_fournisseur_price) ? null : $_facrec->lines[$i]->fk_product_fournisseur_price;
1009 $buyprice = empty($_facrec->lines[$i]->buyprice) ? 0 : $_facrec->lines[$i]->buyprice;
1012 if (!$buyprice && $_facrec->lines[$i]->fk_product > 0) {
1013 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
1015 $producttmp->fetch($_facrec->lines[$i]->fk_product);
1020 if (
getDolGlobalString(
'MARGIN_TYPE') ==
'costprice' && !empty($producttmp->cost_price)) {
1021 $buyprice = $producttmp->cost_price;
1023 $buyprice = $producttmp->pmp;
1025 if ($producttmp->find_min_price_product_fournisseur($_facrec->lines[$i]->fk_product) > 0) {
1026 if ($producttmp->product_fourn_price_id > 0) {
1027 $buyprice =
price2num($producttmp->fourn_unitprice * (1 - $producttmp->fourn_remise_percent / 100) + $producttmp->fourn_remise,
'MU');
1033 $result_insert = $this->
addline(
1034 $_facrec->lines[$i]->desc,
1035 $_facrec->lines[$i]->subprice,
1036 $_facrec->lines[$i]->qty,
1040 $_facrec->lines[$i]->fk_product,
1041 $_facrec->lines[$i]->remise_percent,
1042 ($_facrec->lines[$i]->date_start_fill == 1 && $originaldatewhen) ? $originaldatewhen :
'',
1043 ($_facrec->lines[$i]->date_end_fill == 1 && $previousdaynextdatewhen) ? $previousdaynextdatewhen :
'',
1049 $_facrec->lines[$i]->product_type,
1050 $_facrec->lines[$i]->rang,
1051 $_facrec->lines[$i]->special_code,
1055 $fk_product_fournisseur_price,
1057 $_facrec->lines[$i]->label,
1058 empty($_facrec->lines[$i]->array_options) ? null : $_facrec->lines[$i]->array_options,
1061 $_facrec->lines[$i]->fk_unit,
1062 $_facrec->lines[$i]->multicurrency_subprice,
1063 $_facrec->lines[$i]->ref_ext,
1068 if ($result_insert > 0 && $_facrec->lines[$i]->product_type == 9) {
1069 $fk_parent_line = $result_insert;
1072 if ($result_insert < 0) {
1074 $this->error = $this->db->error();
1093 if (!$error && !$notrigger) {
1103 $this->db->commit();
1106 $this->db->rollback();
1110 $this->error = $langs->trans(
'FailedToUpdatePrice');
1111 $this->db->rollback();
1115 dol_syslog(get_class($this).
"::create error ".$this->error, LOG_ERR);
1116 $this->db->rollback();
1120 $this->error = $this->db->error();
1121 $this->db->rollback();
1139 $facture =
new Facture($this->db);
1145 if (!empty($this->array_options)) {
1146 $facture->array_options = $this->array_options;
1149 foreach ($this->lines as &$line) {
1150 $line->fetch_optionals();
1154 $facture->type = $this->type;
1155 $facture->subtype = $this->subtype;
1156 $facture->socid = $this->socid;
1157 $facture->date = $this->date;
1158 $facture->date_pointoftax = $this->date_pointoftax;
1159 $facture->note_public = $this->note_public;
1160 $facture->note_private = $this->note_private;
1161 $facture->ref_client = $this->ref_client;
1162 $facture->model_pdf = $this->model_pdf;
1163 $facture->fk_project = $this->fk_project;
1164 $facture->cond_reglement_id = $this->cond_reglement_id;
1165 $facture->mode_reglement_id = $this->mode_reglement_id;
1169 $facture->origin = $this->origin;
1170 $facture->origin_id = $this->origin_id;
1171 $facture->fk_account = $this->fk_account;
1173 $facture->lines = $this->lines;
1174 $facture->situation_counter = $this->situation_counter;
1175 $facture->situation_cycle_ref = $this->situation_cycle_ref;
1176 $facture->situation_final = $this->situation_final;
1178 $facture->retained_warranty = $this->retained_warranty;
1179 $facture->retained_warranty_fk_cond_reglement = $this->retained_warranty_fk_cond_reglement;
1180 $facture->retained_warranty_date_limit = $this->retained_warranty_date_limit;
1182 $facture->fk_user_author = $user->id;
1186 foreach ($facture->lines as $i => $tmpline) {
1187 $facture->lines[$i]->fk_prev_id = $this->lines[$i]->rowid;
1188 if ($invertdetail) {
1189 $facture->lines[$i]->subprice = -$facture->lines[$i]->subprice;
1190 $facture->lines[$i]->total_ht = -$facture->lines[$i]->total_ht;
1191 $facture->lines[$i]->total_tva = -$facture->lines[$i]->total_tva;
1192 $facture->lines[$i]->total_localtax1 = -$facture->lines[$i]->total_localtax1;
1193 $facture->lines[$i]->total_localtax2 = -$facture->lines[$i]->total_localtax2;
1194 $facture->lines[$i]->total_ttc = -$facture->lines[$i]->total_ttc;
1195 $facture->lines[$i]->ref_ext =
'';
1199 dol_syslog(get_class($this).
"::createFromCurrent invertdetail=".$invertdetail.
" socid=".$this->socid.
" nboflines=".count($facture->lines));
1201 $facid = $facture->create($user);
1203 $this->error = $facture->error;
1204 $this->errors = $facture->errors;
1208 foreach ($this->linkedObjectsIds as $typeObject => $Tfk_object) {
1209 foreach ($Tfk_object as $fk_object) {
1210 $facture->add_object_linked($typeObject, $fk_object);
1214 $facture->add_object_linked(
'facture', $this->fk_facture_source);
1230 global $conf, $hookmanager;
1234 $object =
new Facture($this->db);
1238 $object->fetch($fromid);
1241 $objFrom = clone $object;
1244 if (!empty($this->socid) && $this->socid != $object->socid) {
1245 $objsoc =
new Societe($this->db);
1247 if ($objsoc->fetch($this->socid) > 0) {
1248 $object->socid = $objsoc->id;
1249 $object->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1250 $object->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1251 $object->fk_project =
'';
1252 $object->fk_delivery_address =
'';
1263 $object->date = (empty($this->date) ?
dol_now() : $this->date);
1264 $object->user_creation_id = $user->id;
1265 $object->user_validation_id =
null;
1266 $object->fk_user_author = $user->id;
1267 $object->fk_user_valid =
null;
1268 $object->fk_facture_source = 0;
1269 $object->date_creation =
'';
1270 $object->date_modification =
'';
1271 $object->date_validation =
'';
1272 $object->ref_client =
'';
1273 $object->close_code =
'';
1274 $object->close_note =
'';
1276 $object->note_private =
'';
1277 $object->note_public =
'';
1281 foreach ($object->lines as $i => $line) {
1282 if (($object->lines[$i]->info_bits & 0x02) == 0x02) {
1283 unset($object->lines[$i]);
1289 if (
getDolGlobalString(
'INVOICE_AUTO_NEXT_MONTH_ON_LINES') && !empty($line->date_start) && !empty($line->date_end)) {
1301 if (
dol_mktime(0, 0, 0, $start[
'mon'], $start[
'mday'], $start[
'year'],
'gmt') == $first
1302 &&
dol_mktime(23, 59, 59, $end[
'mon'], $end[
'mday'], $end[
'year'],
'gmt') == $last) {
1306 $object->lines[$i]->date_start = $newFirst;
1307 $object->lines[$i]->date_end = $newLast;
1311 $object->lines[$i]->ref_ext =
'';
1315 $object->context[
'createfromclone'] =
'createfromclone';
1316 $result = $object->create($user);
1319 $this->error = $object->error;
1320 $this->errors = $object->errors;
1323 if ($object->copy_linked_contact($objFrom,
'internal') < 0) {
1325 $this->error = $object->error;
1326 $this->errors = $object->errors;
1327 } elseif ($object->socid == $objFrom->socid) {
1329 if ($object->copy_linked_contact($objFrom,
'external') < 0) {
1331 $this->error = $object->error;
1332 $this->errors = $object->errors;
1339 if (is_object($hookmanager)) {
1340 $parameters = array(
'objFrom'=>$objFrom);
1342 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $object, $action);
1350 unset($object->context[
'createfromclone']);
1354 $this->db->commit();
1357 $this->db->rollback();
1371 global $conf, $hookmanager;
1379 $num = count($object->lines);
1380 for ($i = 0; $i < $num; $i++) {
1383 $line->libelle = $object->lines[$i]->libelle;
1384 $line->label = $object->lines[$i]->label;
1385 $line->desc = $object->lines[$i]->desc;
1386 $line->subprice = $object->lines[$i]->subprice;
1387 $line->total_ht = $object->lines[$i]->total_ht;
1388 $line->total_tva = $object->lines[$i]->total_tva;
1389 $line->total_localtax1 = $object->lines[$i]->total_localtax1;
1390 $line->total_localtax2 = $object->lines[$i]->total_localtax2;
1391 $line->total_ttc = $object->lines[$i]->total_ttc;
1392 $line->vat_src_code = $object->lines[$i]->vat_src_code;
1393 $line->tva_tx = $object->lines[$i]->tva_tx;
1394 $line->localtax1_tx = $object->lines[$i]->localtax1_tx;
1395 $line->localtax2_tx = $object->lines[$i]->localtax2_tx;
1396 $line->qty = $object->lines[$i]->qty;
1397 $line->fk_remise_except = $object->lines[$i]->fk_remise_except;
1398 $line->remise_percent = $object->lines[$i]->remise_percent;
1399 $line->fk_product = $object->lines[$i]->fk_product;
1400 $line->info_bits = $object->lines[$i]->info_bits;
1401 $line->product_type = $object->lines[$i]->product_type;
1402 $line->rang = $object->lines[$i]->rang;
1403 $line->special_code = $object->lines[$i]->special_code;
1404 $line->fk_parent_line = $object->lines[$i]->fk_parent_line;
1405 $line->fk_unit = $object->lines[$i]->fk_unit;
1406 $line->date_start = $object->lines[$i]->date_start;
1407 $line->date_end = $object->lines[$i]->date_end;
1410 $line->fk_multicurrency = $object->lines[$i]->fk_multicurrency;
1411 $line->multicurrency_code = $object->lines[$i]->multicurrency_code;
1412 $line->multicurrency_subprice = $object->lines[$i]->multicurrency_subprice;
1413 $line->multicurrency_total_ht = $object->lines[$i]->multicurrency_total_ht;
1414 $line->multicurrency_total_tva = $object->lines[$i]->multicurrency_total_tva;
1415 $line->multicurrency_total_ttc = $object->lines[$i]->multicurrency_total_ttc;
1417 $line->fk_fournprice = $object->lines[$i]->fk_fournprice;
1418 $marginInfos =
getMarginInfos($object->lines[$i]->subprice, $object->lines[$i]->remise_percent, $object->lines[$i]->tva_tx, $object->lines[$i]->localtax1_tx, $object->lines[$i]->localtax2_tx, $object->lines[$i]->fk_fournprice, $object->lines[$i]->pa_ht);
1419 $line->pa_ht = $marginInfos[0];
1422 $object->lines[$i]->fetch_optionals();
1423 foreach ($object->lines[$i]->array_options as $options_key => $value) {
1424 $line->array_options[$options_key] = $value;
1427 $this->lines[$i] = $line;
1430 $this->socid = $object->socid;
1431 $this->fk_project = $object->fk_project;
1432 $this->fk_account = $object->fk_account;
1433 $this->cond_reglement_id = $object->cond_reglement_id;
1434 $this->mode_reglement_id = $object->mode_reglement_id;
1435 $this->availability_id = $object->availability_id;
1436 $this->demand_reason_id = $object->demand_reason_id;
1437 $this->delivery_date = $object->delivery_date;
1438 $this->fk_delivery_address = $object->fk_delivery_address;
1439 $this->contact_id = $object->contact_id;
1440 $this->ref_client = $object->ref_client;
1443 $this->note_private = $object->note_private;
1444 $this->note_public = $object->note_public;
1447 $this->module_source = $object->module_source;
1448 $this->pos_source = $object->pos_source;
1450 $this->origin = $object->element;
1451 $this->origin_id = $object->id;
1453 $this->fk_user_author = $user->id;
1456 $object->fetch_optionals();
1457 foreach ($object->array_options as $options_key => $value) {
1458 $this->array_options[$options_key] = $value;
1462 $this->linked_objects[$this->origin] = $this->origin_id;
1463 if (!empty($object->other_linked_objects) && is_array($object->other_linked_objects)) {
1464 $this->linked_objects = array_merge($this->linked_objects, $object->other_linked_objects);
1467 $ret = $this->
create($user);
1471 $hookmanager->initHooks(array(
'invoicedao'));
1473 $parameters = array(
'objFrom'=>$object);
1475 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $this, $action);
1501 global $conf, $hookmanager;
1509 $use_all_lines = empty($lines);
1510 $num = count($object->lines);
1511 for ($i = 0; $i < $num; $i++) {
1512 if (!$use_all_lines && !in_array($object->lines[$i]->id, $lines)) {
1518 $line->libelle = $object->lines[$i]->libelle;
1519 $line->label = $object->lines[$i]->label;
1520 $line->desc = $object->lines[$i]->desc;
1521 $line->subprice = $object->lines[$i]->subprice;
1522 $line->total_ht = $object->lines[$i]->total_ht;
1523 $line->total_tva = $object->lines[$i]->total_tva;
1524 $line->total_localtax1 = $object->lines[$i]->total_localtax1;
1525 $line->total_localtax2 = $object->lines[$i]->total_localtax2;
1526 $line->total_ttc = $object->lines[$i]->total_ttc;
1527 $line->vat_src_code = $object->lines[$i]->vat_src_code;
1528 $line->tva_tx = $object->lines[$i]->tva_tx;
1529 $line->localtax1_tx = $object->lines[$i]->localtax1_tx;
1530 $line->localtax2_tx = $object->lines[$i]->localtax2_tx;
1531 $line->qty = $object->lines[$i]->qty;
1532 $line->fk_remise_except = $object->lines[$i]->fk_remise_except;
1533 $line->remise_percent = $object->lines[$i]->remise_percent;
1534 $line->fk_product = $object->lines[$i]->fk_product;
1535 $line->info_bits = $object->lines[$i]->info_bits;
1536 $line->product_type = $object->lines[$i]->product_type;
1537 $line->rang = $object->lines[$i]->rang;
1538 $line->special_code = $object->lines[$i]->special_code;
1539 $line->fk_parent_line = $object->lines[$i]->fk_parent_line;
1540 $line->fk_unit = $object->lines[$i]->fk_unit;
1541 $line->date_start = $object->lines[$i]->date_start;
1542 $line->date_end = $object->lines[$i]->date_end;
1545 $line->fk_multicurrency = $object->lines[$i]->fk_multicurrency;
1546 $line->multicurrency_code = $object->lines[$i]->multicurrency_code;
1547 $line->multicurrency_subprice = $object->lines[$i]->multicurrency_subprice;
1548 $line->multicurrency_total_ht = $object->lines[$i]->multicurrency_total_ht;
1549 $line->multicurrency_total_tva = $object->lines[$i]->multicurrency_total_tva;
1550 $line->multicurrency_total_ttc = $object->lines[$i]->multicurrency_total_ttc;
1552 $line->fk_fournprice = $object->lines[$i]->fk_fournprice;
1553 $marginInfos =
getMarginInfos($object->lines[$i]->subprice, $object->lines[$i]->remise_percent, $object->lines[$i]->tva_tx, $object->lines[$i]->localtax1_tx, $object->lines[$i]->localtax2_tx, $object->lines[$i]->fk_fournprice, $object->lines[$i]->pa_ht);
1554 $line->pa_ht = $marginInfos[0];
1557 $object->lines[$i]->fetch_optionals();
1558 foreach ($object->lines[$i]->array_options as $options_key => $value) {
1559 $line->array_options[$options_key] = $value;
1562 $this->lines[$i] = $line;
1565 $this->socid = $object->socid;
1566 $this->fk_project = $object->fk_project;
1567 $this->fk_account = $object->fk_account;
1568 $this->cond_reglement_id = $object->cond_reglement_id;
1569 $this->mode_reglement_id = $object->mode_reglement_id;
1570 $this->availability_id = $object->availability_id;
1571 $this->demand_reason_id = $object->demand_reason_id;
1572 $this->delivery_date = $object->delivery_date;
1573 $this->fk_delivery_address = $object->fk_delivery_address;
1574 $this->contact_id = $object->contact_id;
1575 $this->ref_client = $object->ref_client;
1578 $this->note_private = $object->note_private;
1579 $this->note_public = $object->note_public;
1582 $this->module_source = $object->module_source;
1583 $this->pos_source = $object->pos_source;
1585 $this->origin = $object->element;
1586 $this->origin_id = $object->id;
1588 $this->fk_user_author = $user->id;
1591 $object->fetch_optionals();
1592 foreach ($object->array_options as $options_key => $value) {
1593 $this->array_options[$options_key] = $value;
1597 $this->linked_objects[$this->origin] = $this->origin_id;
1598 if (!empty($object->other_linked_objects) && is_array($object->other_linked_objects)) {
1599 $this->linked_objects = array_merge($this->linked_objects, $object->other_linked_objects);
1602 $ret = $this->
create($user);
1606 $hookmanager->initHooks(array(
'invoicedao'));
1608 $parameters = array(
'objFrom'=>$object);
1610 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $this, $action);
1640 global $conf, $langs, $hookmanager, $action;
1642 if (! in_array($origin->element, array(
'propal',
'commande'))) {
1643 $origin->error =
'ErrorCanOnlyAutomaticallyGenerateADepositFromProposalOrOrder';
1648 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'DateInvoice'));
1652 require_once DOL_DOCUMENT_ROOT .
'/core/lib/date.lib.php';
1655 $origin->error =
'ErrorDateIsInFuture';
1659 if ($payment_terms_id <= 0) {
1660 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'PaymentConditionsShort'));
1664 $payment_conditions_deposit_percent =
getDictionaryValue(
'c_payment_term',
'deposit_percent', $origin->cond_reglement_id);
1666 if (empty($payment_conditions_deposit_percent)) {
1667 $origin->error =
'ErrorPaymentConditionsNotEligibleToDepositCreation';
1671 if (empty($origin->deposit_percent)) {
1672 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'DepositPercent'));
1676 $deposit =
new self($origin->db);
1677 $deposit->socid = $origin->socid;
1679 $deposit->fk_project = $origin->fk_project;
1680 $deposit->ref_client = $origin->ref_client;
1681 $deposit->date = $date;
1682 $deposit->mode_reglement_id = $origin->mode_reglement_id;
1683 $deposit->cond_reglement_id = $payment_terms_id;
1684 $deposit->availability_id = $origin->availability_id;
1685 $deposit->demand_reason_id = $origin->demand_reason_id;
1686 $deposit->fk_account = $origin->fk_account;
1687 $deposit->fk_incoterms = $origin->fk_incoterms;
1688 $deposit->location_incoterms = $origin->location_incoterms;
1689 $deposit->fk_multicurrency = $origin->fk_multicurrency;
1690 $deposit->multicurrency_code = $origin->multicurrency_code;
1691 $deposit->multicurrency_tx = $origin->multicurrency_tx;
1692 $deposit->module_source = $origin->module_source;
1693 $deposit->pos_source = $origin->pos_source;
1694 $deposit->model_pdf =
'crabe';
1696 $modelByTypeConfName =
'FACTURE_ADDON_PDF_' . $deposit->type;
1705 $deposit->note_private = $origin->note_private;
1706 $deposit->note_public = $origin->note_public;
1709 $deposit->origin = $origin->element;
1710 $deposit->origin_id = $origin->id;
1712 $origin->fetch_optionals();
1714 foreach ($origin->array_options as $extrakey => $value) {
1715 $deposit->array_options[$extrakey] = $value;
1718 $deposit->linked_objects[$deposit->origin] = $deposit->origin_id;
1720 foreach ($overrideFields as $key => $value) {
1721 $deposit->$key = $value;
1724 $deposit->context[
'createdepositfromorigin'] =
'createdepositfromorigin';
1726 $origin->db->begin();
1729 $createReturn = $deposit->create($user, $notrigger);
1731 if ($createReturn <= 0) {
1732 $origin->db->rollback();
1733 $origin->error = $deposit->error;
1734 $origin->errors = $deposit->errors;
1738 $amount_ttc_diff = 0;
1739 $amountdeposit = array();
1740 $descriptions = array();
1743 $amount = $origin->total_ttc * ($origin->deposit_percent / 100);
1745 $TTotalByTva = array();
1746 foreach ($origin->lines as &$line) {
1747 if (!empty($line->special_code)) {
1750 $TTotalByTva[$line->tva_tx] += $line->total_ttc;
1751 $descriptions[$line->tva_tx] .=
'<li>' . (!empty($line->product_ref) ? $line->product_ref .
' - ' :
'');
1752 $descriptions[$line->tva_tx] .= (!empty($line->product_label) ? $line->product_label .
' - ' :
'');
1753 $descriptions[$line->tva_tx] .= $langs->trans(
'Qty') .
' : ' . $line->qty;
1754 $descriptions[$line->tva_tx] .=
' - ' . $langs->trans(
'TotalHT') .
' : ' .
price($line->total_ht) .
'</li>';
1757 foreach ($TTotalByTva as $tva => &$total) {
1758 $coef = $total / $origin->total_ttc;
1759 $am = $amount * $coef;
1760 $amount_ttc_diff += $am;
1761 $amountdeposit[$tva] += $am / (1 + $tva / 100);
1765 $lines = $origin->lines;
1766 $numlines = count($lines);
1767 for ($i = 0; $i < $numlines; $i++) {
1768 if (empty($lines[$i]->qty)) {
1771 if (!empty($lines[$i]->special_code)) {
1775 $totalamount += $lines[$i]->total_ht;
1776 $tva_tx = $lines[$i]->tva_tx;
1777 $amountdeposit[$tva_tx] += ($lines[$i]->total_ht * $origin->deposit_percent) / 100;
1778 $descriptions[$tva_tx] .=
'<li>' . (!empty($lines[$i]->product_ref) ? $lines[$i]->product_ref .
' - ' :
'');
1779 $descriptions[$tva_tx] .= (!empty($lines[$i]->product_label) ? $lines[$i]->product_label .
' - ' :
'');
1780 $descriptions[$tva_tx] .= $langs->trans(
'Qty') .
' : ' . $lines[$i]->qty;
1781 $descriptions[$tva_tx] .=
' - ' . $langs->trans(
'TotalHT') .
' : ' .
price($lines[$i]->total_ht) .
'</li>';
1784 if ($totalamount == 0) {
1785 $amountdeposit[0] = 0;
1788 $amount_ttc_diff = $amountdeposit[0];
1791 foreach ($amountdeposit as $tva => $amount) {
1792 if (empty($amount)) {
1796 $descline =
'(DEPOSIT) ('. $origin->deposit_percent .
'%) - '.$origin->ref;
1799 if (
getDolGlobalString(
'INVOICE_DEPOSIT_VARIABLE_MODE_DETAIL_LINES_IN_DESCRIPTION') && !empty($descriptions[$tva])) {
1800 $descline .=
'<ul>' . $descriptions[$tva] .
'</ul>';
1803 $addlineResult = $deposit->addline(
1810 (!
getDolGlobalString(
'INVOICE_PRODUCTID_DEPOSIT') ? 0 : $conf->global->INVOICE_PRODUCTID_DEPOSIT),
1830 if ($addlineResult < 0) {
1831 $origin->db->rollback();
1832 $origin->error = $deposit->error;
1833 $origin->errors = $deposit->errors;
1838 $diff = $deposit->total_ttc - $amount_ttc_diff;
1841 $deposit->fetch_lines();
1842 $subprice_diff = $deposit->lines[0]->subprice - $diff / (1 + $deposit->lines[0]->tva_tx / 100);
1844 $updatelineResult = $deposit->updateline(
1845 $deposit->lines[0]->id,
1846 $deposit->lines[0]->desc,
1848 $deposit->lines[0]->qty,
1849 $deposit->lines[0]->remise_percent,
1850 $deposit->lines[0]->date_start,
1851 $deposit->lines[0]->date_end,
1852 $deposit->lines[0]->tva_tx,
1856 $deposit->lines[0]->info_bits,
1857 $deposit->lines[0]->product_type,
1861 $deposit->lines[0]->pa_ht,
1862 $deposit->lines[0]->label,
1868 if ($updatelineResult < 0) {
1869 $origin->db->rollback();
1870 $origin->error = $deposit->error;
1871 $origin->errors = $deposit->errors;
1876 $hookmanager->initHooks(array(
'invoicedao'));
1878 $parameters = array(
'objFrom' => $origin);
1879 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $deposit, $action);
1882 $origin->db->rollback();
1883 $origin->error = $hookmanager->error;
1884 $origin->errors = $hookmanager->errors;
1888 if (!empty($autoValidateDeposit)) {
1889 $validateReturn = $deposit->validate($user,
'', 0, $notrigger);
1891 if ($validateReturn < 0) {
1892 $origin->db->rollback();
1893 $origin->error = $deposit->error;
1894 $origin->errors = $deposit->errors;
1899 unset($deposit->context[
'createdepositfromorigin']);
1901 $origin->db->commit();
1915 global $conf, $langs, $mysoc, $user;
1917 $langs->load(
'bills');
1920 $moretitle = $params[
'moretitle'] ??
'';
1921 $picto = $this->picto;
1922 if ($this->
type == self::TYPE_REPLACEMENT) {
1925 if ($this->
type == self::TYPE_CREDIT_NOTE) {
1928 if ($this->
type == self::TYPE_DEPOSIT) {
1932 if ($user->hasRight(
"facture",
"read")) {
1933 $datas[
'picto'] =
img_picto(
'', $picto).
' <u class="paddingrightonly">'.$langs->trans(
"Invoice").
'</u>';
1935 $datas[
'picto'] .=
' '.$this->getLibType(1);
1938 if (!empty($params[
'fromajaxtooltip']) && !isset($this->alreadypaid)) {
1942 if (isset($this->
status) && isset($this->alreadypaid)) {
1943 $datas[
'picto'] .=
' '.$this->getLibStatut(5, $this->alreadypaid);
1946 $datas[
'picto'] .=
' - '.$moretitle;
1948 if (!empty($this->
ref)) {
1949 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
1951 if (!empty($this->ref_customer)) {
1952 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.$this->ref_customer;
1954 if (!empty($this->date)) {
1955 $datas[
'date'] =
'<br><b>'.$langs->trans(
'Date').
':</b> '.
dol_print_date($this->date,
'day');
1957 if (!empty($this->total_ht)) {
1958 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
1960 if (!empty($this->total_tva)) {
1961 $datas[
'amountvat'] =
'<br><b>'.$langs->trans(
'AmountVAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
1963 if (!empty($this->revenuestamp) && $this->revenuestamp != 0) {
1964 $datas[
'amountrevenustamp'] =
'<br><b>'.$langs->trans(
'RevenueStamp').
':</b> '.
price($this->revenuestamp, 0, $langs, 0, -1, -1, $conf->currency);
1966 if (!empty($this->total_localtax1) && $this->total_localtax1 != 0) {
1968 $datas[
'amountlt1'] =
'<br><b>'.$langs->transcountry(
'AmountLT1', $mysoc->country_code).
':</b> '.
price($this->total_localtax1, 0, $langs, 0, -1, -1, $conf->currency);
1970 if (!empty($this->total_localtax2) && $this->total_localtax2 != 0) {
1971 $datas[
'amountlt2'] =
'<br><b>'.$langs->transcountry(
'AmountLT2', $mysoc->country_code).
':</b> '.
price($this->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency);
1973 if (!empty($this->total_ttc)) {
1974 $datas[
'amountttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
1995 public function getNomUrl($withpicto = 0, $option =
'', $max = 0, $short = 0, $moretitle =
'', $notooltip = 0, $addlinktonotes = 0, $save_lastsearch_value = -1, $target =
'')
1997 global $langs, $conf, $user, $mysoc;
1999 if (!empty($conf->dol_no_mouse_hover)) {
2005 if ($option ==
'withdraw') {
2006 $url = DOL_URL_ROOT.
'/compta/facture/prelevement.php?facid='.$this->id;
2008 $url = DOL_URL_ROOT.
'/compta/facture/card.php?facid='.$this->id;
2011 if (!$user->hasRight(
"facture",
"read")) {
2015 if ($option !==
'nolink') {
2017 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2018 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
2019 $add_save_lastsearch_values = 1;
2021 if ($add_save_lastsearch_values) {
2022 $url .=
'&save_lastsearch_values=1';
2030 $picto = $this->picto;
2031 if ($this->
type == self::TYPE_REPLACEMENT) {
2034 if ($this->
type == self::TYPE_CREDIT_NOTE) {
2037 if ($this->
type == self::TYPE_DEPOSIT) {
2042 'objecttype' => $this->element,
2043 'moretitle' => $moretitle,
2044 'option' => $option,
2046 $classfortooltip =
'classfortooltip';
2049 $classfortooltip =
'classforajaxtooltip';
2050 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
2056 $linkclose = ($target ?
' target="'.$target.
'"' :
'');
2057 if (empty($notooltip) && $user->hasRight(
"facture",
"read")) {
2059 $label = $langs->trans(
"Invoice");
2060 $linkclose .=
' alt="'.dol_escape_htmltag($label, 1).
'"';
2062 $linkclose .= ($label ?
' title="'.dol_escape_htmltag($label, 1).
'"' :
' title="tocomplete"');
2063 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
2066 $linkstart =
'<a href="'.$url.
'"';
2067 $linkstart .= $linkclose.
'>';
2070 if ($option ==
'nolink') {
2075 $result .= $linkstart;
2077 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), ($notooltip ? (($withpicto != 2) ?
'class="paddingright"' :
'') :
'class="'.(($withpicto != 2) ?
'paddingright ' :
'').
'"'), 0, 0, $notooltip ? 0 : 1);
2079 if ($withpicto != 2) {
2080 $result .= ($max ?
dol_trunc($this->
ref, $max) : $this->ref);
2082 $result .= $linkend;
2084 if ($addlinktonotes) {
2085 $txttoshow = ($user->socid > 0 ? $this->note_public : $this->note_private);
2088 $notetoshow = $langs->trans(
"ViewPrivateNote").
':<br>'.$txttoshow;
2089 $result .=
' <span class="note inline-block">';
2090 $result .=
'<a href="'.DOL_URL_ROOT.
'/compta/facture/note.php?id='.$this->
id.
'" class="classfortooltip" title="'.
dol_escape_htmltag($notetoshow, 1, 1).
'">';
2095 $result .=
'</span>';
2099 global $action, $hookmanager;
2100 $hookmanager->initHooks(array(
'invoicedao'));
2101 $parameters = array(
'id'=>$this->
id,
'getnomurl' => &$result,
'notooltip' => $notooltip,
'addlinktonotes' => $addlinktonotes,
'save_lastsearch_value'=> $save_lastsearch_value,
'target' => $target);
2102 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
2104 $result = $hookmanager->resPrint;
2106 $result .= $hookmanager->resPrint;
2122 public function fetch($rowid, $ref =
'', $ref_ext =
'', $notused = 0, $fetch_situation =
false)
2124 if (empty($rowid) && empty($ref) && empty($ref_ext)) {
2128 $sql =
'SELECT f.rowid, f.entity, f.ref, f.ref_client, f.ref_ext, f.type, f.subtype, f.fk_soc';
2129 $sql .=
', f.total_tva, f.localtax1, f.localtax2, f.total_ht, f.total_ttc, f.revenuestamp';
2130 $sql .=
', f.datef as df, f.date_pointoftax';
2131 $sql .=
', f.date_lim_reglement as dlr';
2132 $sql .=
', f.datec as datec';
2133 $sql .=
', f.date_valid as datev';
2134 $sql .=
', f.tms as datem';
2135 $sql .=
', f.note_private, f.note_public, f.fk_statut as status, f.paye, f.close_code, f.close_note, f.fk_user_author, f.fk_user_valid, f.fk_user_modif, f.model_pdf, f.last_main_doc';
2136 $sql .=
', f.fk_facture_source, f.fk_fac_rec_source';
2137 $sql .=
', f.fk_mode_reglement, f.fk_cond_reglement, f.fk_projet as fk_project, f.extraparams';
2138 $sql .=
', f.situation_cycle_ref, f.situation_counter, f.situation_final';
2139 $sql .=
', f.fk_account';
2140 $sql .=
", f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc";
2141 $sql .=
', p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
2142 $sql .=
', c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_doc';
2143 $sql .=
', f.fk_incoterms, f.location_incoterms';
2144 $sql .=
', f.module_source, f.pos_source';
2145 $sql .=
", i.libelle as label_incoterms";
2146 $sql .=
", f.retained_warranty as retained_warranty, f.retained_warranty_date_limit as retained_warranty_date_limit, f.retained_warranty_fk_cond_reglement as retained_warranty_fk_cond_reglement";
2147 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facture as f';
2148 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_payment_term as c ON f.fk_cond_reglement = c.rowid';
2149 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_paiement as p ON f.fk_mode_reglement = p.id';
2150 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON f.fk_incoterms = i.rowid';
2153 $sql .=
" WHERE f.rowid = ".((int) $rowid);
2155 $sql .=
' WHERE f.entity IN ('.getEntity(
'invoice').
')';
2157 $sql .=
" AND f.ref = '".$this->db->escape($ref).
"'";
2160 $sql .=
" AND f.ref_ext = '".$this->db->escape($ref_ext).
"'";
2164 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
2165 $resql = $this->db->query($sql);
2167 if ($this->db->num_rows($resql)) {
2168 $obj = $this->db->fetch_object($resql);
2170 $this->
id = $obj->rowid;
2171 $this->entity = $obj->entity;
2173 $this->
ref = $obj->ref;
2174 $this->ref_client = $obj->ref_client;
2175 $this->ref_customer = $obj->ref_client;
2176 $this->ref_ext = $obj->ref_ext;
2177 $this->
type = $obj->type;
2178 $this->subtype = $obj->subtype;
2179 $this->date = $this->db->jdate($obj->df);
2180 $this->date_pointoftax = $this->db->jdate($obj->date_pointoftax);
2181 $this->date_creation = $this->db->jdate($obj->datec);
2182 $this->date_validation = $this->db->jdate($obj->datev);
2183 $this->date_modification = $this->db->jdate($obj->datem);
2184 $this->datem = $this->db->jdate($obj->datem);
2185 $this->total_ht = $obj->total_ht;
2186 $this->total_tva = $obj->total_tva;
2187 $this->total_localtax1 = $obj->localtax1;
2188 $this->total_localtax2 = $obj->localtax2;
2189 $this->total_ttc = $obj->total_ttc;
2190 $this->revenuestamp = $obj->revenuestamp;
2191 $this->paye = $obj->paye;
2192 $this->close_code = $obj->close_code;
2193 $this->close_note = $obj->close_note;
2195 $this->socid = $obj->fk_soc;
2196 $this->thirdparty =
null;
2198 $this->fk_project = $obj->fk_project;
2199 $this->project =
null;
2201 $this->
statut = $obj->status;
2202 $this->
status = $obj->status;
2204 $this->date_lim_reglement = $this->db->jdate($obj->dlr);
2205 $this->mode_reglement_id = $obj->fk_mode_reglement;
2206 $this->mode_reglement_code = $obj->mode_reglement_code;
2207 $this->mode_reglement = $obj->mode_reglement_libelle;
2208 $this->cond_reglement_id = $obj->fk_cond_reglement;
2209 $this->cond_reglement_code = $obj->cond_reglement_code;
2210 $this->cond_reglement = $obj->cond_reglement_libelle;
2211 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
2212 $this->fk_account = ($obj->fk_account > 0) ? $obj->fk_account :
null;
2213 $this->fk_facture_source = $obj->fk_facture_source;
2214 $this->fk_fac_rec_source = $obj->fk_fac_rec_source;
2215 $this->note = $obj->note_private;
2216 $this->note_private = $obj->note_private;
2217 $this->note_public = $obj->note_public;
2218 $this->user_creation_id = $obj->fk_user_author;
2219 $this->user_validation_id = $obj->fk_user_valid;
2220 $this->user_modification_id = $obj->fk_user_modif;
2221 $this->fk_user_author = $obj->fk_user_author;
2222 $this->fk_user_valid = $obj->fk_user_valid;
2223 $this->fk_user_modif = $obj->fk_user_modif;
2224 $this->model_pdf = $obj->model_pdf;
2225 $this->last_main_doc = $obj->last_main_doc;
2226 $this->situation_cycle_ref = $obj->situation_cycle_ref;
2227 $this->situation_counter = $obj->situation_counter;
2228 $this->situation_final = $obj->situation_final;
2229 $this->retained_warranty = $obj->retained_warranty;
2230 $this->retained_warranty_date_limit = $this->db->jdate($obj->retained_warranty_date_limit);
2231 $this->retained_warranty_fk_cond_reglement = $obj->retained_warranty_fk_cond_reglement;
2233 $this->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
2236 $this->fk_incoterms = $obj->fk_incoterms;
2237 $this->location_incoterms = $obj->location_incoterms;
2238 $this->label_incoterms = $obj->label_incoterms;
2240 $this->module_source = $obj->module_source;
2241 $this->pos_source = $obj->pos_source;
2244 $this->fk_multicurrency = $obj->fk_multicurrency;
2245 $this->multicurrency_code = $obj->multicurrency_code;
2246 $this->multicurrency_tx = $obj->multicurrency_tx;
2247 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
2248 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
2249 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
2251 if (($this->
type == self::TYPE_SITUATION || ($this->
type == self::TYPE_CREDIT_NOTE && $this->situation_cycle_ref > 0)) && $fetch_situation) {
2260 $this->lines = array();
2264 $this->error = $this->db->error();
2268 $this->db->free($resql);
2272 $this->error =
'Invoice with id='.$rowid.
' or ref='.$ref.
' or ref_ext='.$ref_ext.
' not found';
2274 dol_syslog(__METHOD__.$this->error, LOG_WARNING);
2278 $this->error = $this->db->lasterror();
2293 public function fetch_lines($only_product = 0, $loadalsotranslation = 0)
2296 $this->lines = array();
2298 $sql =
'SELECT l.rowid, l.fk_facture, l.fk_product, l.fk_parent_line, l.label as custom_label, l.description, l.product_type, l.price, l.qty, l.vat_src_code, l.tva_tx,';
2299 $sql .=
' l.localtax1_tx, l.localtax2_tx, l.localtax1_type, l.localtax2_type, l.remise_percent, l.fk_remise_except, l.subprice, l.ref_ext,';
2300 $sql .=
' l.situation_percent, l.fk_prev_id,';
2301 $sql .=
' l.rang, l.special_code, l.batch, l.fk_warehouse,';
2302 $sql .=
' l.date_start as date_start, l.date_end as date_end,';
2303 $sql .=
' l.info_bits, l.total_ht, l.total_tva, l.total_localtax1, l.total_localtax2, l.total_ttc, l.fk_code_ventilation, l.fk_product_fournisseur_price as fk_fournprice, l.buy_price_ht as pa_ht,';
2304 $sql .=
' l.fk_unit,';
2305 $sql .=
' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
2306 $sql .=
' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc, p.barcode as product_barcode';
2307 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facturedet as l';
2308 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON l.fk_product = p.rowid';
2309 $sql .=
' WHERE l.fk_facture = '.((int) $this->
id);
2310 $sql .=
' ORDER BY l.rang, l.rowid';
2312 dol_syslog(get_class($this).
'::fetch_lines', LOG_DEBUG);
2313 $result = $this->db->query($sql);
2315 $num = $this->db->num_rows($result);
2318 $objp = $this->db->fetch_object($result);
2321 $line->id = $objp->rowid;
2322 $line->rowid = $objp->rowid;
2323 $line->fk_facture = $objp->fk_facture;
2324 $line->label = $objp->custom_label;
2325 $line->desc = $objp->description;
2326 $line->description = $objp->description;
2327 $line->product_type = $objp->product_type;
2328 $line->ref = $objp->product_ref;
2329 $line->product_ref = $objp->product_ref;
2330 $line->libelle = $objp->product_label;
2331 $line->product_label = $objp->product_label;
2332 $line->product_barcode = $objp->product_barcode;
2333 $line->product_desc = $objp->product_desc;
2334 $line->fk_product_type = $objp->fk_product_type;
2335 $line->qty = $objp->qty;
2336 $line->subprice = $objp->subprice;
2337 $line->ref_ext = $objp->ref_ext;
2339 $line->vat_src_code = $objp->vat_src_code;
2340 $line->tva_tx = $objp->tva_tx;
2341 $line->localtax1_tx = $objp->localtax1_tx;
2342 $line->localtax2_tx = $objp->localtax2_tx;
2343 $line->localtax1_type = $objp->localtax1_type;
2344 $line->localtax2_type = $objp->localtax2_type;
2345 $line->remise_percent = $objp->remise_percent;
2346 $line->fk_remise_except = $objp->fk_remise_except;
2347 $line->fk_product = $objp->fk_product;
2348 $line->date_start = $this->db->jdate($objp->date_start);
2349 $line->date_end = $this->db->jdate($objp->date_end);
2350 $line->info_bits = $objp->info_bits;
2351 $line->total_ht = $objp->total_ht;
2352 $line->total_tva = $objp->total_tva;
2353 $line->total_localtax1 = $objp->total_localtax1;
2354 $line->total_localtax2 = $objp->total_localtax2;
2355 $line->total_ttc = $objp->total_ttc;
2357 $line->code_ventilation = $objp->fk_code_ventilation;
2358 $line->fk_fournprice = $objp->fk_fournprice;
2359 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
2360 $line->pa_ht = $marginInfos[0];
2361 $line->marge_tx = $marginInfos[1];
2362 $line->marque_tx = $marginInfos[2];
2363 $line->rang = $objp->rang;
2364 $line->special_code = $objp->special_code;
2365 $line->fk_parent_line = $objp->fk_parent_line;
2366 $line->situation_percent = $objp->situation_percent;
2367 $line->fk_prev_id = $objp->fk_prev_id;
2368 $line->fk_unit = $objp->fk_unit;
2370 $line->batch = $objp->batch;
2371 $line->fk_warehouse = $objp->fk_warehouse;
2374 $line->fk_accounting_account = $objp->fk_code_ventilation;
2377 $line->fk_multicurrency = $objp->fk_multicurrency;
2378 $line->multicurrency_code = $objp->multicurrency_code;
2379 $line->multicurrency_subprice = $objp->multicurrency_subprice;
2380 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
2381 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
2382 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
2384 $line->fetch_optionals();
2387 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
2388 $tmpproduct =
new Product($this->db);
2389 $tmpproduct->fetch($objp->fk_product);
2390 $tmpproduct->getMultiLangs();
2392 $line->multilangs = $tmpproduct->multilangs;
2395 $this->lines[$i] = $line;
2399 $this->db->free($result);
2402 $this->error = $this->db->error();
2417 $this->tab_previous_situation_invoice = array();
2418 $this->tab_next_situation_invoice = array();
2420 $sql =
'SELECT rowid, type, situation_cycle_ref, situation_counter FROM '.MAIN_DB_PREFIX.
'facture';
2421 $sql .=
" WHERE rowid <> ".((int) $this->
id);
2422 $sql .=
' AND entity = '.((int) $this->entity);
2423 $sql .=
' AND situation_cycle_ref = '.(int) $this->situation_cycle_ref;
2424 $sql .=
' ORDER BY situation_counter ASC';
2426 dol_syslog(get_class($this).
'::fetchPreviousNextSituationInvoice ', LOG_DEBUG);
2427 $result = $this->db->query($sql);
2428 if ($result && $this->db->num_rows($result) > 0) {
2429 while ($objp = $this->db->fetch_object($result)) {
2430 $invoice =
new Facture($this->db);
2431 if ($invoice->fetch($objp->rowid) > 0) {
2432 if ($objp->situation_counter < $this->situation_counter
2433 || ($objp->situation_counter == $this->situation_counter && $objp->rowid < $this->id)
2435 $this->tab_previous_situation_invoice[] = $invoice;
2437 $this->tab_next_situation_invoice[] = $invoice;
2456 if (empty($this->
type)) {
2459 if (isset($this->
ref)) {
2460 $this->
ref = trim($this->
ref);
2462 if (isset($this->ref_ext)) {
2463 $this->ref_ext = trim($this->ref_ext);
2465 if (isset($this->ref_client)) {
2466 $this->ref_client = trim($this->ref_client);
2468 if (isset($this->increment)) {
2469 $this->increment = trim($this->increment);
2471 if (isset($this->close_code)) {
2472 $this->close_code = trim($this->close_code);
2474 if (isset($this->close_note)) {
2475 $this->close_note = trim($this->close_note);
2477 if (isset($this->note) || isset($this->note_private)) {
2478 $this->note = (isset($this->note) ? trim($this->note) : trim($this->note_private));
2480 if (isset($this->note) || isset($this->note_private)) {
2481 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note));
2483 if (isset($this->note_public)) {
2484 $this->note_public = trim($this->note_public);
2486 if (isset($this->model_pdf)) {
2487 $this->model_pdf = trim($this->model_pdf);
2489 if (isset($this->import_key)) {
2490 $this->import_key = trim($this->import_key);
2492 if (isset($this->retained_warranty)) {
2493 $this->retained_warranty = (float) $this->retained_warranty;
2495 if (!isset($this->fk_user_author) && isset($this->user_author) ) {
2496 $this->fk_user_author = $this->user_author;
2504 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facture SET";
2505 $sql .=
" ref=".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
2506 $sql .=
" ref_ext=".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
2507 $sql .=
" type=".(isset($this->
type) ? $this->db->escape($this->
type) :
"null").
",";
2508 $sql .=
" subtype=".(isset($this->subtype) ? $this->db->escape($this->subtype) :
"null").
",";
2509 $sql .=
" ref_client=".(isset($this->ref_client) ?
"'".$this->db->escape($this->ref_client).
"'" :
"null").
",";
2510 $sql .=
" increment=".(isset($this->increment) ?
"'".$this->db->escape($this->increment).
"'" :
"null").
",";
2511 $sql .=
" fk_soc=".(isset($this->socid) ? $this->db->escape($this->socid) :
"null").
",";
2512 $sql .=
" datec=".(strval($this->date_creation) !=
'' ?
"'".$this->db->idate($this->date_creation).
"'" :
'null').
",";
2513 $sql .=
" datef=".(strval($this->date) !=
'' ?
"'".$this->db->idate($this->date).
"'" :
'null').
",";
2514 $sql .=
" date_pointoftax=".(strval($this->date_pointoftax) !=
'' ?
"'".$this->db->idate($this->date_pointoftax).
"'" :
'null').
",";
2515 $sql .=
" date_valid=".(strval($this->date_validation) !=
'' ?
"'".$this->db->idate($this->date_validation).
"'" :
'null').
",";
2516 $sql .=
" paye=".(isset($this->paye) ? $this->db->escape($this->paye) : 0).
",";
2517 $sql .=
" close_code=".(isset($this->close_code) ?
"'".$this->db->escape($this->close_code).
"'" :
"null").
",";
2518 $sql .=
" close_note=".(isset($this->close_note) ?
"'".$this->db->escape($this->close_note).
"'" :
"null").
",";
2519 $sql .=
" total_tva=".(isset($this->total_tva) ? $this->total_tva :
"null").
",";
2520 $sql .=
" localtax1=".(isset($this->total_localtax1) ? $this->total_localtax1 :
"null").
",";
2521 $sql .=
" localtax2=".(isset($this->total_localtax2) ? $this->total_localtax2 :
"null").
",";
2522 $sql .=
" total_ht=".(isset($this->total_ht) ? $this->total_ht :
"null").
",";
2523 $sql .=
" total_ttc=".(isset($this->total_ttc) ? $this->total_ttc :
"null").
",";
2524 $sql .=
" revenuestamp=".((isset($this->revenuestamp) && $this->revenuestamp !=
'') ? $this->db->escape($this->revenuestamp) :
"null").
",";
2525 $sql .=
" fk_statut=".(isset($this->
status) ? ((int) $this->
status) :
"null").
",";
2526 $sql .=
" fk_user_author=".(isset($this->fk_user_author) ? ((int) $this->fk_user_author) :
"null").
",";
2527 $sql .=
" fk_user_valid=".(isset($this->fk_user_valid) ? $this->db->escape($this->fk_user_valid) :
"null").
",";
2528 $sql .=
" fk_facture_source=".(isset($this->fk_facture_source) ? $this->db->escape($this->fk_facture_source) :
"null").
",";
2529 $sql .=
" fk_projet=".(isset($this->fk_project) ? $this->db->escape($this->fk_project) :
"null").
",";
2530 $sql .=
" fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->db->escape($this->cond_reglement_id) :
"null").
",";
2531 $sql .=
" fk_mode_reglement=".(isset($this->mode_reglement_id) ? $this->db->escape($this->mode_reglement_id) :
"null").
",";
2532 $sql .=
" date_lim_reglement=".(strval($this->date_lim_reglement) !=
'' ?
"'".$this->db->idate($this->date_lim_reglement).
"'" :
'null').
",";
2533 $sql .=
" note_private=".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
2534 $sql .=
" note_public=".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
2535 $sql .=
" model_pdf=".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
2536 $sql .=
" import_key=".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null").
",";
2537 $sql .=
" situation_cycle_ref=".(empty($this->situation_cycle_ref) ?
"null" : $this->db->escape($this->situation_cycle_ref)).
",";
2538 $sql .=
" situation_counter=".(empty($this->situation_counter) ?
"null" : $this->db->escape($this->situation_counter)).
",";
2539 $sql .=
" situation_final=".(empty($this->situation_final) ?
"0" : $this->db->escape($this->situation_final)).
",";
2540 $sql .=
" retained_warranty=".(empty($this->retained_warranty) ?
"0" : $this->db->escape($this->retained_warranty)).
",";
2541 $sql .=
" retained_warranty_date_limit=".(strval($this->retained_warranty_date_limit) !=
'' ?
"'".$this->db->idate($this->retained_warranty_date_limit).
"'" :
'null').
",";
2542 $sql .=
" retained_warranty_fk_cond_reglement=".(isset($this->retained_warranty_fk_cond_reglement) ? intval($this->retained_warranty_fk_cond_reglement) :
"null");
2543 $sql .=
" WHERE rowid=".((int) $this->
id);
2547 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
2548 $resql = $this->db->query($sql);
2551 $this->errors[] =
"Error ".$this->db->lasterror();
2561 if (!$error && !$notrigger) {
2572 foreach ($this->errors as $errmsg) {
2573 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
2574 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2576 $this->db->rollback();
2579 $this->db->commit();
2595 global $conf, $langs;
2597 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
2598 include_once DOL_DOCUMENT_ROOT.
'/core/class/discount.class.php';
2603 $result = $remise->fetch($idremise);
2606 if ($remise->fk_facture) {
2607 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed");
2608 $this->db->rollback();
2613 $facligne->fk_facture = $this->id;
2614 $facligne->fk_remise_except = $remise->id;
2615 $facligne->desc = $remise->description;
2616 $facligne->vat_src_code = $remise->vat_src_code;
2617 $facligne->tva_tx = $remise->tva_tx;
2618 $facligne->subprice = -$remise->amount_ht;
2619 $facligne->fk_product = 0;
2621 $facligne->remise_percent = 0;
2622 $facligne->rang = -1;
2623 $facligne->info_bits = 2;
2626 $facligne->rang = 1;
2627 $linecount = count($this->lines);
2628 for ($ii = 1; $ii <= $linecount; $ii++) {
2634 if ($remise->fk_facture_source > 0) {
2635 $srcinvoice =
new Facture($this->db);
2636 $srcinvoice->fetch($remise->fk_facture_source);
2637 include_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmargin.class.php';
2639 $arraytmp = $formmargin->getMarginInfosArray($srcinvoice,
false);
2640 $facligne->pa_ht = $arraytmp[
'pa_total'];
2643 $facligne->total_ht = -$remise->amount_ht;
2644 $facligne->total_tva = -$remise->amount_tva;
2645 $facligne->total_ttc = -$remise->amount_ttc;
2647 $facligne->multicurrency_subprice = -$remise->multicurrency_subprice;
2648 $facligne->multicurrency_total_ht = -$remise->multicurrency_amount_ht;
2649 $facligne->multicurrency_total_tva = -$remise->multicurrency_amount_tva;
2650 $facligne->multicurrency_total_ttc = -$remise->multicurrency_amount_ttc;
2652 $lineid = $facligne->insert();
2657 $result = $remise->link_to_invoice($lineid, 0);
2659 $this->error = $remise->error;
2660 $this->db->rollback();
2664 $this->db->commit();
2667 $this->error = $facligne->error;
2668 $this->db->rollback();
2672 $this->error = $facligne->error;
2673 $this->db->rollback();
2677 $this->db->rollback();
2699 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
2700 if (empty($ref_client)) {
2701 $sql .=
' SET ref_client = NULL';
2703 $sql .=
' SET ref_client = \''.$this->db->escape($ref_client).
'\'';
2705 $sql .=
" WHERE rowid = ".((int) $this->
id);
2707 dol_syslog(__METHOD__.
' this->id='.$this->id.
', ref_client='.$ref_client, LOG_DEBUG);
2708 $resql = $this->db->query($sql);
2710 $this->errors[] = $this->db->error();
2715 $this->ref_client = $ref_client;
2718 if (!$notrigger && empty($error)) {
2728 $this->ref_client = $ref_client;
2730 $this->db->commit();
2733 foreach ($this->errors as $errmsg) {
2734 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2735 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2737 $this->db->rollback();
2750 public function delete($user, $notrigger = 0, $idwarehouse = -1)
2752 global $langs, $conf;
2753 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
2757 dol_syslog(get_class($this).
"::delete rowid=".$rowid.
", ref=".$this->ref.
", thirdparty=".(empty($this->thirdparty) ?
'' : $this->thirdparty->name), LOG_DEBUG);
2770 if (!$error && !$notrigger) {
2784 dol_syslog(get_class($this).
"::delete error deleteExtraFields ".$this->error, LOG_ERR);
2798 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'societe_remise_except';
2799 $sql .=
' WHERE fk_facture_source = '.((int) $rowid);
2800 $sql .=
' AND fk_facture_line IS NULL';
2801 $resql = $this->db->query($sql);
2805 $list_rowid_det = array();
2806 foreach ($this->lines as $key => $invoiceline) {
2807 $list_rowid_det[] = $invoiceline->id;
2811 if (count($list_rowid_det)) {
2812 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
2813 $sql .=
' SET fk_facture = NULL, fk_facture_line = NULL';
2814 $sql .=
' WHERE fk_facture_line IN ('.$this->db->sanitize(join(
',', $list_rowid_det)).
')';
2816 if (!$this->db->query($sql)) {
2817 $this->error = $this->db->error().
" sql=".$sql;
2818 $this->errors[] = $this->error;
2819 $this->db->rollback();
2826 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'eventorganization_conferenceorboothattendee';
2827 $sql .=
' SET fk_invoice = NULL';
2828 $sql .=
' WHERE fk_invoice = '.((int) $rowid);
2830 if (!$this->db->query($sql)) {
2831 $this->error = $this->db->error().
" sql=".$sql;
2832 $this->errors[] = $this->error;
2833 $this->db->rollback();
2837 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'element_time';
2838 $sql .=
' SET invoice_id = NULL, invoice_line_id = NULL';
2839 $sql .=
' WHERE invoice_id = '.((int) $rowid);
2841 if (!$this->db->query($sql)) {
2842 $this->error = $this->db->error().
" sql=".$sql;
2843 $this->errors[] = $this->error;
2844 $this->db->rollback();
2849 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL') && $idwarehouse != -1) {
2850 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
2851 $langs->load(
"agenda");
2853 $num = count($this->lines);
2854 for ($i = 0; $i < $num; $i++) {
2855 if ($this->lines[$i]->fk_product > 0) {
2857 $mouvP->origin = &$this;
2858 $mouvP->setOrigin($this->element, $this->
id);
2860 if ($this->
type == self::TYPE_CREDIT_NOTE) {
2861 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceDeleteDolibarr", $this->ref));
2863 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceDeleteDolibarr", $this->ref));
2870 $main = MAIN_DB_PREFIX.
'facturedet';
2871 $ef = $main.
"_extrafields";
2872 $sqlef =
"DELETE FROM ".$ef.
" WHERE fk_object IN (SELECT rowid FROM ".$main.
" WHERE fk_facture = ".((int) $rowid).
")";
2874 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'facturedet WHERE fk_facture = '.((int) $rowid);
2877 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'facture WHERE rowid = '.((int) $rowid);
2879 $resql = $this->db->query($sql);
2887 if ($conf->facture->dir_output && !empty($this->
ref)) {
2888 $dir = $conf->facture->dir_output.
"/".$ref;
2889 $file = $conf->facture->dir_output.
"/".$ref.
"/".$ref.
".pdf";
2890 if (file_exists($file)) {
2894 $langs->load(
"errors");
2895 $this->error = $langs->trans(
"ErrorFailToDeleteFile", $file);
2896 $this->errors[] = $this->error;
2897 $this->db->rollback();
2901 if (file_exists($dir)) {
2903 $langs->load(
"errors");
2904 $this->error = $langs->trans(
"ErrorFailToDeleteDir", $dir);
2905 $this->errors[] = $this->error;
2906 $this->db->rollback();
2912 $this->db->commit();
2915 $this->error = $this->db->lasterror().
" sql=".$sql;
2916 $this->errors[] = $this->error;
2917 $this->db->rollback();
2921 $this->error = $this->db->lasterror().
" sql=".$sql;
2922 $this->errors[] = $this->error;
2923 $this->db->rollback();
2927 $this->db->rollback();
2944 public function set_paid($user, $close_code =
'', $close_note =
'')
2947 dol_syslog(get_class($this).
"::set_paid is deprecated, use setPaid instead", LOG_NOTICE);
2948 return $this->
setPaid($user, $close_code, $close_note);
2961 public function setPaid($user, $close_code =
'', $close_note =
'')
2965 if ($this->paye != 1) {
2970 dol_syslog(get_class($this).
"::setPaid rowid=".((
int) $this->
id), LOG_DEBUG);
2972 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET';
2973 $sql .=
' fk_statut='.self::STATUS_CLOSED;
2978 $sql .=
", close_code='".$this->db->escape($close_code).
"'";
2981 $sql .=
", close_note='".$this->db->escape($close_note).
"'";
2983 $sql .=
', fk_user_closing = '.((int) $user->id);
2984 $sql .=
", date_closing = '".$this->db->idate($now).
"'";
2985 $sql .=
" WHERE rowid = ".((int) $this->
id);
2987 $resql = $this->db->query($sql);
2997 $this->error = $this->db->lasterror();
3001 $this->db->commit();
3004 $this->db->rollback();
3027 dol_syslog(get_class($this).
"::set_unpaid is deprecated, use setUnpaid instead", LOG_NOTICE);
3045 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
3046 $sql .=
' SET paye=0, fk_statut='.self::STATUS_VALIDATED.
', close_code=null, close_note=null,';
3047 $sql .=
' date_closing=null,';
3048 $sql .=
' fk_user_closing=null';
3049 $sql .=
" WHERE rowid = ".((int) $this->
id);
3051 dol_syslog(get_class($this).
"::setUnpaid", LOG_DEBUG);
3052 $resql = $this->db->query($sql);
3062 $this->error = $this->db->error();
3067 $this->db->commit();
3070 $this->db->rollback();
3092 dol_syslog(get_class($this).
"::set_canceled is deprecated, use setCanceled instead", LOG_NOTICE);
3093 return $this->
setCanceled($user, $close_code, $close_note);
3106 public function setCanceled($user, $close_code =
'', $close_note =
'')
3108 dol_syslog(get_class($this).
"::setCanceled rowid=".((
int) $this->
id), LOG_DEBUG);
3113 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET';
3114 $sql .=
' fk_statut='.self::STATUS_ABANDONED;
3116 $sql .=
", close_code='".$this->db->escape($close_code).
"'";
3119 $sql .=
", close_note='".$this->db->escape($close_note).
"'";
3121 $sql .=
', fk_user_closing = '.((int) $user->id);
3122 $sql .=
", date_closing = '".$this->db->idate($now).
"'";
3123 $sql .=
" WHERE rowid = ".((int) $this->
id);
3125 $resql = $this->db->query($sql);
3129 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
3130 $sql .=
' SET fk_facture = NULL';
3131 $sql .=
' WHERE fk_facture = '.((int) $this->
id);
3133 $resql = $this->db->query($sql);
3138 $this->db->rollback();
3143 $this->db->commit();
3146 $this->error = $this->db->error().
" sql=".$sql;
3147 $this->db->rollback();
3151 $this->error = $this->db->error().
" sql=".$sql;
3152 $this->db->rollback();
3168 public function validate($user, $force_number =
'', $idwarehouse = 0, $notrigger = 0, $batch_rule = 0)
3170 global $conf, $langs, $mysoc;
3171 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
3173 $productStatic =
null;
3174 $warehouseStatic =
null;
3175 if ($batch_rule > 0) {
3176 require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
3177 require_once DOL_DOCUMENT_ROOT.
'/product/class/productbatch.class.php';
3178 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
3179 $productStatic =
new Product($this->db);
3180 $warehouseStatic =
new Entrepot($this->db);
3187 dol_syslog(get_class($this).
'::validate user='.$user->id.
', force_number='.$force_number.
', idwarehouse='.$idwarehouse);
3194 if ($this->
status != self::STATUS_DRAFT) {
3195 dol_syslog(get_class($this).
"::validate Current status is not draft. operation canceled.", LOG_WARNING);
3198 if (count($this->lines) <= 0) {
3199 $langs->load(
"errors");
3200 $this->error = $langs->trans(
"ErrorObjectMustHaveLinesToBeValidated", $this->
ref);
3204 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && !$user->hasRight(
'facture',
'invoice_advance',
'validate'))) {
3205 $this->error =
'Permission denied';
3206 dol_syslog(get_class($this).
"::validate ".$this->error.
' MAIN_USE_ADVANCED_PERMS=' .
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS'), LOG_ERR);
3209 if ((preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) &&
3217 if (!$last_of_type[0]) {
3218 $this->error = $langs->transnoentities(
"ErrorInvoiceIsNotLastOfSameType", $this->
ref,
dol_print_date($this->date,
'day'),
dol_print_date($last_of_type[1],
'day'));
3224 if (!empty($this->thirdparty) && is_object($this->thirdparty)) {
3225 $array_to_check = array(
'IDPROF1',
'IDPROF2',
'IDPROF3',
'IDPROF4',
'IDPROF5',
'IDPROF6',
'EMAIL',
'ACCOUNTANCY_CODE_CUSTOMER');
3226 foreach ($array_to_check as $key) {
3227 $keymin = strtolower($key);
3228 if (!property_exists($this->thirdparty, $keymin)) {
3231 $vallabel = $this->thirdparty->$keymin;
3233 $i = (int) preg_replace(
'/[^0-9]/',
'', $key);
3235 if ($this->thirdparty->isACompany()) {
3237 if ($mysoc->country_id > 0 && $this->thirdparty->country_id == $mysoc->country_id) {
3238 $idprof_mandatory =
'SOCIETE_'.$key.
'_INVOICE_MANDATORY';
3239 if (!$vallabel && !empty($conf->global->$idprof_mandatory)) {
3240 $langs->load(
"errors");
3241 $this->error = $langs->trans(
'ErrorProdIdIsMandatory', $langs->transcountry(
'ProfId'.$i, $this->thirdparty->country_code)).
' ('.$langs->trans(
"ForbiddenBySetupRules").
') ['.$langs->trans(
'Company').
' : '.$this->thirdparty->name.
']';
3242 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3248 if ($key ==
'EMAIL') {
3250 if (
getDolGlobalString(
'SOCIETE_EMAIL_INVOICE_MANDATORY') && !isValidEMail($this->thirdparty->email)) {
3251 $langs->load(
"errors");
3252 $this->error = $langs->trans(
"ErrorBadEMail", $this->thirdparty->email).
' ('.$langs->trans(
"ForbiddenBySetupRules").
') ['.$langs->trans(
'Company').
' : '.$this->thirdparty->name.
']';
3253 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3257 if ($key ==
'ACCOUNTANCY_CODE_CUSTOMER') {
3259 if (
getDolGlobalString(
'SOCIETE_ACCOUNTANCY_CODE_CUSTOMER_INVOICE_MANDATORY') && empty($this->thirdparty->code_compta)) {
3260 $langs->load(
"errors");
3261 $this->error = $langs->trans(
"ErrorAccountancyCodeCustomerIsMandatory", $this->thirdparty->name).
' ('.$langs->trans(
"ForbiddenBySetupRules").
')';
3262 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3271 $array_to_check = array(
'REF_CLIENT'=>
'RefCustomer');
3272 foreach ($array_to_check as $key => $val) {
3273 $keymin = strtolower($key);
3274 $vallabel = $this->$keymin;
3277 $keymandatory =
'INVOICE_'.$key.
'_MANDATORY_FOR_VALIDATION';
3279 $langs->load(
"errors");
3281 setEventMessages($langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv($val)),
null,
'errors');
3288 if ($this->
type == self::TYPE_REPLACEMENT) {
3290 if ($this->fk_facture_source <= 0) {
3291 $this->error = $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"InvoiceReplacement"));
3292 $this->db->rollback();
3297 $facreplaced =
new Facture($this->db);
3298 $result = $facreplaced->fetch($this->fk_facture_source);
3300 $this->error = $langs->trans(
"ErrorBadInvoice");
3301 $this->db->rollback();
3306 $idreplacement = $facreplaced->getIdReplacingInvoice(
'validated');
3307 if ($idreplacement && $idreplacement != $this->
id) {
3308 $facreplacement =
new Facture($this->db);
3309 $facreplacement->fetch($idreplacement);
3310 $this->error = $langs->trans(
"ErrorInvoiceAlreadyReplaced", $facreplaced->ref, $facreplacement->ref);
3311 $this->db->rollback();
3315 $result = $facreplaced->setCanceled($user, self::CLOSECODE_REPLACED,
'');
3317 $this->error = $facreplaced->error;
3318 $this->db->rollback();
3324 if ($force_number) {
3325 $num = $force_number;
3326 } elseif (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
3342 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
3343 $sql .=
" SET ref = '".$this->db->escape($num).
"', fk_statut = ".self::STATUS_VALIDATED.
", fk_user_valid = ".($user->id > 0 ? $user->id :
"null").
", date_valid = '".$this->db->idate($now).
"'";
3345 $sql .=
", datef='".$this->db->idate($this->date).
"'";
3346 $sql .=
", date_lim_reglement='".$this->db->idate($this->date_lim_reglement).
"'";
3348 $sql .=
" WHERE rowid = ".((int) $this->
id);
3350 dol_syslog(get_class($this).
"::validate", LOG_DEBUG);
3351 $resql = $this->db->query($sql);
3358 if (!$error && (preg_match(
'/^[\(]?PROV/i', $this->
ref))) {
3364 $result = $this->thirdparty->setAsCustomer();
3367 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL') && $idwarehouse > 0) {
3368 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3369 $langs->load(
"agenda");
3372 $cpt = count($this->lines);
3373 for ($i = 0; $i < $cpt; $i++) {
3374 if ($this->lines[$i]->fk_product > 0) {
3376 $mouvP->origin = &$this;
3377 $mouvP->setOrigin($this->element, $this->
id);
3383 if ($this->
type == self::TYPE_CREDIT_NOTE) {
3384 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceValidatedInDolibarr", $num));
3387 $this->error = $mouvP->error;
3390 $is_batch_line =
false;
3391 if ($batch_rule > 0) {
3392 $productStatic->fetch($this->lines[$i]->fk_product);
3393 if ($productStatic->hasbatch()) {
3394 $is_batch_line =
true;
3395 $product_qty_remain = $this->lines[$i]->qty;
3401 $sortfield =
'pl.sellby,pl.eatby,pb.qty,pl.rowid';
3402 $sortorder =
'ASC,ASC,ASC,ASC';
3405 $resBatchList = $productbatch->findAllForProduct($productStatic->id, $idwarehouse, (
getDolGlobalInt(
'STOCK_ALLOW_NEGATIVE_TRANSFER') ?
null : 0), $sortfield, $sortorder);
3406 if (!is_array($resBatchList)) {
3408 $this->error = $this->db->lasterror();
3412 $batchList = $resBatchList;
3413 if (empty($batchList)) {
3415 $langs->load(
'errors');
3416 $warehouseStatic->fetch($idwarehouse);
3417 $this->error = $langs->trans(
'ErrorBatchNoFoundForProductInWarehouse', $productStatic->label, $warehouseStatic->ref);
3418 dol_syslog(__METHOD__.
' Error: '.$langs->transnoentitiesnoconv(
'ErrorBatchNoFoundForProductInWarehouse', $productStatic->label, $warehouseStatic->ref), LOG_ERR);
3421 foreach ($batchList as $batch) {
3422 if ($batch->qty <= 0) {
3427 if ($batch->qty >= $product_qty_remain) {
3428 $product_batch_qty = $product_qty_remain;
3431 $product_batch_qty = $batch->qty;
3433 $result = $mouvP->livraison($user, $productStatic->id, $idwarehouse, $product_batch_qty, $this->lines[$i]->subprice, $langs->trans(
'InvoiceValidatedInDolibarr', $num),
'',
'',
'', $batch->batch);
3436 $this->error = $mouvP->error;
3437 $this->errors = $mouvP->errors;
3441 $product_qty_remain -= $product_batch_qty;
3443 if ($product_qty_remain <= 0) {
3448 if (!$error && $product_qty_remain > 0) {
3451 $batch = $batchList[0];
3452 $result = $mouvP->livraison($user, $productStatic->id, $idwarehouse, $product_qty_remain, $this->lines[$i]->subprice, $langs->trans(
'InvoiceValidatedInDolibarr', $num),
'',
'',
'', $batch->batch);
3455 $this->error = $mouvP->error;
3456 $this->errors = $mouvP->errors;
3460 $langs->load(
'errors');
3461 $warehouseStatic->fetch($idwarehouse);
3462 $this->error = $langs->trans(
'ErrorBatchNoFoundEnoughQuantityForProductInWarehouse', $productStatic->label, $warehouseStatic->ref);
3463 dol_syslog(__METHOD__.
' Error: '.$langs->transnoentitiesnoconv(
'ErrorBatchNoFoundEnoughQuantityForProductInWarehouse', $productStatic->label, $warehouseStatic->ref), LOG_ERR);
3470 if (!$is_batch_line) {
3471 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceValidatedInDolibarr", $num));
3474 $this->error = $mouvP->error;
3475 $this->errors = $mouvP->errors;
3488 if (!$error && $this->
type == self::TYPE_CREDIT_NOTE && $this->fk_facture_source > 0) {
3489 $invoice_situation =
new Facture($this->db);
3490 $result = $invoice_situation->fetch($this->fk_facture_source);
3491 if ($result > 0 && $invoice_situation->type == self::TYPE_SITUATION && $invoice_situation->situation_final == 1) {
3492 $invoice_situation->situation_final = 0;
3494 $result = $invoice_situation->setFinal($user, 1);
3497 $this->error = $invoice_situation->error;
3498 $this->errors = $invoice_situation->errors;
3504 if (!$error && !$notrigger) {
3514 $this->oldref = $this->ref;
3517 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
3519 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filename = CONCAT('".$this->db->escape($this->newref).
"', SUBSTR(filename, ".(strlen($this->
ref) + 1).
")), filepath = 'facture/".$this->db->escape($this->newref).
"'";
3520 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'facture/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
3521 $resql = $this->db->query($sql);
3524 $this->error = $this->db->lasterror();
3526 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'facture/".$this->db->escape($this->newref).
"'";
3527 $sql .=
" WHERE filepath = 'facture/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
3528 $resql = $this->db->query($sql);
3531 $this->error = $this->db->lasterror();
3537 $dirsource = $conf->facture->dir_output.
'/'.$oldref;
3538 $dirdest = $conf->facture->dir_output.
'/'.$newref;
3539 if (!$error && file_exists($dirsource)) {
3540 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
3542 if (@rename($dirsource, $dirdest)) {
3545 $listoffiles =
dol_dir_list($conf->facture->dir_output.
'/'.$newref,
'files', 1,
'^'.preg_quote($oldref,
'/'));
3546 foreach ($listoffiles as $fileentry) {
3547 $dirsource = $fileentry[
'name'];
3548 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
3549 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
3550 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
3551 @rename($dirsource, $dirdest);
3569 $this->date_validation = $now;
3574 $nboflines = count($this->lines);
3575 while (($i < $nboflines) && $final) {
3576 $final = ($this->lines[$i]->situation_percent == 100);
3580 if (empty($final)) {
3581 $this->situation_final = 0;
3583 $this->situation_final = 1;
3594 $this->db->commit();
3597 $this->db->rollback();
3610 foreach ($this->tab_next_situation_invoice as $next_invoice) {
3611 $is_last = $next_invoice->is_last_in_cycle();
3613 if ($next_invoice->status == self::STATUS_DRAFT && $is_last != 1) {
3614 $this->error = $langs->trans(
'updatePriceNextInvoiceErrorUpdateline', $next_invoice->ref);
3618 foreach ($next_invoice->lines as $line) {
3619 $result = $next_invoice->updateline(
3624 $line->remise_percent,
3628 $line->localtax1_tx,
3629 $line->localtax2_tx,
3632 $line->product_type,
3633 $line->fk_parent_line,
3635 $line->fk_fournprice,
3638 $line->special_code,
3639 $line->array_options,
3640 $line->situation_percent,
3645 $this->error = $langs->trans(
'updatePriceNextInvoiceErrorUpdateline', $next_invoice->ref);
3666 global $conf, $langs;
3670 if ($this->
status == self::STATUS_DRAFT) {
3671 dol_syslog(__METHOD__.
" already draft status", LOG_WARNING);
3679 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facture";
3680 $sql .=
" SET fk_statut = ".self::STATUS_DRAFT;
3681 $sql .=
" WHERE rowid = ".((int) $this->
id);
3683 $result = $this->db->query($sql);
3686 $this->oldcopy = clone $this;
3690 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL')) {
3691 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3692 $langs->load(
"agenda");
3694 $num = count($this->lines);
3695 for ($i = 0; $i < $num; $i++) {
3696 if ($this->lines[$i]->fk_product > 0) {
3698 $mouvP->origin = &$this;
3699 $mouvP->setOrigin($this->element, $this->
id);
3701 if ($this->
type == self::TYPE_CREDIT_NOTE) {
3702 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceBackToDraftInDolibarr", $this->ref));
3704 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceBackToDraftInDolibarr", $this->ref));
3711 $old_statut = $this->status;
3716 $result = $this->
call_trigger(
'BILL_UNVALIDATE', $user);
3719 $this->
statut = $old_statut;
3720 $this->
status = $old_statut;
3724 $this->db->rollback();
3729 $this->db->commit();
3732 $this->db->rollback();
3736 $this->error = $this->db->error();
3737 $this->db->rollback();
3792 $remise_percent = 0,
3797 $fk_remise_except = 0,
3798 $price_base_type =
'HT',
3805 $fk_parent_line = 0,
3806 $fk_fournprice =
null,
3809 $array_options = array(),
3810 $situation_percent = 100,
3815 $noupdateafterinsertline = 0
3819 dol_syslog(__METHOD__.
": using line label is deprecated", LOG_WARNING);
3823 global $mysoc, $conf, $langs;
3825 dol_syslog(get_class($this).
"::addline id=$this->id, pu_ht=$pu_ht, qty=$qty, txtva=$txtva, txlocaltax1=$txlocaltax1, txlocaltax2=$txlocaltax2, fk_product=$fk_product, remise_percent=$remise_percent, date_start=$date_start, date_end=$date_end, ventil=$ventil, info_bits=$info_bits, fk_remise_except=$fk_remise_except, price_base_type=$price_base_type, pu_ttc=$pu_ttc, type=$type, fk_unit=$fk_unit, desc=".
dol_trunc($desc, 25), LOG_DEBUG);
3827 if ($this->
status == self::STATUS_DRAFT) {
3828 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
3831 if (empty($remise_percent)) {
3832 $remise_percent = 0;
3837 if (empty($info_bits)) {
3843 if (empty($ventil)) {
3846 if (empty($txtva)) {
3849 if (empty($txlocaltax1)) {
3852 if (empty($txlocaltax2)) {
3855 if (empty($fk_parent_line) || $fk_parent_line < 0) {
3856 $fk_parent_line = 0;
3858 if (empty($fk_prev_id)) {
3859 $fk_prev_id =
'null';
3861 if (!isset($situation_percent) || $situation_percent > 100 || (
string) $situation_percent ==
'') {
3862 $situation_percent = 100;
3864 if (empty($ref_ext)) {
3868 $remise_percent =
price2num($remise_percent);
3871 $pu_ht_devise =
price2num($pu_ht_devise);
3874 if (!preg_match(
'/\((.*)\)/', $txtva)) {
3880 if ($price_base_type ==
'HT') {
3891 if ($date_start && $date_end && $date_start > $date_end) {
3892 $langs->load(
"errors");
3893 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
3899 $product_type = $type;
3900 if (!empty($fk_product) && $fk_product > 0) {
3901 $product =
new Product($this->db);
3902 $result = $product->fetch($fk_product);
3903 $product_type = $product->type;
3905 if (
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_INVOICE') && $product_type == 0 && $product->stock_reel < $qty) {
3906 $langs->load(
"errors");
3907 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnInvoice', $product->ref);
3908 $this->db->rollback();
3918 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
3919 $vat_src_code = $reg[1];
3920 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
3928 $tabprice =
calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $product_type, $mysoc, $localtaxes_type, $situation_percent, $this->multicurrency_tx, $pu_ht_devise);
3930 $total_ht = $tabprice[0];
3931 $total_tva = $tabprice[1];
3932 $total_ttc = $tabprice[2];
3933 $total_localtax1 = $tabprice[9];
3934 $total_localtax2 = $tabprice[10];
3935 $pu_ht = $tabprice[3];
3938 $multicurrency_total_ht = $tabprice[16];
3939 $multicurrency_total_tva = $tabprice[17];
3940 $multicurrency_total_ttc = $tabprice[18];
3941 $pu_ht_devise = $tabprice[19];
3945 if ($ranktouse == -1) {
3946 $rangmax = $this->
line_max($fk_parent_line);
3947 $ranktouse = $rangmax + 1;
3953 $this->line->context = $this->context;
3955 $this->line->fk_facture = $this->id;
3956 $this->line->label = $label;
3957 $this->line->desc = $desc;
3958 $this->line->ref_ext = $ref_ext;
3960 $this->line->qty = ($this->
type == self::TYPE_CREDIT_NOTE ? abs($qty) : $qty);
3961 $this->line->subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht) : $pu_ht);
3963 $this->line->vat_src_code = $vat_src_code;
3964 $this->line->tva_tx = $txtva;
3965 $this->line->localtax1_tx = ($total_localtax1 ? $localtaxes_type[1] : 0);
3966 $this->line->localtax2_tx = ($total_localtax2 ? $localtaxes_type[3] : 0);
3967 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
3968 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
3970 $this->line->total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ht) : $total_ht);
3971 $this->line->total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ttc) : $total_ttc);
3972 $this->line->total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_tva) : $total_tva);
3973 $this->line->total_localtax1 = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_localtax1) : $total_localtax1);
3974 $this->line->total_localtax2 = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_localtax2) : $total_localtax2);
3976 $this->line->fk_product = $fk_product;
3977 $this->line->product_type = $product_type;
3978 $this->line->remise_percent = $remise_percent;
3979 $this->line->date_start = $date_start;
3980 $this->line->date_end = $date_end;
3981 $this->line->ventil = $ventil;
3982 $this->line->rang = $ranktouse;
3983 $this->line->info_bits = $info_bits;
3984 $this->line->fk_remise_except = $fk_remise_except;
3986 $this->line->special_code = $special_code;
3987 $this->line->fk_parent_line = $fk_parent_line;
3988 $this->line->origin = $origin;
3989 $this->line->origin_id = $origin_id;
3990 $this->line->situation_percent = $situation_percent;
3991 $this->line->fk_prev_id = $fk_prev_id;
3992 $this->line->fk_unit = $fk_unit;
3995 $this->line->fk_fournprice = $fk_fournprice;
3996 $this->line->pa_ht = $pa_ht;
3999 $this->line->fk_multicurrency = $this->fk_multicurrency;
4000 $this->line->multicurrency_code = $this->multicurrency_code;
4001 $this->line->multicurrency_subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht_devise) : $pu_ht_devise);
4003 $this->line->multicurrency_total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ht) : $multicurrency_total_ht);
4004 $this->line->multicurrency_total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_tva) : $multicurrency_total_tva);
4005 $this->line->multicurrency_total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ttc) : $multicurrency_total_ttc);
4007 if (is_array($array_options) && count($array_options) > 0) {
4008 $this->line->array_options = $array_options;
4011 $result = $this->line->insert();
4014 if (!empty($fk_parent_line)) {
4016 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
4017 $linecount = count($this->lines);
4018 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
4024 if (empty($noupdateafterinsertline)) {
4029 $this->db->commit();
4030 return $this->line->id;
4032 $this->error = $this->db->lasterror();
4033 $this->db->rollback();
4037 $this->error = $this->line->error;
4038 $this->errors = $this->line->errors;
4039 $this->db->rollback();
4043 $this->errors[] =
'status of invoice must be Draft to allow use of ->addline()';
4044 dol_syslog(get_class($this).
"::addline status of invoice must be Draft to allow use of ->addline()", LOG_ERR);
4080 public function updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type =
'HT', $info_bits = 0, $type = self::TYPE_STANDARD, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice =
null, $pa_ht = 0, $label =
'', $special_code = 0, $array_options = array(), $situation_percent = 100, $fk_unit =
null, $pu_ht_devise = 0, $notrigger = 0, $ref_ext =
'', $rang = 0)
4082 global $conf, $user;
4085 dol_syslog(__METHOD__.
": using line label is deprecated", LOG_WARNING);
4088 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
4090 global $mysoc, $langs;
4092 dol_syslog(get_class($this).
"::updateline rowid=$rowid, desc=$desc, pu=$pu, qty=$qty, remise_percent=$remise_percent, date_start=$date_start, date_end=$date_end, txtva=$txtva, txlocaltax1=$txlocaltax1, txlocaltax2=$txlocaltax2, price_base_type=$price_base_type, info_bits=$info_bits, type=$type, fk_parent_line=$fk_parent_line pa_ht=$pa_ht, special_code=$special_code, fk_unit=$fk_unit, pu_ht_devise=$pu_ht_devise", LOG_DEBUG);
4094 if ($this->
status == self::STATUS_DRAFT) {
4097 if (!$this->error) {
4098 $this->error = $langs->trans(
'invoiceLineProgressError');
4104 if ($date_start && $date_end && $date_start > $date_end) {
4105 $langs->load(
"errors");
4106 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
4116 if (empty($fk_parent_line) || $fk_parent_line < 0) {
4117 $fk_parent_line = 0;
4119 if (empty($special_code) || $special_code == 3) {
4122 if (!isset($situation_percent) || $situation_percent > 100 || (
string) $situation_percent ==
'') {
4123 $situation_percent = 100;
4125 if (empty($ref_ext)) {
4129 $remise_percent =
price2num($remise_percent);
4132 $pu_ht_devise =
price2num($pu_ht_devise);
4134 if (!preg_match(
'/\((.*)\)/', $txtva)) {
4154 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
4155 $vat_src_code = $reg[1];
4156 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
4159 $tabprice =
calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, $situation_percent, $this->multicurrency_tx, $pu_ht_devise);
4161 $total_ht = $tabprice[0];
4162 $total_tva = $tabprice[1];
4163 $total_ttc = $tabprice[2];
4164 $total_localtax1 = $tabprice[9];
4165 $total_localtax2 = $tabprice[10];
4166 $pu_ht = $tabprice[3];
4167 $pu_tva = $tabprice[4];
4168 $pu_ttc = $tabprice[5];
4171 $multicurrency_total_ht = $tabprice[16];
4172 $multicurrency_total_tva = $tabprice[17];
4173 $multicurrency_total_ttc = $tabprice[18];
4174 $pu_ht_devise = $tabprice[19];
4179 if ($remise_percent > 0) {
4180 $remise = round(((
float) $pu * (
float) $remise_percent / 100), 2);
4181 $price = ((float) $pu - $remise);
4187 $line->fetch($rowid);
4188 $line->fetch_optionals();
4190 if (!empty($line->fk_product)) {
4191 $product =
new Product($this->db);
4192 $result = $product->fetch($line->fk_product);
4193 $product_type = $product->type;
4195 if (
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_INVOICE') && $product_type == 0 && $product->stock_reel < $qty) {
4196 $langs->load(
"errors");
4197 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnInvoice', $product->ref);
4198 $this->db->rollback();
4203 $staticline = clone $line;
4205 $line->oldline = $staticline;
4206 $this->line = $line;
4207 $this->line->context = $this->context;
4208 $this->line->rang = $rang;
4211 if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
4212 $rangmax = $this->
line_max($fk_parent_line);
4213 $this->line->rang = $rangmax + 1;
4215 $apply_abs_price_on_credit_note=
false;
4217 $apply_abs_price_on_credit_note =
true;
4221 $this->line->id = $rowid;
4222 $this->line->rowid = $rowid;
4223 $this->line->label = $label;
4224 $this->line->desc = $desc;
4225 $this->line->ref_ext = $ref_ext;
4226 $this->line->qty = ($this->
type == self::TYPE_CREDIT_NOTE ? abs($qty) : $qty);
4228 $this->line->vat_src_code = $vat_src_code;
4229 $this->line->tva_tx = $txtva;
4230 $this->line->localtax1_tx = $txlocaltax1;
4231 $this->line->localtax2_tx = $txlocaltax2;
4232 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
4233 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
4235 $this->line->remise_percent = $remise_percent;
4236 $this->line->subprice = ($apply_abs_price_on_credit_note ? -abs($pu_ht) : $pu_ht);
4237 $this->line->date_start = $date_start;
4238 $this->line->date_end = $date_end;
4239 $this->line->total_ht = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($total_ht) : $total_ht);
4240 $this->line->total_tva = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($total_tva) : $total_tva);
4241 $this->line->total_localtax1 = $total_localtax1;
4242 $this->line->total_localtax2 = $total_localtax2;
4243 $this->line->total_ttc = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($total_ttc) : $total_ttc);
4244 $this->line->info_bits = $info_bits;
4245 $this->line->special_code = $special_code;
4246 $this->line->product_type = $type;
4247 $this->line->fk_parent_line = $fk_parent_line;
4248 $this->line->skip_update_total = $skip_update_total;
4249 $this->line->situation_percent = $situation_percent;
4250 $this->line->fk_unit = $fk_unit;
4252 $this->line->fk_fournprice = $fk_fournprice;
4253 $this->line->pa_ht = $pa_ht;
4256 $this->line->multicurrency_subprice = ($apply_abs_price_on_credit_note ? -abs($pu_ht_devise) : $pu_ht_devise);
4257 $this->line->multicurrency_total_ht = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($multicurrency_total_ht) : $multicurrency_total_ht);
4258 $this->line->multicurrency_total_tva = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($multicurrency_total_tva) : $multicurrency_total_tva);
4259 $this->line->multicurrency_total_ttc = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($multicurrency_total_ttc) : $multicurrency_total_ttc);
4261 if (is_array($array_options) && count($array_options) > 0) {
4263 foreach ($array_options as $key => $value) {
4264 $this->line->array_options[$key] = $array_options[$key];
4268 $result = $this->line->update($user, $notrigger);
4271 if (!empty($fk_parent_line)) {
4277 $this->db->commit();
4280 $this->error = $this->line->error;
4281 $this->db->rollback();
4285 $this->error =
"Invoice statut makes operation forbidden";
4299 $sql =
'SELECT fd.situation_percent FROM '.MAIN_DB_PREFIX.
'facturedet fd
4300 INNER JOIN '.MAIN_DB_PREFIX.
'facture f ON (fd.fk_facture = f.rowid)
4301 WHERE fd.fk_prev_id = '.((int) $idline).
' AND f.fk_statut <> 0';
4303 $result = $this->db->query($sql);
4305 $this->error = $this->db->error();
4309 $obj = $this->db->fetch_object($result);
4311 if ($obj ===
null) {
4314 return ($situation_percent < $obj->situation_percent);
4330 global $mysoc, $user;
4333 if (($line->info_bits & 2) == 2) {
4337 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
4340 if ($percent > 100) {
4343 $line->situation_percent = $percent;
4344 $tabprice =
calcul_price_total($line->qty, $line->subprice, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 0,
'HT', 0, $line->product_type, $mysoc,
'', $percent);
4345 $line->total_ht = $tabprice[0];
4346 $line->total_tva = $tabprice[1];
4347 $line->total_ttc = $tabprice[2];
4348 $line->total_localtax1 = $tabprice[9];
4349 $line->total_localtax2 = $tabprice[10];
4350 $line->multicurrency_total_ht = $tabprice[16];
4351 $line->multicurrency_total_tva = $tabprice[17];
4352 $line->multicurrency_total_ttc = $tabprice[18];
4353 $line->update($user);
4356 if ($update_price) {
4372 dol_syslog(get_class($this).
"::deleteline rowid=".((
int) $rowid), LOG_DEBUG);
4374 if ($this->
status != self::STATUS_DRAFT) {
4375 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
4381 $line->context = $this->context;
4384 $result = $line->fetch($rowid);
4385 if (!($result > 0)) {
4390 if ($id > 0 && $line->fk_facture != $id) {
4391 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
4398 $staticline = clone $line;
4399 $line->oldline = $staticline;
4401 if ($line->delete($user) > 0) {
4405 $this->db->commit();
4408 $this->db->rollback();
4409 $this->error = $this->db->lasterror();
4413 $this->db->rollback();
4414 $this->error = $line->error;
4433 dol_syslog(get_class($this).
"::set_remise is deprecated, use setDiscount instead", LOG_NOTICE);
4434 return $this->
setDiscount($user, $remise, $notrigger);
4449 if (empty($remise)) {
4453 if ($user->hasRight(
'facture',
'creer')) {
4460 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
4461 $sql .=
' SET remise_percent = '.((float) $remise);
4462 $sql .=
" WHERE rowid = ".((int) $this->
id);
4463 $sql .=
' AND fk_statut = '.self::STATUS_DRAFT;
4466 $resql = $this->db->query($sql);
4468 $this->errors[] = $this->db->error();
4472 if (!$notrigger && empty($error)) {
4482 $this->remise_percent = $remise;
4485 $this->db->commit();
4488 foreach ($this->errors as $errmsg) {
4489 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
4490 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
4492 $this->db->rollback();
4579 global $conf, $langs;
4581 if ($this->module_source ==
'takepos') {
4582 $langs->load(
'cashdesk');
4584 $moduleName =
'takepos';
4585 $moduleSourceName =
'Takepos';
4586 $addonConstName =
'TAKEPOS_REF_ADDON';
4590 $conf->global->TAKEPOS_REF_ADDON =
'mod_takepos_ref_simple';
4593 $addon = $conf->global->TAKEPOS_REF_ADDON;
4595 $langs->load(
'bills');
4597 $moduleName =
'facture';
4598 $moduleSourceName =
'Invoice';
4599 $addonConstName =
'FACTURE_ADDON';
4603 $conf->global->FACTURE_ADDON =
'mod_facture_terre';
4605 $conf->global->FACTURE_ADDON =
'mod_facture_terre';
4607 $conf->global->FACTURE_ADDON =
'mod_facture_mercure';
4610 $addon = $conf->global->FACTURE_ADDON;
4613 if (!empty($addon)) {
4614 dol_syslog(
"Call getNextNumRef with ".$addonConstName.
" = " .
getDolGlobalString(
'FACTURE_ADDON').
", thirdparty=".$soc->name.
", type=".$soc->typent_code.
", mode=".$mode, LOG_DEBUG);
4618 $file = $addon.
'.php';
4619 $classname = $addon;
4623 $dirmodels = array_merge(array(
'/'), (array) $conf->modules_parts[
'models']);
4624 foreach ($dirmodels as $reldir) {
4625 $dir =
dol_buildpath($reldir.
'core/modules/'.$moduleName.
'/');
4628 if (is_file($dir.$file) && is_readable($dir.$file)) {
4629 $mybool |= include_once $dir.$file;
4635 $file = $addon.
'/'.$addon.
'.modules.php';
4636 $classname =
'mod_'.$moduleName.
'_'.$addon;
4637 $classname = preg_replace(
'/\-.*$/',
'', $classname);
4639 foreach ($conf->file->dol_document_root as $dirroot) {
4640 $dir = $dirroot.
'/core/modules/'.$moduleName.
'/';
4643 if (is_file($dir.$file) && is_readable($dir.$file)) {
4644 $mybool |= include_once $dir.$file;
4654 $obj =
new $classname();
4656 $numref = $obj->getNextValue($soc, $this, $mode);
4663 if ($mode !=
'last' && !$numref) {
4664 $this->error = $obj->error;
4670 $langs->load(
'errors');
4671 print $langs->trans(
'Error').
' '.$langs->trans(
'ErrorModuleSetupNotComplete', $langs->transnoentitiesnoconv($moduleSourceName));
4684 $sql =
'SELECT c.rowid, datec, date_valid as datev, tms as datem,';
4685 $sql .=
' date_closing as dateclosing,';
4686 $sql .=
' fk_user_author, fk_user_valid, fk_user_closing';
4687 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facture as c';
4688 $sql .=
' WHERE c.rowid = '.((int) $id);
4690 $result = $this->db->query($sql);
4692 if ($this->db->num_rows($result)) {
4693 $obj = $this->db->fetch_object($result);
4695 $this->
id = $obj->rowid;
4696 $this->user_creation_id = $obj->fk_user_author;
4697 $this->user_validation_id = $obj->fk_user_valid;
4698 $this->user_closing_id = $obj->fk_user_closing;
4700 $this->date_creation = $this->db->jdate($obj->datec);
4701 $this->date_modification = $this->db->jdate($obj->datem);
4702 $this->date_validation = $this->db->jdate($obj->datev);
4703 $this->date_closing = $this->db->jdate($obj->dateclosing);
4705 $this->db->free($result);
4726 public function liste_array($shortlist = 0, $draft = 0, $excluser =
null, $socid = 0, $limit = 0, $offset = 0, $sortfield =
'f.datef,f.rowid', $sortorder =
'DESC')
4729 global $conf, $user;
4733 $sql =
"SELECT s.rowid, s.nom as name, s.client,";
4734 $sql .=
" f.rowid as fid, f.ref as ref, f.datef as df";
4735 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4736 $sql .=
", sc.fk_soc, sc.fk_user";
4738 $sql .=
" FROM ".MAIN_DB_PREFIX.
"societe as s, ".MAIN_DB_PREFIX.
"facture as f";
4739 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4740 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
4742 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice').
")";
4743 $sql .=
" AND f.fk_soc = s.rowid";
4744 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4745 $sql .=
" AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4748 $sql .=
" AND s.rowid = ".((int) $socid);
4751 $sql .=
" AND f.fk_statut = ".self::STATUS_DRAFT;
4753 if (is_object($excluser)) {
4754 $sql .=
" AND f.fk_user_author <> ".((int) $excluser->id);
4756 $sql .= $this->db->order($sortfield, $sortorder);
4757 $sql .= $this->db->plimit($limit, $offset);
4759 $result = $this->db->query($sql);
4761 $numc = $this->db->num_rows($result);
4764 while ($i < $numc) {
4765 $obj = $this->db->fetch_object($result);
4767 if ($shortlist == 1) {
4768 $ga[$obj->fid] = $obj->ref;
4769 } elseif ($shortlist == 2) {
4770 $ga[$obj->fid] = $obj->ref.
' ('.$obj->name.
')';
4772 $ga[$i][
'id'] = $obj->fid;
4773 $ga[$i][
'ref'] = $obj->ref;
4774 $ga[$i][
'name'] = $obj->name;
4803 $sql =
"SELECT f.rowid as rowid, f.ref, f.fk_statut as status, f.paye as paid,";
4804 $sql .=
" ff.rowid as rowidnext";
4806 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4807 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"paiement_facture as pf ON f.rowid = pf.fk_facture";
4808 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facture as ff ON f.rowid = ff.fk_facture_source";
4809 $sql .=
" WHERE (f.fk_statut = ".self::STATUS_VALIDATED.
" OR (f.fk_statut = ".self::STATUS_ABANDONED.
" AND f.close_code = '".self::CLOSECODE_ABANDONED.
"'))";
4810 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4811 $sql .=
" AND f.paye = 0";
4812 $sql .=
" AND pf.fk_paiement IS NULL";
4813 $sql .=
" AND ff.fk_statut IS NULL";
4815 $sql .=
" AND f.fk_soc = ".((int) $socid);
4818 $sql .=
" ORDER BY f.ref";
4820 dol_syslog(get_class($this).
"::list_replacable_invoices", LOG_DEBUG);
4821 $resql = $this->db->query($sql);
4823 while ($obj = $this->db->fetch_object($resql)) {
4824 $return[$obj->rowid] = array(
4825 'id' => $obj->rowid,
4827 'status' => $obj->status,
4828 'paid' => $obj->paid,
4835 $this->error = $this->db->error();
4858 $sql =
"SELECT f.rowid as rowid, f.ref, f.fk_statut, f.type, f.subtype, f.paye, pf.fk_paiement";
4859 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4860 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"paiement_facture as pf ON f.rowid = pf.fk_facture";
4861 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facture as ff ON (f.rowid = ff.fk_facture_source AND ff.type=".self::TYPE_REPLACEMENT.
")";
4862 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice').
")";
4863 $sql .=
" AND f.fk_statut in (".self::STATUS_VALIDATED.
",".self::STATUS_CLOSED.
")";
4867 $sql .=
" AND ff.type IS NULL";
4868 $sql .=
" AND f.type <> ".self::TYPE_CREDIT_NOTE;
4872 $sql .=
" AND (f.type <> ".self::TYPE_SITUATION.
" OR f.rowid IN ";
4873 $sql .=
'(SELECT MAX(fs.rowid)';
4874 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as fs";
4875 $sql .=
" WHERE fs.entity IN (".getEntity(
'invoice').
")";
4876 $sql .=
" AND fs.type = ".self::TYPE_SITUATION;
4877 $sql .=
" AND fs.fk_statut IN (".self::STATUS_VALIDATED.
",".self::STATUS_CLOSED.
")";
4879 $sql .=
" AND fs.fk_soc = ".((int) $socid);
4881 $sql .=
" GROUP BY fs.situation_cycle_ref)";
4884 $sql .=
" AND f.type <> ".self::TYPE_SITUATION;
4888 $sql .=
" AND f.fk_soc = ".((int) $socid);
4890 $sql .=
" ORDER BY f.ref";
4892 dol_syslog(get_class($this).
"::list_qualified_avoir_invoices", LOG_DEBUG);
4893 $resql = $this->db->query($sql);
4895 while ($obj = $this->db->fetch_object($resql)) {
4897 if ($obj->fk_statut == self::STATUS_VALIDATED) {
4900 if ($obj->fk_statut == self::STATUS_CLOSED) {
4905 $paymentornot = ($obj->fk_paiement ? 1 : 0);
4906 $return[$obj->rowid] = array(
'ref'=>$obj->ref,
'status'=>$obj->fk_statut,
'type'=>$obj->type,
'paye'=>$obj->paye,
'paymentornot'=>$paymentornot);
4912 $this->error = $this->db->error();
4928 global $conf, $langs;
4932 $sql =
"SELECT f.rowid, f.date_lim_reglement as datefin, f.fk_statut as status, f.total_ht";
4933 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4934 if (!$user->hasRight(
'societe',
'client',
'voir') && !$user->socid) {
4935 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON f.fk_soc = sc.fk_soc";
4936 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
4939 $sql .= $clause.
" f.paye=0";
4940 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4941 $sql .=
" AND f.fk_statut = ".self::STATUS_VALIDATED;
4943 $sql .=
" AND f.fk_soc = ".((int) $user->socid);
4946 $resql = $this->db->query($sql);
4948 $langs->load(
"bills");
4952 $response->warning_delay = $conf->facture->client->warning_delay / 60 / 60 / 24;
4953 $response->label = $langs->trans(
"CustomerBillsUnpaid");
4954 $response->labelShort = $langs->trans(
"Unpaid");
4955 $response->url = DOL_URL_ROOT.
'/compta/facture/list.php?search_status=1&mainmenu=billing&leftmenu=customers_bills';
4958 $generic_facture =
new Facture($this->db);
4960 while ($obj = $this->db->fetch_object($resql)) {
4961 $generic_facture->date_lim_reglement = $this->db->jdate($obj->datefin);
4962 $generic_facture->statut = $obj->status;
4963 $generic_facture->status = $obj->status;
4965 $response->nbtodo++;
4966 $response->total += $obj->total_ht;
4968 if ($generic_facture->hasDelay()) {
4969 $response->nbtodolate++;
4970 $response->url_late = DOL_URL_ROOT.
'/compta/facture/list.php?search_option=late&mainmenu=billing&leftmenu=customers_bills';
4974 $this->db->free($resql);
4978 $this->error = $this->db->error();
5017 global $conf, $langs, $user;
5021 $nownotime =
dol_mktime(0, 0, 0, $arraynow[
'mon'], $arraynow[
'mday'], $arraynow[
'year']);
5026 $sql =
"SELECT rowid";
5027 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
5028 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
5029 $sql .= $this->db->plimit(100);
5031 $resql = $this->db->query($sql);
5033 $num_prods = $this->db->num_rows($resql);
5035 while ($i < $num_prods) {
5037 $row = $this->db->fetch_row($resql);
5038 $prodids[$i] = $row[0];
5042 if (empty($num_prods)) {
5049 $this->
ref =
'SPECIMEN';
5050 $this->specimen = 1;
5052 $this->date = $nownotime;
5053 $this->date_lim_reglement = $nownotime + 3600 * 24 * 30;
5054 $this->cond_reglement_id = 1;
5055 $this->cond_reglement_code =
'RECEP';
5057 $this->mode_reglement_id = 0;
5058 $this->mode_reglement_code =
'';
5060 $this->note_public =
'This is a comment (public)';
5061 $this->note_private =
'This is a comment (private)';
5062 $this->note =
'This is a comment (private)';
5064 $this->fk_user_author = $user->id;
5066 $this->multicurrency_tx = 1;
5067 $this->multicurrency_code = $conf->currency;
5069 $this->fk_incoterms = 0;
5070 $this->location_incoterms =
'';
5072 if (empty($option) || $option !=
'nolines') {
5076 while ($xnbp < $nbp) {
5078 $line->desc = $langs->trans(
"Description").
" ".$xnbp;
5080 $line->subprice = 100;
5081 $line->tva_tx = 19.6;
5082 $line->localtax1_tx = 0;
5083 $line->localtax2_tx = 0;
5084 $line->remise_percent = 0;
5086 $prodid = mt_rand(1, $num_prods);
5087 $line->fk_product = $prodids[$prodid];
5089 $line->total_ht = -100;
5090 $line->total_ttc = -119.6;
5091 $line->total_tva = -19.6;
5092 $line->multicurrency_total_ht = -200;
5093 $line->multicurrency_total_ttc = -239.2;
5094 $line->multicurrency_total_tva = -39.2;
5095 } elseif ($xnbp == 2) {
5096 $line->subprice = -100;
5097 $line->total_ht = -100;
5098 $line->total_ttc = -119.6;
5099 $line->total_tva = -19.6;
5100 $line->remise_percent = 0;
5101 $line->multicurrency_total_ht = -200;
5102 $line->multicurrency_total_ttc = -239.2;
5103 $line->multicurrency_total_tva = -39.2;
5104 } elseif ($xnbp == 3) {
5105 $prodid = mt_rand(1, $num_prods);
5106 $line->fk_product = $prodids[$prodid];
5107 $line->total_ht = 50;
5108 $line->total_ttc = 59.8;
5109 $line->total_tva = 9.8;
5110 $line->multicurrency_total_ht = 100;
5111 $line->multicurrency_total_ttc = 119.6;
5112 $line->multicurrency_total_tva = 19.6;
5113 $line->remise_percent = 50;
5115 $prodid = mt_rand(1, $num_prods);
5116 $line->fk_product = $prodids[$prodid];
5117 $line->total_ht = 100;
5118 $line->total_ttc = 119.6;
5119 $line->total_tva = 19.6;
5120 $line->multicurrency_total_ht = 200;
5121 $line->multicurrency_total_ttc = 239.2;
5122 $line->multicurrency_total_tva = 39.2;
5123 $line->remise_percent = 0;
5126 $this->lines[$xnbp] = $line;
5129 $this->total_ht += $line->total_ht;
5130 $this->total_tva += $line->total_tva;
5131 $this->total_ttc += $line->total_ttc;
5133 $this->multicurrency_total_ht += $line->multicurrency_total_ht;
5134 $this->multicurrency_total_tva += $line->multicurrency_total_tva;
5135 $this->multicurrency_total_ttc += $line->multicurrency_total_ttc;
5139 $this->revenuestamp = 0;
5143 $line->desc = $langs->trans(
"Description").
" (offered line)";
5145 $line->subprice = 100;
5146 $line->tva_tx = 19.6;
5147 $line->localtax1_tx = 0;
5148 $line->localtax2_tx = 0;
5149 $line->remise_percent = 100;
5150 $line->total_ht = 0;
5151 $line->total_ttc = 0;
5152 $line->total_tva = 0;
5153 $line->multicurrency_total_ht = 0;
5154 $line->multicurrency_total_ttc = 0;
5155 $line->multicurrency_total_tva = 0;
5156 $prodid = mt_rand(1, $num_prods);
5157 $line->fk_product = $prodids[$prodid];
5159 $this->lines[$xnbp] = $line;
5173 global $conf, $user;
5175 $this->nb = array();
5179 $sql =
"SELECT count(f.rowid) as nb";
5180 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
5181 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON f.fk_soc = s.rowid";
5182 if (!$user->hasRight(
'societe',
'client',
'voir') && !$user->socid) {
5183 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON s.rowid = sc.fk_soc";
5184 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
5187 $sql .=
" ".$clause.
" f.entity IN (".
getEntity(
'invoice').
")";
5189 $resql = $this->db->query($sql);
5191 while ($obj = $this->db->fetch_object($resql)) {
5192 $this->nb[
"invoices"] = $obj->nb;
5194 $this->db->free($resql);
5198 $this->error = $this->db->error();
5224 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
5226 global $conf, $langs;
5228 $outputlangs->loadLangs(array(
"bills",
"products"));
5232 $thisTypeConfName =
'FACTURE_ADDON_PDF_'.$this->type;
5234 if (!empty($this->model_pdf)) {
5235 $modele = $this->model_pdf;
5239 $modele = $conf->global->FACTURE_ADDON_PDF;
5243 $modelpath =
"core/modules/facture/doc/";
5245 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
5255 $sql =
'SELECT max(situation_cycle_ref) FROM '.MAIN_DB_PREFIX.
'facture as f';
5256 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice', 0).
")";
5257 $resql = $this->db->query($sql);
5259 if ($this->db->num_rows($resql) > 0) {
5260 $res = $this->db->fetch_array($resql);
5261 $ref = $res[
'max(situation_cycle_ref)'];
5266 $this->db->free($resql);
5269 $this->error = $this->db->lasterror();
5270 dol_syslog(
"Error sql=".$sql.
", error=".$this->error, LOG_ERR);
5284 return ($this->situation_counter == 1);
5298 $sql =
'SELECT rowid FROM '.MAIN_DB_PREFIX.
'facture';
5299 $sql .=
' WHERE situation_cycle_ref = '.((int) $this->situation_cycle_ref);
5300 $sql .=
' AND situation_counter < '.((int) $this->situation_counter);
5301 $sql .=
' AND entity = '.($this->entity > 0 ? $this->entity : $conf->entity);
5302 $resql = $this->db->query($sql);
5304 if ($resql && $this->db->num_rows($resql) > 0) {
5305 while ($row = $this->db->fetch_object($resql)) {
5307 $situation =
new Facture($this->db);
5308 $situation->fetch($id);
5309 $res[] = $situation;
5312 $this->error = $this->db->error();
5313 dol_syslog(
"Error sql=".$sql.
", error=".$this->error, LOG_ERR);
5333 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET situation_final = '.((int) $this->situation_final).
' WHERE rowid = '.((int) $this->
id);
5336 $resql = $this->db->query($sql);
5338 $this->errors[] = $this->db->error();
5342 if (!$notrigger && empty($error)) {
5352 $this->db->commit();
5355 foreach ($this->errors as $errmsg) {
5356 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
5357 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
5359 $this->db->rollback();
5375 if (!empty($this->situation_cycle_ref)) {
5377 $sql =
'SELECT max(situation_counter) FROM '.MAIN_DB_PREFIX.
'facture';
5378 $sql .=
' WHERE situation_cycle_ref = '.((int) $this->situation_cycle_ref);
5379 $sql .=
' AND entity = '.($this->entity > 0 ? $this->entity : $conf->entity);
5380 $resql = $this->db->query($sql);
5382 if ($resql && $this->db->num_rows($resql) > 0) {
5383 $res = $this->db->fetch_array($resql);
5384 $last = $res[
'max(situation_counter)'];
5385 return ($last == $this->situation_counter);
5387 $this->error = $this->db->lasterror();
5388 dol_syslog(get_class($this).
"::select Error ".$this->error, LOG_ERR);
5446 $hasDelay = $this->date_lim_reglement < ($now - $conf->facture->client->warning_delay);
5447 if ($hasDelay && !empty($this->retained_warranty) && !empty($this->retained_warranty_date_limit)) {
5449 $totalpaid = (float) $totalpaid;
5451 if ($totalpaid >= 0 && $RetainedWarrantyAmount >= 0) {
5452 if (($totalpaid < $this->total_ttc - $RetainedWarrantyAmount) && $this->date_lim_reglement < ($now - $conf->facture->client->warning_delay)) {
5454 } elseif ($totalpaid < $this->total_ttc && $this->retained_warranty_date_limit < ($now - $conf->facture->client->warning_delay)) {
5477 $displayWarranty =
false;
5478 if (!empty($this->retained_warranty)) {
5479 $displayWarranty =
true;
5483 $displayWarranty =
false;
5484 if (!empty($this->situation_final)) {
5485 $displayWarranty =
true;
5488 $displayWarranty =
true;
5490 foreach ($this->lines as $i => $line) {
5491 if ($line->product_type < 2 && $line->situation_percent < 100) {
5492 $displayWarranty =
false;
5500 return $displayWarranty;
5510 if (empty($this->retained_warranty)) {
5514 $retainedWarrantyAmount = 0;
5518 $displayWarranty =
true;
5520 if (!empty($this->lines)) {
5521 foreach ($this->lines as $i => $line) {
5522 if ($line->product_type < 2 && $line->situation_percent < 100) {
5523 $displayWarranty =
false;
5529 if ($displayWarranty && !empty($this->situation_final)) {
5531 $TPreviousIncoice = $this->tab_previous_situation_invoice;
5534 foreach ($TPreviousIncoice as &$fac) {
5535 $total2BillWT += $fac->total_ttc;
5537 $total2BillWT += $this->total_ttc;
5539 $retainedWarrantyAmount = $total2BillWT * $this->retained_warranty / 100;
5545 $retainedWarrantyAmount = $this->total_ttc * $this->retained_warranty / 100;
5548 if ($rounding < 0) {
5552 if ($rounding > 0) {
5553 return round($retainedWarrantyAmount, $rounding);
5556 return $retainedWarrantyAmount;
5567 dol_syslog(get_class($this).
'::setRetainedWarranty('.$value.
')');
5569 if ($this->
status >= 0) {
5570 $fieldname =
'retained_warranty';
5571 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
5572 $sql .=
" SET ".$fieldname.
" = ".((float) $value);
5573 $sql .=
' WHERE rowid='.((int) $this->
id);
5575 if ($this->db->query($sql)) {
5576 $this->retained_warranty = (float) $value;
5579 dol_syslog(get_class($this).
'::setRetainedWarranty Erreur '.$sql.
' - '.$this->db->error());
5580 $this->error = $this->db->error();
5584 dol_syslog(get_class($this).
'::setRetainedWarranty, status of the object is incompatible');
5585 $this->error =
'Status of the object is incompatible '.$this->status;
5600 if (!$timestamp && $dateYmd) {
5601 $timestamp = $this->db->jdate($dateYmd);
5605 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit('.$timestamp.
')');
5606 if ($this->
status >= 0) {
5607 $fieldname =
'retained_warranty_date_limit';
5608 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
5609 $sql .=
" SET ".$fieldname.
" = ".(strval($timestamp) !=
'' ?
"'".$this->db->idate($timestamp).
"'" :
'null');
5610 $sql .=
' WHERE rowid = '.((int) $this->
id);
5612 if ($this->db->query($sql)) {
5613 $this->retained_warranty_date_limit = $timestamp;
5616 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit Erreur '.$sql.
' - '.$this->db->error());
5617 $this->error = $this->db->error();
5621 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit, status of the object is incompatible');
5622 $this->error =
'Status of the object is incompatible '.$this->status;
5641 global $conf, $langs, $user;
5647 $errorsMsg = array();
5649 $langs->load(
"bills");
5651 if (!isModEnabled(
'facture')) {
5652 $this->output .= $langs->trans(
'ModuleNotEnabled', $langs->transnoentitiesnoconv(
"Facture"));
5655 if (!in_array($datetouse, array(
'duedate',
'invoicedate'))) {
5656 $this->output .=
'Bad value for parameter datetouse. Must be "duedate" or "invoicedate"';
5666 require_once DOL_DOCUMENT_ROOT.
'/core/lib/date.lib.php';
5667 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmail.class.php';
5668 require_once DOL_DOCUMENT_ROOT.
'/core/class/CMailFile.class.php';
5669 $formmail =
new FormMail($this->db);
5674 $tmpinvoice =
new Facture($this->db);
5679 $sql =
"SELECT rowid as id FROM ".MAIN_DB_PREFIX.
"facture as f";
5680 if (!empty($paymentmode) && $paymentmode !=
'all') {
5681 $sql .=
", ".MAIN_DB_PREFIX.
"c_paiement as cp";
5683 $sql .=
" WHERE f.paye = 0";
5684 $sql .=
" AND f.fk_statut = ".self::STATUS_VALIDATED;
5685 if ($datetouse ==
'invoicedate') {
5686 $sql .=
" AND f.datef = '".$this->db->idate($tmpidate,
'gmt').
"'";
5688 $sql .=
" AND f.date_lim_reglement = '".$this->db->idate($tmpidate,
'gmt').
"'";
5690 $sql .=
" AND f.entity IN (".getEntity(
'facture', 0).
")";
5691 if (!empty($paymentmode) && $paymentmode !=
'all') {
5692 $sql .=
" AND f.fk_mode_reglement = cp.id AND cp.code = '".$this->db->escape($paymentmode).
"'";
5695 if ($datetouse ==
'invoicedate') {
5696 $sql .= $this->db->order(
"datef",
"ASC");
5698 $sql .= $this->db->order(
"date_lim_reglement",
"ASC");
5701 $resql = $this->db->query($sql);
5704 if ($datetouse ==
'invoicedate') {
5705 $this->output .= $langs->transnoentitiesnoconv(
"SearchValidatedInvoicesWithDate", $stmpidate);
5707 $this->output .= $langs->transnoentitiesnoconv(
"SearchUnpaidInvoicesWithDueDate", $stmpidate);
5709 if (!empty($paymentmode) && $paymentmode !=
'all') {
5710 $this->output .=
' ('.$langs->transnoentitiesnoconv(
"PaymentMode").
' '.$paymentmode.
')';
5712 $this->output .=
'<br>';
5715 while ($obj = $this->db->fetch_object($resql)) {
5718 $res = $tmpinvoice->fetch($obj->id);
5720 $tmpinvoice->fetch_thirdparty();
5722 $outputlangs =
new Translate(
'', $conf);
5723 if ($tmpinvoice->thirdparty->default_lang) {
5724 $outputlangs->setDefaultLang($tmpinvoice->thirdparty->default_lang);
5725 $outputlangs->loadLangs(array(
"main",
"bills"));
5727 $outputlangs = $langs;
5731 $arraymessage = $formmail->getEMailTemplate($this->db,
'facture_send', $user, $outputlangs, (is_numeric($template) ? $template : 0), 1, (is_numeric($template) ?
'' : $template));
5732 if (is_numeric($arraymessage) && $arraymessage <= 0) {
5733 $langs->load(
"errors");
5734 $this->output .= $langs->trans(
'ErrorFailedToFindEmailTemplate', $template);
5747 $sendTopic =
make_substitutions(empty($arraymessage->topic) ? $outputlangs->transnoentitiesnoconv(
'InformationMessage') : $arraymessage->topic, $substitutionarray, $outputlangs, 1);
5750 $content = $outputlangs->transnoentitiesnoconv($arraymessage->content);
5756 if ($forcerecipient) {
5757 $to = array($forcerecipient);
5759 $res = $tmpinvoice->fetch_thirdparty();
5760 $recipient = $tmpinvoice->thirdparty;
5762 $tmparraycontact = $tmpinvoice->liste_contact(-1,
'external', 0,
'BILLING');
5763 if (is_array($tmparraycontact) && count($tmparraycontact) > 0) {
5764 foreach ($tmparraycontact as $data_email) {
5765 if (!empty($data_email[
'email'])) {
5766 $to[] = $tmpinvoice->thirdparty->contact_get_property($data_email[
'id'],
'email');
5770 if (empty($to) && !empty($recipient->email)) {
5771 $to[] = $recipient->email;
5774 $errormesg =
"Failed to send remind to thirdparty id=".$tmpinvoice->socid.
". No email defined for invoice or customer.";
5778 $errormesg =
"Failed to load recipient with thirdparty id=".$tmpinvoice->socid;
5785 if (!empty($arraymessage->email_from)) {
5786 $from = $arraymessage->email_from;
5789 $errormesg =
"Failed to get sender into global setup MAIN_MAIL_EMAIL_FROM";
5793 if (!$error && !empty($to)) {
5796 $to = implode(
',', $to);
5797 if (!empty($arraymessage->email_to)) {
5798 $to = $to.
','.$arraymessage->email_to;
5802 $errors_to = $conf->global->MAIN_MAIL_ERRORS_TO;
5804 $trackid =
'inv'.$tmpinvoice->id;
5805 $sendcontext =
'standard';
5808 if (!empty($arraymessage->email_tocc)) {
5809 $email_tocc = $arraymessage->email_tocc;
5813 if (!empty($arraymessage->email_tobcc)) {
5814 $email_tobcc = $arraymessage->email_tobcc;
5821 if ($arraymessage->joinfiles == 1 && !empty($tmpinvoice->last_main_doc)) {
5822 $joinFile[] = DOL_DATA_ROOT.
'/'.$tmpinvoice->last_main_doc;
5823 $joinFileName[] = basename($tmpinvoice->last_main_doc);
5824 $joinFileMime[] =
dol_mimetype(DOL_DATA_ROOT.
'/'.$tmpinvoice->last_main_doc);
5828 $cMailFile =
new CMailFile($sendTopic, $to, $from, $sendContent, $joinFile, $joinFileMime, $joinFileName, $email_tocc, $email_tobcc, 0, 1, $errors_to,
'', $trackid,
'', $sendcontext,
'');
5831 if ($cMailFile->sendfile()) {
5835 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
5840 $actioncomm->type_code =
'AC_OTH_AUTO';
5841 $actioncomm->socid = $tmpinvoice->thirdparty->id;
5842 $actioncomm->contact_id = 0;
5844 $actioncomm->code =
'AC_EMAIL';
5845 $actioncomm->label =
'sendEmailsRemindersOnInvoiceDueDateOK (nbdays='.$nbdays.
' paymentmode='.$paymentmode.
' template='.$template.
' datetouse='.$datetouse.
' forcerecipient='.$forcerecipient.
')';
5846 $actioncomm->note_private = $sendContent;
5847 $actioncomm->fk_project = $tmpinvoice->fk_project;
5848 $actioncomm->datep =
dol_now();
5849 $actioncomm->datef = $actioncomm->datep;
5850 $actioncomm->percentage = -1;
5851 $actioncomm->authorid = $user->id;
5852 $actioncomm->userownerid = $user->id;
5854 $actioncomm->email_msgid = $cMailFile->msgid;
5855 $actioncomm->email_subject = $sendTopic;
5856 $actioncomm->email_from = $from;
5857 $actioncomm->email_sender =
'';
5858 $actioncomm->email_to = $to;
5862 $actioncomm->errors_to = $errors_to;
5864 $actioncomm->elementtype =
'invoice';
5865 $actioncomm->fk_element = $tmpinvoice->id;
5869 $actioncomm->create($user);
5871 $errormesg = $cMailFile->error.
' : '.$to;
5875 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
5880 $actioncomm->type_code =
'AC_OTH_AUTO';
5881 $actioncomm->socid = $tmpinvoice->thirdparty->id;
5882 $actioncomm->contact_id = 0;
5884 $actioncomm->code =
'AC_EMAIL';
5885 $actioncomm->label =
'sendEmailsRemindersOnInvoiceDueDateKO';
5886 $actioncomm->note_private = $errormesg;
5887 $actioncomm->fk_project = $tmpinvoice->fk_project;
5888 $actioncomm->datep =
dol_now();
5889 $actioncomm->datef = $actioncomm->datep;
5890 $actioncomm->percentage = -1;
5891 $actioncomm->authorid = $user->id;
5892 $actioncomm->userownerid = $user->id;
5894 $actioncomm->email_msgid = $cMailFile->msgid;
5895 $actioncomm->email_from = $from;
5896 $actioncomm->email_sender =
'';
5897 $actioncomm->email_to = $to;
5901 $actioncomm->errors_to = $errors_to;
5905 $actioncomm->create($user);
5908 $this->db->commit();
5912 $errorsMsg[] = $errormesg;
5915 $errorsMsg[] =
'Failed to fetch record invoice with ID = '.$obj->id;
5925 $this->output .=
'Nb of emails sent : '.$nbMailSend;
5927 dol_syslog(__METHOD__.
" end - ".$this->output, LOG_INFO);
5931 $this->error =
'Nb of emails sent : '.$nbMailSend.
', '.(!empty($errorsMsg)) ? join(
', ', $errorsMsg) : $error;
5933 dol_syslog(__METHOD__.
" end - ".$this->error, LOG_INFO);
5948 $sql =
"SELECT datef";
5949 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture";
5950 $sql .=
" WHERE type = " . (int) $this->
type ;
5951 $sql .=
" AND date_valid IS NOT NULL";
5952 $sql .=
" AND entity IN (".getEntity(
'invoice').
")";
5953 $sql .=
" ORDER BY datef DESC LIMIT 1";
5955 $result = $this->db->query($sql);
5958 if ($this->db->num_rows($result)) {
5959 $obj = $this->db->fetch_object($result);
5960 $last_date = $this->db->jdate($obj->datef);
5961 $invoice_date = $this->date;
5963 $is_last_of_same_type = $invoice_date >= $last_date;
5964 if ($allow_validated_drafts) {
5968 return array($is_last_of_same_type, $last_date);
5991 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
5993 $return =
'<div class="box-flex-item box-flex-grow-zero">';
5994 $return .=
'<div class="info-box info-box-sm">';
5995 $return .=
'<span class="info-box-icon bg-infobox-action">';
5997 $return .=
'</span>';
5998 $return .=
'<div class="info-box-content">';
5999 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl(1) : $this->ref).
'</span>';
6000 if ($selected >= 0) {
6001 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
6003 if (!empty($arraydata[
'thirdparty'])) {
6004 $return .=
'<br><span class="info-box-label">'.$arraydata[
'thirdparty'].
'</span>';
6006 if (property_exists($this,
'date')) {
6007 $return .=
'<br><span class="info-box-label">'.dol_print_date($this->date,
'day').
'</span>';
6009 if (property_exists($this,
'total_ht')) {
6010 $return .=
' <span class="info-box-label amount" title="'.dol_escape_htmltag($langs->trans(
"AmountHT")).
'">'.
price($this->total_ht);
6011 $return .=
' '.$langs->trans(
"HT");
6012 $return .=
'</span>';
6014 if (method_exists($this,
'getLibStatut')) {
6015 $alreadypaid = (empty($arraydata[
'alreadypaid']) ? 0 : $arraydata[
'alreadypaid']);
6016 $return .=
'<br><div class="info-box-status">'.$this->getLibStatut(3, $alreadypaid).
'</div>';
6018 $return .=
'</div>';
6019 $return .=
'</div>';
6020 $return .=
'</div>';
6034 public $element =
'facturedet';
6039 public $table_element =
'facturedet';
6056 public $localtax1_type;
6057 public $localtax2_type;
6058 public $fk_remise_except;
6061 public $fk_fournprice;
6071 public $remise_percent;
6089 public $fk_warehouse;
6098 public $fk_code_ventilation = 0;
6104 public $skip_update_total;
6109 public $situation_percent;
6134 $sql =
'SELECT fd.rowid, fd.fk_facture, fd.fk_parent_line, fd.fk_product, fd.product_type, fd.label as custom_label, fd.description, fd.price, fd.qty, fd.vat_src_code, fd.tva_tx,';
6135 $sql .=
' fd.localtax1_tx, fd. localtax2_tx, fd.remise, fd.remise_percent, fd.fk_remise_except, fd.subprice, fd.ref_ext,';
6136 $sql .=
' fd.date_start as date_start, fd.date_end as date_end, fd.fk_product_fournisseur_price as fk_fournprice, fd.buy_price_ht as pa_ht,';
6137 $sql .=
' fd.info_bits, fd.special_code, fd.total_ht, fd.total_tva, fd.total_ttc, fd.total_localtax1, fd.total_localtax2, fd.rang,';
6138 $sql .=
' fd.fk_code_ventilation,';
6139 $sql .=
' fd.fk_unit, fd.fk_user_author, fd.fk_user_modif,';
6140 $sql .=
' fd.situation_percent, fd.fk_prev_id,';
6141 $sql .=
' fd.multicurrency_subprice,';
6142 $sql .=
' fd.multicurrency_total_ht,';
6143 $sql .=
' fd.multicurrency_total_tva,';
6144 $sql .=
' fd.multicurrency_total_ttc,';
6145 $sql .=
' p.ref as product_ref, p.label as product_label, p.description as product_desc';
6146 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facturedet as fd';
6147 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON fd.fk_product = p.rowid';
6148 $sql .=
' WHERE fd.rowid = '.((int) $rowid);
6150 $result = $this->db->query($sql);
6152 $objp = $this->db->fetch_object($result);
6155 $this->error =
'InvoiceLine with id '. $rowid .
' not found sql='.$sql;
6159 $this->
rowid = $objp->rowid;
6160 $this->
id = $objp->rowid;
6161 $this->fk_facture = $objp->fk_facture;
6162 $this->fk_parent_line = $objp->fk_parent_line;
6163 $this->label = $objp->custom_label;
6164 $this->desc = $objp->description;
6165 $this->qty = $objp->qty;
6166 $this->subprice = $objp->subprice;
6167 $this->ref_ext = $objp->ref_ext;
6168 $this->vat_src_code = $objp->vat_src_code;
6169 $this->tva_tx = $objp->tva_tx;
6170 $this->localtax1_tx = $objp->localtax1_tx;
6171 $this->localtax2_tx = $objp->localtax2_tx;
6172 $this->remise_percent = $objp->remise_percent;
6173 $this->fk_remise_except = $objp->fk_remise_except;
6174 $this->fk_product = $objp->fk_product;
6175 $this->product_type = $objp->product_type;
6176 $this->date_start = $this->db->jdate($objp->date_start);
6177 $this->date_end = $this->db->jdate($objp->date_end);
6178 $this->info_bits = $objp->info_bits;
6179 $this->tva_npr = ($objp->info_bits & 1 == 1) ? 1 : 0;
6180 $this->special_code = $objp->special_code;
6181 $this->total_ht = $objp->total_ht;
6182 $this->total_tva = $objp->total_tva;
6183 $this->total_localtax1 = $objp->total_localtax1;
6184 $this->total_localtax2 = $objp->total_localtax2;
6185 $this->total_ttc = $objp->total_ttc;
6186 $this->fk_code_ventilation = $objp->fk_code_ventilation;
6187 $this->rang = $objp->rang;
6188 $this->fk_fournprice = $objp->fk_fournprice;
6189 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $this->fk_fournprice, $objp->pa_ht);
6190 $this->pa_ht = $marginInfos[0];
6191 $this->marge_tx = $marginInfos[1];
6192 $this->marque_tx = $marginInfos[2];
6194 $this->
ref = $objp->product_ref;
6196 $this->product_ref = $objp->product_ref;
6197 $this->product_label = $objp->product_label;
6198 $this->product_desc = $objp->product_desc;
6200 $this->fk_unit = $objp->fk_unit;
6201 $this->fk_user_modif = $objp->fk_user_modif;
6202 $this->fk_user_author = $objp->fk_user_author;
6204 $this->situation_percent = $objp->situation_percent;
6205 $this->fk_prev_id = $objp->fk_prev_id;
6207 $this->multicurrency_subprice = $objp->multicurrency_subprice;
6208 $this->multicurrency_total_ht = $objp->multicurrency_total_ht;
6209 $this->multicurrency_total_tva = $objp->multicurrency_total_tva;
6210 $this->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
6214 $this->db->free($result);
6218 $this->error = $this->db->lasterror();
6230 public function insert($notrigger = 0, $noerrorifdiscountalreadylinked = 0)
6232 global $langs, $user, $conf;
6236 $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht ==
'');
6238 dol_syslog(get_class($this).
"::insert rang=".$this->rang, LOG_DEBUG);
6241 $this->desc = trim($this->desc);
6242 if (empty($this->tva_tx)) {
6245 if (empty($this->localtax1_tx)) {
6246 $this->localtax1_tx = 0;
6248 if (empty($this->localtax2_tx)) {
6249 $this->localtax2_tx = 0;
6251 if (empty($this->localtax1_type)) {
6252 $this->localtax1_type = 0;
6254 if (empty($this->localtax2_type)) {
6255 $this->localtax2_type = 0;
6257 if (empty($this->total_localtax1)) {
6258 $this->total_localtax1 = 0;
6260 if (empty($this->total_localtax2)) {
6261 $this->total_localtax2 = 0;
6263 if (empty($this->rang)) {
6266 if (empty($this->remise_percent)) {
6267 $this->remise_percent = 0;
6269 if (empty($this->info_bits)) {
6270 $this->info_bits = 0;
6272 if (empty($this->subprice)) {
6273 $this->subprice = 0;
6275 if (empty($this->ref_ext)) {
6276 $this->ref_ext =
'';
6278 if (empty($this->special_code)) {
6279 $this->special_code = 0;
6281 if (empty($this->fk_parent_line)) {
6282 $this->fk_parent_line = 0;
6284 if (empty($this->fk_prev_id)) {
6285 $this->fk_prev_id = 0;
6287 if (!isset($this->situation_percent) || $this->situation_percent > 100 || (
string) $this->situation_percent ==
'') {
6288 $this->situation_percent = 100;
6291 if (empty($this->pa_ht)) {
6294 if (empty($this->multicurrency_subprice)) {
6295 $this->multicurrency_subprice = 0;
6297 if (empty($this->multicurrency_total_ht)) {
6298 $this->multicurrency_total_ht = 0;
6300 if (empty($this->multicurrency_total_tva)) {
6301 $this->multicurrency_total_tva = 0;
6303 if (empty($this->multicurrency_total_ttc)) {
6304 $this->multicurrency_total_ttc = 0;
6308 if ($this->pa_ht == 0 && $pa_ht_isemptystring) {
6309 if (($result = $this->
defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0) {
6312 $this->pa_ht = $result;
6317 if ($this->product_type < 0) {
6318 $this->error =
'ErrorProductTypeMustBe0orMore';
6321 if (!empty($this->fk_product) && $this->fk_product > 0) {
6325 $this->error =
'ErrorProductIdDoesNotExists';
6326 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6334 $sql =
'INSERT INTO '.MAIN_DB_PREFIX.
'facturedet';
6335 $sql .=
' (fk_facture, fk_parent_line, label, description, qty,';
6336 $sql .=
' vat_src_code, tva_tx, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type,';
6337 $sql .=
' fk_product, product_type, remise_percent, subprice, ref_ext, fk_remise_except,';
6338 $sql .=
' date_start, date_end, fk_code_ventilation, ';
6339 $sql .=
' rang, special_code, fk_product_fournisseur_price, buy_price_ht,';
6340 $sql .=
' info_bits, total_ht, total_tva, total_ttc, total_localtax1, total_localtax2,';
6341 $sql .=
' situation_percent, fk_prev_id,';
6342 $sql .=
' fk_unit, fk_user_author, fk_user_modif,';
6343 $sql .=
' fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc';
6345 $sql .=
" VALUES (".$this->fk_facture.
",";
6346 $sql .=
" ".($this->fk_parent_line > 0 ? $this->fk_parent_line :
"null").
",";
6347 $sql .=
" ".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null").
",";
6348 $sql .=
" '".$this->db->escape($this->desc).
"',";
6349 $sql .=
" ".price2num($this->qty).
",";
6350 $sql .=
" ".(empty($this->vat_src_code) ?
"''" :
"'".$this->db->escape($this->vat_src_code).
"'").
",";
6351 $sql .=
" ".price2num($this->tva_tx).
",";
6352 $sql .=
" ".price2num($this->localtax1_tx).
",";
6353 $sql .=
" ".price2num($this->localtax2_tx).
",";
6354 $sql .=
" '".$this->db->escape($this->localtax1_type).
"',";
6355 $sql .=
" '".$this->db->escape($this->localtax2_type).
"',";
6356 $sql .=
' '.((!empty($this->fk_product) && $this->fk_product > 0) ? $this->fk_product :
"null").
',';
6357 $sql .=
" ".((int) $this->product_type).
",";
6358 $sql .=
" ".price2num($this->remise_percent).
",";
6359 $sql .=
" ".price2num($this->subprice).
",";
6360 $sql .=
" '".$this->db->escape($this->ref_ext).
"',";
6361 $sql .=
' '.(!empty($this->fk_remise_except) ? $this->fk_remise_except :
"null").
',';
6362 $sql .=
" ".(!empty($this->date_start) ?
"'".$this->db->idate($this->date_start).
"'" :
"null").
",";
6363 $sql .=
" ".(!empty($this->date_end) ?
"'".$this->db->idate($this->date_end).
"'" :
"null").
",";
6364 $sql .=
' '.((int) $this->fk_code_ventilation).
',';
6365 $sql .=
' '.((int) $this->rang).
',';
6366 $sql .=
' '.((int) $this->special_code).
',';
6367 $sql .=
' '.(!empty($this->fk_fournprice) ? $this->fk_fournprice :
"null").
',';
6368 $sql .=
' '.price2num($this->pa_ht).
',';
6369 $sql .=
" '".$this->db->escape($this->info_bits).
"',";
6370 $sql .=
" ".price2num($this->total_ht).
",";
6371 $sql .=
" ".price2num($this->total_tva).
",";
6372 $sql .=
" ".price2num($this->total_ttc).
",";
6373 $sql .=
" ".price2num($this->total_localtax1).
",";
6374 $sql .=
" ".price2num($this->total_localtax2);
6375 $sql .=
", ".((float) $this->situation_percent);
6376 $sql .=
", ".(!empty($this->fk_prev_id) ? $this->fk_prev_id :
"null");
6377 $sql .=
", ".(!$this->fk_unit ?
'NULL' : $this->fk_unit);
6378 $sql .=
", ".((int) $user->id);
6379 $sql .=
", ".((int) $user->id);
6380 $sql .=
", ".(int) $this->fk_multicurrency;
6381 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
6382 $sql .=
", ".price2num($this->multicurrency_subprice);
6383 $sql .=
", ".price2num($this->multicurrency_total_ht);
6384 $sql .=
", ".price2num($this->multicurrency_total_tva);
6385 $sql .=
", ".price2num($this->multicurrency_total_ttc);
6388 dol_syslog(get_class($this).
"::insert", LOG_DEBUG);
6389 $resql = $this->db->query($sql);
6391 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
'facturedet');
6392 $this->
rowid = $this->id;
6403 if ($this->fk_remise_except) {
6405 $result = $discount->fetch($this->fk_remise_except);
6410 if ($discount->fk_facture_line > 0) {
6411 if (empty($noerrorifdiscountalreadylinked)) {
6412 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed", $discount->id);
6413 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6414 $this->db->rollback();
6418 $result = $discount->link_to_invoice($this->
rowid, 0);
6420 $this->error = $discount->error;
6421 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6422 $this->db->rollback();
6427 $this->error = $langs->trans(
"ErrorADiscountThatHasBeenRemovedIsIncluded");
6428 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6429 $this->db->rollback();
6433 $this->error = $discount->error;
6434 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6435 $this->db->rollback();
6442 $result = $this->
call_trigger(
'LINEBILL_INSERT', $user);
6444 $this->db->rollback();
6450 $this->db->commit();
6453 $this->error = $this->db->lasterror();
6454 $this->db->rollback();
6466 public function update($user =
null, $notrigger = 0)
6468 global $user, $conf;
6472 $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht ==
'');
6475 $this->desc = trim($this->desc);
6476 if (empty($this->ref_ext)) {
6477 $this->ref_ext =
'';
6479 if (empty($this->tva_tx)) {
6482 if (empty($this->localtax1_tx)) {
6483 $this->localtax1_tx = 0;
6485 if (empty($this->localtax2_tx)) {
6486 $this->localtax2_tx = 0;
6488 if (empty($this->localtax1_type)) {
6489 $this->localtax1_type = 0;
6491 if (empty($this->localtax2_type)) {
6492 $this->localtax2_type = 0;
6494 if (empty($this->total_localtax1)) {
6495 $this->total_localtax1 = 0;
6497 if (empty($this->total_localtax2)) {
6498 $this->total_localtax2 = 0;
6500 if (empty($this->remise_percent)) {
6501 $this->remise_percent = 0;
6503 if (empty($this->info_bits)) {
6504 $this->info_bits = 0;
6506 if (empty($this->special_code)) {
6507 $this->special_code = 0;
6509 if (empty($this->product_type)) {
6510 $this->product_type = 0;
6512 if (empty($this->fk_parent_line)) {
6513 $this->fk_parent_line = 0;
6515 if (!isset($this->situation_percent) || $this->situation_percent > 100 || (
string) $this->situation_percent ==
'') {
6516 $this->situation_percent = 100;
6518 if (empty($this->pa_ht)) {
6522 if (empty($this->multicurrency_subprice)) {
6523 $this->multicurrency_subprice = 0;
6525 if (empty($this->multicurrency_total_ht)) {
6526 $this->multicurrency_total_ht = 0;
6528 if (empty($this->multicurrency_total_tva)) {
6529 $this->multicurrency_total_tva = 0;
6531 if (empty($this->multicurrency_total_ttc)) {
6532 $this->multicurrency_total_ttc = 0;
6536 if ($this->product_type < 0) {
6541 if ($this->pa_ht == 0 && $pa_ht_isemptystring) {
6543 $result = $this->
defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product);
6547 $this->pa_ht = $result;
6554 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facturedet SET";
6555 $sql .=
" description='".$this->db->escape($this->desc).
"'";
6556 $sql .=
", ref_ext='".$this->db->escape($this->ref_ext).
"'";
6557 $sql .=
", label=".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null");
6558 $sql .=
", subprice=".price2num($this->subprice);
6559 $sql .=
", remise_percent=".price2num($this->remise_percent);
6560 if ($this->fk_remise_except) {
6561 $sql .=
", fk_remise_except=".$this->fk_remise_except;
6563 $sql .=
", fk_remise_except=null";
6565 $sql .=
", vat_src_code = '".(empty($this->vat_src_code) ?
'' : $this->db->escape($this->vat_src_code)).
"'";
6566 $sql .=
", tva_tx=".price2num($this->tva_tx);
6567 $sql .=
", localtax1_tx=".price2num($this->localtax1_tx);
6568 $sql .=
", localtax2_tx=".price2num($this->localtax2_tx);
6569 $sql .=
", localtax1_type='".$this->db->escape($this->localtax1_type).
"'";
6570 $sql .=
", localtax2_type='".$this->db->escape($this->localtax2_type).
"'";
6571 $sql .=
", qty=".price2num($this->qty);
6572 $sql .=
", date_start=".(!empty($this->date_start) ?
"'".$this->db->idate($this->date_start).
"'" :
"null");
6573 $sql .=
", date_end=".(!empty($this->date_end) ?
"'".$this->db->idate($this->date_end).
"'" :
"null");
6574 $sql .=
", product_type=".$this->product_type;
6575 $sql .=
", info_bits='".$this->db->escape($this->info_bits).
"'";
6576 $sql .=
", special_code='".$this->db->escape($this->special_code).
"'";
6577 if (empty($this->skip_update_total)) {
6578 $sql .=
", total_ht=".price2num($this->total_ht);
6579 $sql .=
", total_tva=".price2num($this->total_tva);
6580 $sql .=
", total_ttc=".price2num($this->total_ttc);
6581 $sql .=
", total_localtax1=".price2num($this->total_localtax1);
6582 $sql .=
", total_localtax2=".price2num($this->total_localtax2);
6584 $sql .=
", fk_product_fournisseur_price=".(!empty($this->fk_fournprice) ?
"'".$this->db->escape($this->fk_fournprice).
"'" :
"null");
6585 $sql .=
", buy_price_ht=".(($this->pa_ht || (string) $this->pa_ht ===
'0') ?
price2num($this->pa_ht) :
"null");
6586 $sql .=
", fk_parent_line=".($this->fk_parent_line > 0 ? $this->fk_parent_line :
"null");
6587 if (!empty($this->rang)) {
6588 $sql .=
", rang=".((int) $this->rang);
6590 $sql .=
", situation_percent = ".((float) $this->situation_percent);
6591 $sql .=
", fk_unit = ".(!$this->fk_unit ?
'NULL' : $this->fk_unit);
6592 $sql .=
", fk_user_modif = ".((int) $user->id);
6595 $sql .=
", multicurrency_subprice=".price2num($this->multicurrency_subprice);
6596 $sql .=
", multicurrency_total_ht=".price2num($this->multicurrency_total_ht);
6597 $sql .=
", multicurrency_total_tva=".price2num($this->multicurrency_total_tva);
6598 $sql .=
", multicurrency_total_ttc=".price2num($this->multicurrency_total_ttc);
6600 $sql .=
" WHERE rowid = ".((int) $this->
rowid);
6602 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
6603 $resql = $this->db->query($sql);
6606 $this->
id = $this->rowid;
6613 if (!$error && !$notrigger) {
6615 $result = $this->
call_trigger(
'LINEBILL_MODIFY', $user);
6617 $this->db->rollback();
6622 $this->db->commit();
6625 $this->error = $this->db->error();
6626 $this->db->rollback();
6638 public function delete($tmpuser =
null, $notrigger =
false)
6645 if (empty($notrigger)) {
6646 $result = $this->
call_trigger(
'LINEBILL_DELETE', $user);
6648 $this->db->rollback();
6657 $this->db->rollback();
6662 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
6663 $sql .=
' SET fk_facture_line = NULL';
6664 $sql .=
' WHERE fk_facture_line = '.((int) $this->
id);
6666 dol_syslog(get_class($this).
"::deleteline", LOG_DEBUG);
6667 $result = $this->db->query($sql);
6669 $this->error = $this->db->error();
6670 $this->errors[] = $this->error;
6671 $this->db->rollback();
6675 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'element_time';
6676 $sql .=
' SET invoice_id = NULL, invoice_line_id = NULL';
6677 $sql .=
' WHERE invoice_line_id = '.((int) $this->
id);
6678 if (!$this->db->query($sql)) {
6679 $this->error = $this->db->error().
" sql=".$sql;
6680 $this->errors[] = $this->error;
6681 $this->db->rollback();
6685 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"facturedet WHERE rowid = ".((int) $this->
id);
6687 if ($this->db->query($sql)) {
6688 $this->db->commit();
6691 $this->error = $this->db->error().
" sql=".$sql;
6692 $this->errors[] = $this->error;
6693 $this->db->rollback();
6709 dol_syslog(get_class($this).
"::update_total", LOG_DEBUG);
6712 if (empty($this->total_localtax1)) {
6713 $this->total_localtax1 = 0;
6715 if (empty($this->total_localtax2)) {
6716 $this->total_localtax2 = 0;
6720 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facturedet SET";
6721 $sql .=
" total_ht=".price2num($this->total_ht);
6722 $sql .=
",total_tva=".price2num($this->total_tva);
6723 $sql .=
",total_localtax1=".price2num($this->total_localtax1);
6724 $sql .=
",total_localtax2=".price2num($this->total_localtax2);
6725 $sql .=
",total_ttc=".price2num($this->total_ttc);
6726 $sql .=
" WHERE rowid = ".((int) $this->
rowid);
6728 dol_syslog(get_class($this).
"::update_total", LOG_DEBUG);
6730 $resql = $this->db->query($sql);
6732 $this->db->commit();
6735 $this->error = $this->db->error();
6736 $this->db->rollback();
6753 global $invoicecache;
6755 if (is_null($this->fk_prev_id) || empty($this->fk_prev_id) || $this->fk_prev_id ==
"") {
6759 if (!isset($invoicecache[$invoiceid])) {
6760 $invoicecache[$invoiceid] =
new Facture($this->db);
6761 $invoicecache[$invoiceid]->fetch($invoiceid);
6767 $sql =
"SELECT situation_percent FROM ".MAIN_DB_PREFIX.
"facturedet WHERE rowid = ".((int) $this->fk_prev_id);
6768 $resql = $this->db->query($sql);
6769 if ($resql && $this->db->num_rows($resql) > 0) {
6770 $res = $this->db->fetch_array($resql);
6772 $returnPercent = (float) $res[
'situation_percent'];
6774 if ($include_credit_note) {
6775 $sql =
'SELECT fd.situation_percent FROM '.MAIN_DB_PREFIX.
'facturedet fd';
6776 $sql .=
' JOIN '.MAIN_DB_PREFIX.
'facture f ON (f.rowid = fd.fk_facture) ';
6777 $sql .=
" WHERE fd.fk_prev_id = ".((int) $this->fk_prev_id);
6778 $sql .=
" AND f.situation_cycle_ref = ".((int) $invoicecache[$invoiceid]->situation_cycle_ref);
6779 $sql .=
" AND f.type = ".Facture::TYPE_CREDIT_NOTE;
6781 $res = $this->db->query($sql);
6783 while ($obj = $this->db->fetch_object($res)) {
6784 $returnPercent = $returnPercent + (float) $obj->situation_percent;
6791 return $returnPercent;
6793 $this->error = $this->db->error();
6794 dol_syslog(get_class($this).
"::select Error ".$this->error, LOG_ERR);
6795 $this->db->rollback();
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Class to manage agenda events (actions)
Class to send emails (with attachments or not) Usage: $mailfile = new CMailFile($subject,...
Superclass for invoices classes.
getSommePaiement($multicurrency=0)
Return amount of payments already done.
calculate_date_lim_reglement($cond_reglement=0)
Returns an invoice payment deadline based on the invoice settlement conditions and billing date.
is_erasable()
Return if an invoice can be deleted Rule is: If invoice is draft and has a temporary ref -> yes (1) I...
Parent class of all other business classes for details of elements (invoices, contracts,...
Parent class of all other business classes (invoices, contracts, proposals, orders,...
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...
line_order($renum=false, $rowidorder='ASC', $fk_parent_line=true)
Save a new position (field rang) for details lines.
deleteEcmFiles($mode=0)
Delete related files of object in database.
add_object_linked($origin=null, $origin_id=null, $f_user=null, $notrigger=0)
Add an object link into llx_element_element.
defineBuyPrice($unitPrice=0.0, $discountPercent=0.0, $fk_product=0)
Get buy price to use for margin calculation.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty.
getIdContact($source, $code, $status=0)
Return id of contacts for a source and a contact code.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid=0, $f_user=null, $notrigger=0)
Delete all links between an object $this.
setErrorsFromObject($object)
setErrorsFromObject
static isExistingObject($element, $id, $ref='', $ref_ext='')
Check an object id/ref exists If you don't need/want to instantiate object and just need to know if o...
updateRangOfLine($rowid, $rang)
Update position of line (rang)
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).
deleteExtraFields()
Delete all extra fields values for the current object.
fetchObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $clause='OR', $alsosametype=1, $orderby='sourcetype', $loadalsoobjects=1)
Fetch array of objects linked to current object (object of enabled modules only).
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
static commonReplaceProduct(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a product id with another one.
line_max($fk_parent_line=0)
Get max value used for position of line (rang)
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
delete_linked_contact($source='', $code='')
Delete all links between an object $this and all its contacts in llx_element_contact.
call_trigger($triggerName, $user)
Call trigger based on this instance.
add_contact($fk_socpeople, $type_contact, $source='external', $notrigger=0)
Add a link between element $this->element and a contact.
Class to manage absolute discounts.
Class to manage Dolibarr database access.
Class to manage warehouses.
Class to manage shipments.
Class to manage invoices.
createFromClone(User $user, $fromid=0)
Load an object from its id and create a new one in database.
setDraft($user, $idwarehouse=-1)
Set draft status.
$fk_facture_source
id of source invoice if replacement invoice or credit note
getIdShippingContact()
Retourne id des contacts clients de livraison.
setFinal(User $user, $notrigger=0)
Sets the invoice as a final situation.
setCanceled($user, $close_code='', $close_note='')
Tag invoice as canceled, with no payment on it (example for replacement invoice or payment never rece...
static createDepositFromOrigin(CommonObject $origin, $date, $payment_terms_id, User $user, $notrigger=0, $autoValidateDeposit=false, $overrideFields=array())
Creates a deposit from a proposal or an order by grouping lines by VAT rates.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
list_replacable_invoices($socid=0)
Return list of invoices qualified to be replaced by another invoice.
insert_discount($idremise)
Add a discount line into an invoice (as an invoice line) using an existing absolute discount (Consume...
createFromOrder($object, User $user)
Load an object from an order and create a new invoice into database.
load_state_board()
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
willBeLastOfSameType($allow_validated_drafts=false)
See if current invoice date is posterior to the last invoice date among validated invoices of same ty...
update_percent($line, $percent, $update_price=true)
Update invoice line with percentage.
const TYPE_REPLACEMENT
Replacement invoice.
validate($user, $force_number='', $idwarehouse=0, $notrigger=0, $batch_rule=0)
Tag invoice as validated + call trigger BILL_VALIDATE Object must have lines loaded with fetch_lines.
deleteline($rowid, $id=0)
Delete line in database.
update(User $user, $notrigger=0)
Update database.
fetch_lines($only_product=0, $loadalsotranslation=0)
Load all detailed lines into this->lines.
$fk_fac_rec_source
id of template invoice when generated from a template invoice
liste_array($shortlist=0, $draft=0, $excluser=null, $socid=0, $limit=0, $offset=0, $sortfield='f.datef, f.rowid', $sortorder='DESC')
Return list of invoices (eventually filtered on a user) into an array.
getIdBillingContact()
Retourne id des contacts clients de facturation.
__construct(DoliDB $db)
Constructor.
const STATUS_DRAFT
Draft status.
updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $txtva, $txlocaltax1=0, $txlocaltax2=0, $price_base_type='HT', $info_bits=0, $type=self::TYPE_STANDARD, $fk_parent_line=0, $skip_update_total=0, $fk_fournprice=null, $pa_ht=0, $label='', $special_code=0, $array_options=array(), $situation_percent=100, $fk_unit=null, $pu_ht_devise=0, $notrigger=0, $ref_ext='', $rang=0)
Update a detail line.
getNomUrl($withpicto=0, $option='', $max=0, $short=0, $moretitle='', $notooltip=0, $addlinktonotes=0, $save_lastsearch_value=-1, $target='')
Return clicable link of object (with eventually picto)
load_board($user)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
fetchPreviousNextSituationInvoice()
Fetch previous and next situations invoices.
fetch($rowid, $ref='', $ref_ext='', $notused=0, $fetch_situation=false)
Get object from database.
const TYPE_STANDARD
Standard invoice.
const TYPE_SITUATION
Situation invoice.
$paye
1 if invoice paid COMPLETELY, 0 otherwise (do not use it anymore, use statut and close_code)
updatePriceNextInvoice(&$langs)
Update price of next invoice.
static replaceProduct(DoliDB $db, $origin_id, $dest_id)
Function used to replace a product id with another one.
setRetainedWarrantyDateLimit($timestamp, $dateYmd='')
Change the retained_warranty_date_limit.
$pos_source
key of pos source ('0', '1', ...)
sendEmailsRemindersOnInvoiceDueDate($nbdays=0, $paymentmode='all', $template='', $datetouse='duedate', $forcerecipient='')
Send reminders by emails for invoices validated that are due.
info($id)
Load miscellaneous information for tab "Info".
const TYPE_PROFORMA
Proforma invoice (should not be used.
addline( $desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $date_start='', $date_end='', $ventil=0, $info_bits=0, $fk_remise_except=0, $price_base_type='HT', $pu_ttc=0, $type=0, $rang=-1, $special_code=0, $origin='', $origin_id=0, $fk_parent_line=0, $fk_fournprice=null, $pa_ht=0, $label='', $array_options=array(), $situation_percent=100, $fk_prev_id=0, $fk_unit=null, $pu_ht_devise=0, $ref_ext='', $noupdateafterinsertline=0)
Add an invoice line into database (linked to product/service or not).
getKanbanView($option='', $arraydata=null)
Return clicable link of object (with eventually picto)
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
setRetainedWarranty($value)
Change the retained warranty.
get_prev_sits()
Returns an array containing the previous situations as Facture objects.
list_qualified_avoir_invoices($socid=0)
Return list of invoices qualified to be corrected by a credit note.
set_canceled($user, $close_code='', $close_note='')
Tag invoice as canceled, with no payment on it (example for replacement invoice or payment never rece...
newCycle()
Gets the smallest reference available for a new cycle.
setDiscount($user, $remise, $notrigger=0)
Set percent discount.
set_ref_client($ref_client, $notrigger=0)
Set customer ref.
is_first()
Checks if the invoice is the first of a cycle.
set_remise($user, $remise, $notrigger=0)
Set percent discount.
getTooltipContentArray($params)
getTooltipContentArray
getNextNumRef($soc, $mode='next')
Set absolute discount.
checkProgressLine($idline, $situation_percent)
Check if the percent edited is lower of next invoice line.
const STATUS_VALIDATED
Validated (need to be paid)
hasDelay()
Is the customer invoice delayed?
getLinesArray()
Create an array of invoice lines.
set_unpaid($user)
Tag la facture comme non payee completement + appel trigger BILL_UNPAYED Fonction utilisee quand un p...
const TYPE_DEPOSIT
Deposit invoice.
set_paid($user, $close_code='', $close_note='')
Tag the invoice as paid completely (if close_code is filled) => this->fk_statut=2,...
const STATUS_ABANDONED
Classified abandoned and no payment done.
createFromCurrent(User $user, $invertdetail=0)
Create a new invoice in database from current invoice.
setPaid($user, $close_code='', $close_note='')
Tag the invoice as :
displayRetainedWarranty()
Currently used for documents generation : to know if retained warranty need to be displayed.
const TYPE_CREDIT_NOTE
Credit note invoice.
is_last_in_cycle()
Checks if the invoice is the last in its cycle.
initAsSpecimen($option='')
Initialise an instance with random values.
getRetainedWarrantyAmount($rounding=-1)
create(User $user, $notrigger=0, $forceduedate=0)
Create invoice in database.
$module_source
key of module source when invoice generated from a dedicated module ('cashdesk', 'takepos',...
setUnpaid($user)
Tag la facture comme non payee completement + appel trigger BILL_UNPAYED Fonction utilisee quand un p...
const STATUS_CLOSED
Classified paid.
createFromContract($object, User $user, $lines=array())
Load an object from an order and create a new invoice into database.
Class to manage invoice lines.
$fk_parent_line
Id parent line.
$special_code
List of special options to define line: 1: shipment cost lines 2: ecotaxe 3: ?? idofmodule: a meaning...
insert($notrigger=0, $noerrorifdiscountalreadylinked=0)
Insert line into database.
get_prev_progress($invoiceid, $include_credit_note=true)
Returns situation_percent of the previous line.
fetch($rowid)
Load invoice line from database.
update($user=null, $notrigger=0)
Update line into database.
$fk_facture
From llx_facturedet Id facture.
__construct($db)
Constructor.
update_total()
Update DB line fields total_xxx Used by migration.
Class to manage invoice templates.
Class to manage stock movements.
static getIdFromCode($dbs, $code)
Get id of currency from code.
static getIdAndTxFromCode($dbs, $code, $date_document='')
Get id and rate of currency from code.
Class to manage predefined suppliers products.
Class to manage products or services.
Manage record for batch number management.
const BATCH_RULE_SELLBY_EATBY_DATES_FIRST
Batches rules.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
hasRight($module, $permlevel1, $permlevel2='')
Return if a user has a permission.
dol_get_first_hour($date, $gm='tzserver')
Return GMT time for first hour of a given GMT date (it removes hours, min and second part)
dol_get_last_hour($date, $gm='tzserver')
Return GMT time for last hour of a given GMT date (it replaces hours, min and second part to 23:59:59...
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
dol_get_next_month($month, $year)
Return next month.
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
dol_delete_preview($object)
Delete all preview files linked to object instance.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
dol_mimetype($file, $default='application/octet-stream', $mode=0)
Return MIME type of a file from its name with extension.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null, $include=null)
Return array of possible common substitutions.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
getDictionaryValue($tablename, $field, $id, $checkentity=false, $rowidfield='rowid')
Return the value of a filed into a dictionary for the record $id.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall right right takeposterminal SELECT e rowid
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall right right takeposterminal SELECT e e e e e statut
getMarginInfos($pvht, $remise_percent, $tva_tx, $localtax1_tx, $localtax2_tx, $fk_pa, $paht)
Return an array with margins information of a line.
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, $multicurrency_code='')
Calculate totals (net, vat, ...) of a line.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type