43require_once DOL_DOCUMENT_ROOT.
'/core/class/commoninvoice.class.php';
44require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobjectline.class.php';
45require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
46require_once DOL_DOCUMENT_ROOT.
'/societe/class/client.class.php';
47require_once DOL_DOCUMENT_ROOT.
'/margin/lib/margins.lib.php';
48require_once DOL_DOCUMENT_ROOT.
'/multicurrency/class/multicurrency.class.php';
50if (isModEnabled(
'accounting')) {
51 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formaccounting.class.php';
53if (isModEnabled(
'accounting')) {
54 require_once DOL_DOCUMENT_ROOT.
'/accountancy/class/accountingaccount.class.php';
65 public $element =
'facture';
70 public $table_element =
'facture';
75 public $table_element_line =
'facturedet';
80 public $fk_element =
'fk_facture';
85 public $picto =
'bill';
91 public $ismultientitymanaged = 1;
97 public $restrictiononfksoc = 1;
127 public $fk_user_author;
139 public $fk_user_valid;
146 public $user_modification;
151 public $fk_user_modif;
161 public $date_livraison;
166 public $delivery_date;
178 public $ref_customer;
182 public $remise_absolue;
191 public $total_localtax1;
192 public $total_localtax2;
194 public $revenuestamp;
224 public $linked_objects = array();
226 public $date_lim_reglement;
227 public $cond_reglement_code;
228 public $cond_reglement_doc;
229 public $mode_reglement_code;
239 public $lines = array();
245 public $extraparams = array();
252 public $date_pointoftax;
258 public $fk_multicurrency;
260 public $multicurrency_code;
261 public $multicurrency_tx;
262 public $multicurrency_total_ht;
263 public $multicurrency_total_tva;
264 public $multicurrency_total_ttc;
265 public $multicurrency_total_localtax1;
266 public $multicurrency_total_localtax2;
271 public $situation_cycle_ref;
276 public $situation_counter;
281 public $situation_final;
286 public $tab_previous_situation_invoice = array();
291 public $tab_next_situation_invoice = array();
298 public $retained_warranty;
303 public $retained_warranty_date_limit;
308 public $retained_warranty_fk_cond_reglement;
340 public $fields = array(
341 'rowid' =>array(
'type'=>
'integer',
'label'=>
'TechnicalID',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>1),
342 'ref' =>array(
'type'=>
'varchar(30)',
'label'=>
'Ref',
'enabled'=>1,
'visible'=>1,
'notnull'=>1,
'showoncombobox'=>1,
'position'=>5),
343 'entity' =>array(
'type'=>
'integer',
'label'=>
'Entity',
'default'=>1,
'enabled'=>1,
'visible'=>-2,
'notnull'=>1,
'position'=>20,
'index'=>1),
344 'ref_client' =>array(
'type'=>
'varchar(255)',
'label'=>
'RefCustomer',
'enabled'=>1,
'visible'=>-1,
'position'=>10),
345 'ref_ext' =>array(
'type'=>
'varchar(255)',
'label'=>
'Ref ext',
'enabled'=>1,
'visible'=>0,
'position'=>12),
346 'type' =>array(
'type'=>
'smallint(6)',
'label'=>
'Type',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>15),
348 'fk_soc' =>array(
'type'=>
'integer:Societe:societe/class/societe.class.php',
'label'=>
'ThirdParty',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>50),
349 'datef' =>array(
'type'=>
'date',
'label'=>
'DateInvoice',
'enabled'=>1,
'visible'=>1,
'position'=>20),
350 'date_valid' =>array(
'type'=>
'date',
'label'=>
'DateValidation',
'enabled'=>1,
'visible'=>-1,
'position'=>22),
351 'date_lim_reglement' =>array(
'type'=>
'date',
'label'=>
'DateDue',
'enabled'=>1,
'visible'=>1,
'position'=>25),
352 'date_closing' =>array(
'type'=>
'datetime',
'label'=>
'Date closing',
'enabled'=>1,
'visible'=>-1,
'position'=>30),
353 'paye' =>array(
'type'=>
'smallint(6)',
'label'=>
'InvoicePaidCompletely',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>80),
356 'remise_absolue' =>array(
'type'=>
'double',
'label'=>
'CustomerRelativeDiscount',
'enabled'=>1,
'visible'=>-1,
'position'=>91),
358 'close_code' =>array(
'type'=>
'varchar(16)',
'label'=>
'EarlyClosingReason',
'enabled'=>1,
'visible'=>-1,
'position'=>92),
359 'close_note' =>array(
'type'=>
'varchar(128)',
'label'=>
'EarlyClosingComment',
'enabled'=>1,
'visible'=>-1,
'position'=>93),
360 'total_ht' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountHT',
'enabled'=>1,
'visible'=>1,
'position'=>95,
'isameasure'=>1),
361 'total_tva' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountVAT',
'enabled'=>1,
'visible'=>-1,
'position'=>100,
'isameasure'=>1),
362 'localtax1' =>array(
'type'=>
'double(24,8)',
'label'=>
'LT1',
'enabled'=>1,
'visible'=>-1,
'position'=>110,
'isameasure'=>1),
363 'localtax2' =>array(
'type'=>
'double(24,8)',
'label'=>
'LT2',
'enabled'=>1,
'visible'=>-1,
'position'=>120,
'isameasure'=>1),
364 'revenuestamp' =>array(
'type'=>
'double(24,8)',
'label'=>
'RevenueStamp',
'enabled'=>1,
'visible'=>-1,
'position'=>115,
'isameasure'=>1),
365 'total_ttc' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountTTC',
'enabled'=>1,
'visible'=>1,
'position'=>130,
'isameasure'=>1),
366 'fk_facture_source' =>array(
'type'=>
'integer',
'label'=>
'SourceInvoice',
'enabled'=>1,
'visible'=>-1,
'position'=>170),
367 'fk_projet' =>array(
'type'=>
'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)',
'label'=>
'Project',
'enabled'=>1,
'visible'=>-1,
'position'=>175),
368 'fk_account' =>array(
'type'=>
'integer',
'label'=>
'Fk account',
'enabled'=>1,
'visible'=>-1,
'position'=>180),
369 'fk_currency' =>array(
'type'=>
'varchar(3)',
'label'=>
'CurrencyCode',
'enabled'=>1,
'visible'=>-1,
'position'=>185),
370 'fk_cond_reglement' =>array(
'type'=>
'integer',
'label'=>
'PaymentTerm',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>190),
371 'fk_mode_reglement' =>array(
'type'=>
'integer',
'label'=>
'PaymentMode',
'enabled'=>1,
'visible'=>-1,
'position'=>195),
372 'note_private' =>array(
'type'=>
'html',
'label'=>
'NotePrivate',
'enabled'=>1,
'visible'=>0,
'position'=>205),
373 'note_public' =>array(
'type'=>
'html',
'label'=>
'NotePublic',
'enabled'=>1,
'visible'=>0,
'position'=>210),
374 'model_pdf' =>array(
'type'=>
'varchar(255)',
'label'=>
'Model pdf',
'enabled'=>1,
'visible'=>0,
'position'=>215),
375 'extraparams' =>array(
'type'=>
'varchar(255)',
'label'=>
'Extraparams',
'enabled'=>1,
'visible'=>-1,
'position'=>225),
376 'situation_cycle_ref' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation cycle ref',
'enabled'=>
'$conf->global->INVOICE_USE_SITUATION',
'visible'=>-1,
'position'=>230),
377 'situation_counter' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation counter',
'enabled'=>
'$conf->global->INVOICE_USE_SITUATION',
'visible'=>-1,
'position'=>235),
378 'situation_final' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation final',
'enabled'=>
'empty($conf->global->INVOICE_USE_SITUATION) ? 0 : 1',
'visible'=>-1,
'position'=>240),
379 'retained_warranty' =>array(
'type'=>
'double',
'label'=>
'Retained warranty',
'enabled'=>
'$conf->global->INVOICE_USE_RETAINED_WARRANTY',
'visible'=>-1,
'position'=>245),
380 'retained_warranty_date_limit' =>array(
'type'=>
'date',
'label'=>
'Retained warranty date limit',
'enabled'=>
'$conf->global->INVOICE_USE_RETAINED_WARRANTY',
'visible'=>-1,
'position'=>250),
381 '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),
382 'fk_incoterms' =>array(
'type'=>
'integer',
'label'=>
'IncotermCode',
'enabled'=>
'$conf->incoterm->enabled',
'visible'=>-1,
'position'=>260),
383 'location_incoterms' =>array(
'type'=>
'varchar(255)',
'label'=>
'IncotermLabel',
'enabled'=>
'$conf->incoterm->enabled',
'visible'=>-1,
'position'=>265),
384 'date_pointoftax' =>array(
'type'=>
'date',
'label'=>
'DatePointOfTax',
'enabled'=>
'$conf->global->INVOICE_POINTOFTAX_DATE',
'visible'=>-1,
'position'=>270),
385 'fk_multicurrency' =>array(
'type'=>
'integer',
'label'=>
'MulticurrencyID',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>275),
386 'multicurrency_code' =>array(
'type'=>
'varchar(255)',
'label'=>
'Currency',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>280),
387 'multicurrency_tx' =>array(
'type'=>
'double(24,8)',
'label'=>
'CurrencyRate',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>285,
'isameasure'=>1),
388 'multicurrency_total_ht' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountHT',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>290,
'isameasure'=>1),
389 'multicurrency_total_tva' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountVAT',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>291,
'isameasure'=>1),
390 'multicurrency_total_ttc' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountTTC',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>292,
'isameasure'=>1),
391 'fk_fac_rec_source' =>array(
'type'=>
'integer',
'label'=>
'RecurringInvoiceSource',
'enabled'=>1,
'visible'=>-1,
'position'=>305),
392 'last_main_doc' =>array(
'type'=>
'varchar(255)',
'label'=>
'LastMainDoc',
'enabled'=>1,
'visible'=>-1,
'position'=>310),
393 'module_source' =>array(
'type'=>
'varchar(32)',
'label'=>
'POSModule',
'enabled'=>
"(isModEnabled('cashdesk') || isModEnabled('takepos') || getDolGlobalInt('INVOICE_SHOW_POS'))",
'visible'=>-1,
'position'=>315),
394 'pos_source' =>array(
'type'=>
'varchar(32)',
'label'=>
'POSTerminal',
'enabled'=>
"(isModEnabled('cashdesk') || isModEnabled('takepos') || getDolGlobalInt('INVOICE_SHOW_POS'))",
'visible'=>-1,
'position'=>320),
395 'datec' =>array(
'type'=>
'datetime',
'label'=>
'DateCreation',
'enabled'=>1,
'visible'=>-1,
'position'=>500),
396 'tms' =>array(
'type'=>
'timestamp',
'label'=>
'DateModificationShort',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>502),
397 'fk_user_author' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserAuthor',
'enabled'=>1,
'visible'=>-1,
'position'=>506),
398 'fk_user_modif' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserModif',
'enabled'=>1,
'visible'=>-1,
'notnull'=>-1,
'position'=>508),
399 'fk_user_valid' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserValidation',
'enabled'=>1,
'visible'=>-1,
'position'=>510),
400 'fk_user_closing' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserClosing',
'enabled'=>1,
'visible'=>-1,
'position'=>512),
401 'import_key' =>array(
'type'=>
'varchar(14)',
'label'=>
'ImportId',
'enabled'=>1,
'visible'=>-2,
'position'=>900),
402 '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')),
464 const CLOSECODE_DISCOUNTVAT =
'discount_vat';
465 const CLOSECODE_BADDEBT =
'badcustomer';
466 const CLOSECODE_BANKCHARGE =
'bankcharge';
467 const CLOSECODE_OTHER =
'other';
469 const CLOSECODE_ABANDONED =
'abandon';
470 const CLOSECODE_REPLACED =
'replaced';
493 public function create(
User $user, $notrigger = 0, $forceduedate = 0)
495 global $langs, $conf, $mysoc, $hookmanager;
499 if (empty($this->
type)) {
503 $this->ref_client = trim($this->ref_client);
505 $this->note = (isset($this->note) ? trim($this->note) : trim($this->note_private));
506 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note_private));
507 $this->note_public = trim($this->note_public);
508 if (!$this->cond_reglement_id) {
509 $this->cond_reglement_id = 0;
511 if (!$this->mode_reglement_id) {
512 $this->mode_reglement_id = 0;
514 $this->brouillon = 1;
518 if (!empty($this->multicurrency_code)) {
520 if (empty($this->multicurrency_tx)) {
528 $this->fk_multicurrency = 0;
530 if (empty($this->fk_multicurrency)) {
531 $this->multicurrency_code = $conf->currency;
532 $this->fk_multicurrency = 0;
533 $this->multicurrency_tx = 1;
536 dol_syslog(get_class($this).
"::create user=".$user->id.
" date=".$this->date);
539 if (empty($this->date)) {
540 $this->error =
"Try to create an invoice with an empty parameter (date)";
541 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
545 $result = $soc->fetch($this->socid);
547 $this->error =
"Failed to fetch company: ".$soc->error;
548 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
553 $this->date_creation = $now;
557 $originaldatewhen =
null;
558 $nextdatewhen =
null;
559 $previousdaynextdatewhen =
null;
562 if ($this->fac_rec > 0) {
563 $this->fk_fac_rec_source = $this->fac_rec;
565 require_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture-rec.class.php';
567 $result = $_facrec->fetch($this->fac_rec);
568 $result = $_facrec->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 0);
571 $originaldatewhen = $_facrec->date_when;
572 $nextdatewhen =
null; $previousdaynextdatewhen =
null;
573 if ($originaldatewhen) {
574 $nextdatewhen =
dol_time_plus_duree($originaldatewhen, $_facrec->frequency, $_facrec->unit_frequency);
578 if (!empty($_facrec->frequency)) {
579 $this->socid = $_facrec->socid;
581 $this->entity = $_facrec->entity;
584 $this->fk_project =
GETPOST(
'projectid',
'int') > 0 ? ((int)
GETPOST(
'projectid',
'int')) : $_facrec->fk_project;
585 $this->note_public = GETPOSTISSET(
'note_public') ?
GETPOST(
'note_public',
'restricthtml') : $_facrec->note_public;
586 $this->note_private = GETPOSTISSET(
'note_private') ?
GETPOST(
'note_private',
'restricthtml') : $_facrec->note_private;
587 $this->model_pdf = GETPOSTISSET(
'model') ?
GETPOST(
'model',
'alpha') : $_facrec->model_pdf;
588 $this->cond_reglement_id =
GETPOST(
'cond_reglement_id',
'int') > 0 ? ((int)
GETPOST(
'cond_reglement_id',
'int')) : $_facrec->cond_reglement_id;
589 $this->mode_reglement_id =
GETPOST(
'mode_reglement_id',
'int') > 0 ? ((int)
GETPOST(
'mode_reglement_id',
'int')) : $_facrec->mode_reglement_id;
590 $this->fk_account =
GETPOST(
'fk_account') > 0 ? ((int)
GETPOST(
'fk_account')) : $_facrec->fk_account;
593 $this->total_ht = $_facrec->total_ht;
594 $this->total_ttc = $_facrec->total_ttc;
597 $this->remise_absolue = $_facrec->remise_absolue;
598 $this->remise_percent = $_facrec->remise_percent;
599 $this->fk_incoterms = $_facrec->fk_incoterms;
600 $this->location_incoterms = $_facrec->location_incoterms;
606 $this->ref_client = trim($this->ref_client);
607 $this->ref_customer = trim($this->ref_customer);
608 $this->note_public = trim($this->note_public);
609 $this->note_private = trim($this->note_private);
610 $this->note_private =
dol_concatdesc($this->note_private, $langs->trans(
"GeneratedFromRecurringInvoice", $_facrec->ref));
612 $this->array_options = $_facrec->array_options;
614 if (!$this->mode_reglement_id) {
615 $this->mode_reglement_id = 0;
617 $this->brouillon = 1;
621 $this->linked_objects = $_facrec->linkedObjectsIds;
626 if ($_facrec->frequency > 0) {
627 dol_syslog(
"This is a recurring invoice so we set date_last_gen and next date_when");
628 if (empty($_facrec->date_when)) {
629 $_facrec->date_when = $now;
631 $next_date = $_facrec->getNextDate();
632 $result = $_facrec->setValueFrom(
'date_last_gen', $now,
'',
null,
'date',
'', $user,
'');
634 $result = $_facrec->setNextDate($next_date, 1);
638 $outputlangs = $langs;
641 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && empty($newlang) && isset($this->thirdparty->default_lang)) {
642 $newlang = $this->thirdparty->default_lang;
644 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && empty($newlang) && isset($this->default_lang)) {
645 $newlang = $this->default_lang;
647 if (!empty($newlang)) {
649 $outputlangs->setDefaultLang($newlang);
655 $substitutionarray[
'__INVOICE_MONTH__'] =
dol_print_date($this->date,
'%m');
658 $substitutionarray[
'__INVOICE_MONTH_TEXT__'] =
dol_print_date($this->date,
'%B');
661 $substitutionarray[
'__INVOICE_YEAR__'] =
dol_print_date($this->date,
'%Y');
664 $substitutionarray[
'__INVOICE_DATE_NEXT_INVOICE_BEFORE_GEN__'] = (isset($originaldatewhen) ?
dol_print_date($originaldatewhen,
'dayhour') :
'');
665 $substitutionarray[
'__INVOICE_DATE_NEXT_INVOICE_AFTER_GEN__'] = (isset($nextdatewhen) ?
dol_print_date($nextdatewhen,
'dayhour') :
'');
666 $substitutionarray[
'__INVOICE_PREVIOUS_DATE_NEXT_INVOICE_AFTER_GEN__'] = (isset($previousdaynextdatewhen) ?
dol_print_date($previousdaynextdatewhen,
'dayhour') :
'');
667 $substitutionarray[
'__INVOICE_COUNTER_CURRENT__'] = $_facrec->nb_gen_done;
668 $substitutionarray[
'__INVOICE_COUNTER_MAX__'] = $_facrec->nb_gen_max;
679 if (empty($forceduedate)) {
685 $this->date_lim_reglement = $duedate;
687 $this->date_lim_reglement = $forceduedate;
691 $socid = $this->socid;
693 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"facture (";
700 $sql .=
", remise_absolue";
701 $sql .=
", remise_percent";
703 $sql .=
", date_pointoftax";
704 $sql .=
", note_private";
705 $sql .=
", note_public";
706 $sql .=
", ref_client";
707 $sql .=
", fk_account";
708 $sql .=
", module_source, pos_source, fk_fac_rec_source, fk_facture_source, fk_user_author, fk_projet";
709 $sql .=
", fk_cond_reglement, fk_mode_reglement, date_lim_reglement, model_pdf";
710 $sql .=
", situation_cycle_ref, situation_counter, situation_final";
711 $sql .=
", fk_incoterms, location_incoterms";
712 $sql .=
", fk_multicurrency";
713 $sql .=
", multicurrency_code";
714 $sql .=
", multicurrency_tx";
715 $sql .=
", retained_warranty";
716 $sql .=
", retained_warranty_date_limit";
717 $sql .=
", retained_warranty_fk_cond_reglement";
721 $sql .=
", ".setEntity($this);
722 $sql .=
", ".($this->ref_ext ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
723 $sql .=
", '".$this->db->escape($this->
type).
"'";
724 $sql .=
", ".((int) $socid);
725 $sql .=
", '".$this->db->idate($this->date_creation).
"'";
726 $sql .=
", ".($this->remise_absolue > 0 ? $this->remise_absolue :
'NULL');
727 $sql .=
", ".($this->remise_percent > 0 ? $this->remise_percent :
'NULL');
728 $sql .=
", '".$this->db->idate($this->date).
"'";
729 $sql .=
", ".(empty($this->date_pointoftax) ?
"null" :
"'".$this->db->idate($this->date_pointoftax).
"'");
730 $sql .=
", ".($this->note_private ?
"'".$this->db->escape($this->note_private).
"'" :
"null");
731 $sql .=
", ".($this->note_public ?
"'".$this->db->escape($this->note_public).
"'" :
"null");
732 $sql .=
", ".($this->ref_customer ?
"'".$this->db->escape($this->ref_customer).
"'" : ($this->ref_client ?
"'".$this->db->escape($this->ref_client).
"'" :
"null"));
733 $sql .=
", ".($this->fk_account > 0 ? $this->fk_account :
'NULL');
734 $sql .=
", ".($this->module_source ?
"'".$this->db->escape($this->module_source).
"'" :
"null");
735 $sql .=
", ".($this->pos_source !=
'' ?
"'".$this->db->escape($this->pos_source).
"'" :
"null");
736 $sql .=
", ".($this->fk_fac_rec_source ?
"'".$this->db->escape($this->fk_fac_rec_source).
"'" :
"null");
737 $sql .=
", ".($this->fk_facture_source ?
"'".$this->db->escape($this->fk_facture_source).
"'" :
"null");
738 $sql .=
", ".($user->id > 0 ? (int) $user->id :
"null");
739 $sql .=
", ".($this->fk_project ? $this->fk_project :
"null");
740 $sql .=
", ".((int) $this->cond_reglement_id);
741 $sql .=
", ".((int) $this->mode_reglement_id);
742 $sql .=
", '".$this->db->idate($this->date_lim_reglement).
"'";
743 $sql .=
", ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null");
744 $sql .=
", ".($this->situation_cycle_ref ?
"'".$this->db->escape($this->situation_cycle_ref).
"'" :
"null");
745 $sql .=
", ".($this->situation_counter ?
"'".$this->db->escape($this->situation_counter).
"'" :
"null");
746 $sql .=
", ".($this->situation_final ? $this->situation_final : 0);
747 $sql .=
", ".(int) $this->fk_incoterms;
748 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
749 $sql .=
", ".(int) $this->fk_multicurrency;
750 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
751 $sql .=
", ".(double) $this->multicurrency_tx;
752 $sql .=
", ".(empty($this->retained_warranty) ?
"0" : $this->db->escape($this->retained_warranty));
753 $sql .=
", ".(!empty($this->retained_warranty_date_limit) ?
"'".$this->db->idate($this->retained_warranty_date_limit).
"'" :
'NULL');
754 $sql .=
", ".(int) $this->retained_warranty_fk_cond_reglement;
757 $resql = $this->db->query($sql);
759 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
'facture');
762 $this->
ref =
'(PROV'.$this->id.
')';
763 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"facture SET ref='".$this->db->escape($this->
ref).
"' WHERE rowid=".((int) $this->
id);
765 $resql = $this->db->query($sql);
770 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {
771 $this->linked_objects = $this->linkedObjectsIds;
775 if (!$error && $this->
id && !empty($this->linked_objects) && is_array($this->linked_objects)) {
776 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
777 if (is_array($tmp_origin_id)) {
778 foreach ($tmp_origin_id as $origin_id) {
781 $this->error = $this->db->lasterror();
787 $origin_id = $tmp_origin_id;
790 $this->error = $this->db->lasterror();
798 if (!$error && $this->
id && !empty($conf->global->MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN) && !empty($this->origin) && !empty($this->origin_id)) {
799 $originforcontact = $this->origin;
800 $originidforcontact = $this->origin_id;
801 if ($originforcontact ==
'shipping') {
802 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expedition.class.php';
804 $exp->fetch($this->origin_id);
805 $exp->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 0);
806 if (count($exp->linkedObjectsIds[
'commande']) > 0) {
807 foreach ($exp->linkedObjectsIds[
'commande'] as $key => $value) {
808 $originforcontact =
'commande';
809 if (is_object($value)) {
810 $originidforcontact = $value->id;
812 $originidforcontact = $value;
819 $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";
820 $sqlcontact .=
" WHERE element_id = ".((int) $originidforcontact).
" AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$this->db->escape($originforcontact).
"'";
822 $resqlcontact = $this->db->query($sqlcontact);
824 while ($objcontact = $this->db->fetch_object($resqlcontact)) {
826 $this->
add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source);
836 if (!$error && empty($this->fac_rec) && count($this->lines) && is_object($this->lines[0])) {
839 dol_syslog(
"There is ".count($this->lines).
" lines that are invoice lines objects");
840 foreach ($this->lines as $i => $val) {
841 $newinvoiceline = $this->lines[$i];
843 $newinvoiceline->context = $this->context;
845 $newinvoiceline->fk_facture = $this->id;
847 $newinvoiceline->origin = $this->lines[$i]->element;
848 $newinvoiceline->origin_id = $this->lines[$i]->id;
851 if ($this->lines[$i]->date_start_fill == 1 && $originaldatewhen) {
852 $newinvoiceline->date_start = $originaldatewhen;
854 if ($this->lines[$i]->date_end_fill == 1 && $previousdaynextdatewhen) {
855 $newinvoiceline->date_end = $previousdaynextdatewhen;
860 if (($newinvoiceline->product_type != 9 && empty($newinvoiceline->fk_parent_line)) || $newinvoiceline->product_type == 9) {
865 $vatrate = $newinvoiceline->tva_tx;
866 if ($newinvoiceline->vat_src_code && ! preg_match(
'/\(.*\)/', $vatrate)) $vatrate.=
' ('.$newinvoiceline->vat_src_code.
')';
868 $newinvoiceline->fk_parent_line = $fk_parent_line;
872 $discount->fetch($newinvoiceline->fk_remise_except);
874 $discountId = $soc->set_remise_except($discount->amount_ht, $user, $discount->description, $discount->tva_tx);
875 $newinvoiceline->fk_remise_except = $discountId;
879 $newinvoiceline->desc,
880 $newinvoiceline->subprice,
881 $newinvoiceline->qty,
883 $newinvoiceline->localtax1_tx,
884 $newinvoiceline->localtax2_tx,
885 $newinvoiceline->fk_product,
886 $newinvoiceline->remise_percent,
887 $newinvoiceline->date_start,
888 $newinvoiceline->date_end,
889 $newinvoiceline->fk_code_ventilation,
890 $newinvoiceline->info_bits,
891 $newinvoiceline->fk_remise_except,
894 $newinvoiceline->product_type,
895 $newinvoiceline->rang,
896 $newinvoiceline->special_code,
897 $newinvoiceline->element,
900 $newinvoiceline->fk_fournprice,
901 $newinvoiceline->pa_ht,
902 $newinvoiceline->label,
903 $newinvoiceline->array_options,
904 $newinvoiceline->situation_percent,
905 $newinvoiceline->fk_prev_id,
906 $newinvoiceline->fk_unit,
907 $newinvoiceline->multicurrency_subprice,
908 $newinvoiceline->ref_ext,
913 if ($result > 0 && $newinvoiceline->product_type == 9) {
914 $fk_parent_line = $result;
918 $this->error = $newinvoiceline->error;
919 $this->errors = $newinvoiceline->errors;
924 } elseif (!$error && empty($this->fac_rec)) {
927 dol_syslog(
"There is ".count($this->lines).
" lines that are array lines");
929 foreach ($this->lines as $i => $val) {
930 $line = $this->lines[$i];
934 if (!is_object($line)) {
935 $line = (object) $line;
940 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
945 $vatrate = $line->tva_tx;
946 if ($line->vat_src_code && !preg_match(
'/\(.*\)/', $vatrate)) {
947 $vatrate .=
' ('.$line->vat_src_code.
')';
950 if (!empty($conf->global->MAIN_CREATEFROM_KEEP_LINE_ORIGIN_INFORMATION)) {
951 $originid = $line->origin_id;
952 $origintype = $line->origin;
954 $originid = $line->id;
955 $origintype = $this->element;
959 if (empty($line->ref_ext)) {
971 $line->remise_percent,
974 $line->fk_code_ventilation,
976 $line->fk_remise_except,
985 $line->fk_fournprice,
988 $line->array_options,
989 $line->situation_percent,
992 $line->multicurrency_subprice,
997 $this->error = $this->db->lasterror();
999 $this->db->rollback();
1004 if ($result > 0 && $line->product_type == 9) {
1005 $fk_parent_line = $result;
1014 if (!$error && $this->fac_rec > 0) {
1015 foreach ($_facrec->lines as $i => $val) {
1016 if ($_facrec->lines[$i]->fk_product) {
1017 $prod =
new Product($this->db);
1018 $res = $prod->fetch($_facrec->lines[$i]->fk_product);
1029 $tva_tx = $_facrec->lines[$i]->tva_tx.($_facrec->lines[$i]->vat_src_code ?
'('.$_facrec->lines[$i]->vat_src_code.
')' :
'');
1030 $tva_npr = $_facrec->lines[$i]->info_bits;
1031 if (empty($tva_tx)) {
1034 $localtax1_tx = $_facrec->lines[$i]->localtax1_tx;
1035 $localtax2_tx = $_facrec->lines[$i]->localtax2_tx;
1037 $fk_product_fournisseur_price = empty($_facrec->lines[$i]->fk_product_fournisseur_price) ? null : $_facrec->lines[$i]->fk_product_fournisseur_price;
1038 $buyprice = empty($_facrec->lines[$i]->buyprice) ? 0 : $_facrec->lines[$i]->buyprice;
1041 if (!$buyprice && $_facrec->lines[$i]->fk_product > 0) {
1042 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
1044 $producttmp->fetch($_facrec->lines[$i]->fk_product);
1049 if ($conf->global->MARGIN_TYPE ==
'costprice' && !empty($producttmp->cost_price)) {
1050 $buyprice = $producttmp->cost_price;
1051 } elseif (isModEnabled(
'stock') && ($conf->global->MARGIN_TYPE ==
'costprice' || $conf->global->MARGIN_TYPE ==
'pmp') && !empty($producttmp->pmp)) {
1052 $buyprice = $producttmp->pmp;
1054 if ($producttmp->find_min_price_product_fournisseur($_facrec->lines[$i]->fk_product) > 0) {
1055 if ($producttmp->product_fourn_price_id > 0) {
1056 $buyprice =
price2num($producttmp->fourn_unitprice * (1 - $producttmp->fourn_remise_percent / 100) + $producttmp->fourn_remise,
'MU');
1062 $result_insert = $this->
addline(
1063 $_facrec->lines[$i]->desc,
1064 $_facrec->lines[$i]->subprice,
1065 $_facrec->lines[$i]->qty,
1069 $_facrec->lines[$i]->fk_product,
1070 $_facrec->lines[$i]->remise_percent,
1071 ($_facrec->lines[$i]->date_start_fill == 1 && $originaldatewhen) ? $originaldatewhen :
'',
1072 ($_facrec->lines[$i]->date_end_fill == 1 && $previousdaynextdatewhen) ? $previousdaynextdatewhen :
'',
1078 $_facrec->lines[$i]->product_type,
1079 $_facrec->lines[$i]->rang,
1080 $_facrec->lines[$i]->special_code,
1084 $fk_product_fournisseur_price,
1086 $_facrec->lines[$i]->label,
1087 empty($_facrec->lines[$i]->array_options) ?
null:$_facrec->lines[$i]->array_options,
1090 $_facrec->lines[$i]->fk_unit,
1091 $_facrec->lines[$i]->multicurrency_subprice,
1092 $_facrec->lines[$i]->ref_ext,
1096 if ($result_insert < 0) {
1098 $this->error = $this->db->error();
1117 if (!$error && !$notrigger) {
1127 $this->db->commit();
1130 $this->db->rollback();
1134 $this->error = $langs->trans(
'FailedToUpdatePrice');
1135 $this->db->rollback();
1139 dol_syslog(get_class($this).
"::create error ".$this->error, LOG_ERR);
1140 $this->db->rollback();
1144 $this->error = $this->db->error();
1145 $this->db->rollback();
1163 $facture =
new Facture($this->db);
1169 if (!empty($this->array_options)) {
1170 $facture->array_options = $this->array_options;
1173 foreach ($this->lines as &$line) {
1174 $line->fetch_optionals();
1178 $facture->type = $this->type;
1179 $facture->socid = $this->socid;
1180 $facture->date = $this->date;
1181 $facture->date_pointoftax = $this->date_pointoftax;
1182 $facture->note_public = $this->note_public;
1183 $facture->note_private = $this->note_private;
1184 $facture->ref_client = $this->ref_client;
1185 $facture->modelpdf = $this->model_pdf;
1186 $facture->model_pdf = $this->model_pdf;
1187 $facture->fk_project = $this->fk_project;
1188 $facture->cond_reglement_id = $this->cond_reglement_id;
1189 $facture->mode_reglement_id = $this->mode_reglement_id;
1190 $facture->remise_absolue = $this->remise_absolue;
1193 $facture->origin = $this->origin;
1194 $facture->origin_id = $this->origin_id;
1195 $facture->fk_account = $this->fk_account;
1197 $facture->lines = $this->lines;
1198 $facture->situation_counter = $this->situation_counter;
1199 $facture->situation_cycle_ref = $this->situation_cycle_ref;
1200 $facture->situation_final = $this->situation_final;
1202 $facture->retained_warranty = $this->retained_warranty;
1203 $facture->retained_warranty_fk_cond_reglement = $this->retained_warranty_fk_cond_reglement;
1204 $facture->retained_warranty_date_limit = $this->retained_warranty_date_limit;
1206 $facture->fk_user_author = $user->id;
1210 foreach ($facture->lines as $i => $tmpline) {
1211 $facture->lines[$i]->fk_prev_id = $this->lines[$i]->rowid;
1212 if ($invertdetail) {
1213 $facture->lines[$i]->subprice = -$facture->lines[$i]->subprice;
1214 $facture->lines[$i]->total_ht = -$facture->lines[$i]->total_ht;
1215 $facture->lines[$i]->total_tva = -$facture->lines[$i]->total_tva;
1216 $facture->lines[$i]->total_localtax1 = -$facture->lines[$i]->total_localtax1;
1217 $facture->lines[$i]->total_localtax2 = -$facture->lines[$i]->total_localtax2;
1218 $facture->lines[$i]->total_ttc = -$facture->lines[$i]->total_ttc;
1219 $facture->lines[$i]->ref_ext =
'';
1223 dol_syslog(get_class($this).
"::createFromCurrent invertdetail=".$invertdetail.
" socid=".$this->socid.
" nboflines=".count($facture->lines));
1225 $facid = $facture->create($user);
1227 $this->error = $facture->error;
1228 $this->errors = $facture->errors;
1229 } elseif ($this->
type == self::TYPE_SITUATION && !empty($conf->global->INVOICE_USE_SITUATION)) {
1232 foreach ($this->linkedObjectsIds as $typeObject => $Tfk_object) {
1233 foreach ($Tfk_object as $fk_object) {
1234 $facture->add_object_linked($typeObject, $fk_object);
1238 $facture->add_object_linked(
'facture', $this->fk_facture_source);
1254 global $conf, $hookmanager;
1258 $object =
new Facture($this->db);
1262 $object->fetch($fromid);
1265 $objFrom = clone $object;
1268 if (!empty($this->socid) && $this->socid != $object->socid) {
1269 $objsoc =
new Societe($this->db);
1271 if ($objsoc->fetch($this->socid) > 0) {
1272 $object->socid = $objsoc->id;
1273 $object->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1274 $object->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1275 $object->fk_project =
'';
1276 $object->fk_delivery_address =
'';
1287 $object->date = (empty($this->date) ?
dol_now() : $this->date);
1288 $object->user_author = $user->id;
1289 $object->user_valid =
null;
1290 $object->fk_user_author = $user->id;
1291 $object->fk_user_valid =
null;
1292 $object->fk_facture_source = 0;
1293 $object->date_creation =
'';
1294 $object->date_modification =
'';
1295 $object->date_validation =
'';
1296 $object->ref_client =
'';
1297 $object->close_code =
'';
1298 $object->close_note =
'';
1300 $object->note_private =
'';
1301 $object->note_public =
'';
1305 foreach ($object->lines as $i => $line) {
1306 if (($object->lines[$i]->info_bits & 0x02) == 0x02) {
1307 unset($object->lines[$i]);
1313 if (!empty($conf->global->INVOICE_AUTO_NEXT_MONTH_ON_LINES) && !empty($line->date_start) && !empty($line->date_end)) {
1325 if (
dol_mktime(0, 0, 0, $start[
'mon'], $start[
'mday'], $start[
'year'],
'gmt') == $first
1326 &&
dol_mktime(23, 59, 59, $end[
'mon'], $end[
'mday'], $end[
'year'],
'gmt') == $last) {
1330 $object->lines[$i]->date_start = $newFirst;
1331 $object->lines[$i]->date_end = $newLast;
1335 $object->lines[$i]->ref_ext =
'';
1339 $object->context[
'createfromclone'] =
'createfromclone';
1340 $result = $object->create($user);
1343 $this->error = $object->error;
1344 $this->errors = $object->errors;
1347 if ($object->copy_linked_contact($objFrom,
'internal') < 0) {
1349 $this->error = $object->error;
1350 $this->errors = $object->errors;
1351 } elseif ($object->socid == $objFrom->socid) {
1353 if ($object->copy_linked_contact($objFrom,
'external') < 0) {
1355 $this->error = $object->error;
1356 $this->errors = $object->errors;
1363 if (is_object($hookmanager)) {
1364 $parameters = array(
'objFrom'=>$objFrom);
1366 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $object, $action);
1374 unset($object->context[
'createfromclone']);
1378 $this->db->commit();
1381 $this->db->rollback();
1395 global $conf, $hookmanager;
1403 $num = count($object->lines);
1404 for ($i = 0; $i < $num; $i++) {
1407 $line->libelle = $object->lines[$i]->libelle;
1408 $line->label = $object->lines[$i]->label;
1409 $line->desc = $object->lines[$i]->desc;
1410 $line->subprice = $object->lines[$i]->subprice;
1411 $line->total_ht = $object->lines[$i]->total_ht;
1412 $line->total_tva = $object->lines[$i]->total_tva;
1413 $line->total_localtax1 = $object->lines[$i]->total_localtax1;
1414 $line->total_localtax2 = $object->lines[$i]->total_localtax2;
1415 $line->total_ttc = $object->lines[$i]->total_ttc;
1416 $line->vat_src_code = $object->lines[$i]->vat_src_code;
1417 $line->tva_tx = $object->lines[$i]->tva_tx;
1418 $line->localtax1_tx = $object->lines[$i]->localtax1_tx;
1419 $line->localtax2_tx = $object->lines[$i]->localtax2_tx;
1420 $line->qty = $object->lines[$i]->qty;
1421 $line->fk_remise_except = $object->lines[$i]->fk_remise_except;
1422 $line->remise_percent = $object->lines[$i]->remise_percent;
1423 $line->fk_product = $object->lines[$i]->fk_product;
1424 $line->info_bits = $object->lines[$i]->info_bits;
1425 $line->product_type = $object->lines[$i]->product_type;
1426 $line->rang = $object->lines[$i]->rang;
1427 $line->special_code = $object->lines[$i]->special_code;
1428 $line->fk_parent_line = $object->lines[$i]->fk_parent_line;
1429 $line->fk_unit = $object->lines[$i]->fk_unit;
1430 $line->date_start = $object->lines[$i]->date_start;
1431 $line->date_end = $object->lines[$i]->date_end;
1434 $line->fk_multicurrency = $object->lines[$i]->fk_multicurrency;
1435 $line->multicurrency_code = $object->lines[$i]->multicurrency_code;
1436 $line->multicurrency_subprice = $object->lines[$i]->multicurrency_subprice;
1437 $line->multicurrency_total_ht = $object->lines[$i]->multicurrency_total_ht;
1438 $line->multicurrency_total_tva = $object->lines[$i]->multicurrency_total_tva;
1439 $line->multicurrency_total_ttc = $object->lines[$i]->multicurrency_total_ttc;
1441 $line->fk_fournprice = $object->lines[$i]->fk_fournprice;
1442 $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);
1443 $line->pa_ht = $marginInfos[0];
1446 $object->lines[$i]->fetch_optionals();
1447 foreach ($object->lines[$i]->array_options as $options_key => $value) {
1448 $line->array_options[$options_key] = $value;
1451 $this->lines[$i] = $line;
1454 $this->socid = $object->socid;
1455 $this->fk_project = $object->fk_project;
1456 $this->fk_account = $object->fk_account;
1457 $this->cond_reglement_id = $object->cond_reglement_id;
1458 $this->mode_reglement_id = $object->mode_reglement_id;
1459 $this->availability_id = $object->availability_id;
1460 $this->demand_reason_id = $object->demand_reason_id;
1461 $this->delivery_date = (empty($object->delivery_date) ? $object->date_livraison : $object->delivery_date);
1462 $this->date_livraison = $object->delivery_date;
1463 $this->fk_delivery_address = $object->fk_delivery_address;
1464 $this->contact_id = $object->contact_id;
1465 $this->ref_client = $object->ref_client;
1467 if (empty($conf->global->MAIN_DISABLE_PROPAGATE_NOTES_FROM_ORIGIN)) {
1468 $this->note_private = $object->note_private;
1469 $this->note_public = $object->note_public;
1472 $this->module_source = $object->module_source;
1473 $this->pos_source = $object->pos_source;
1475 $this->origin = $object->element;
1476 $this->origin_id = $object->id;
1478 $this->fk_user_author = $user->id;
1481 $object->fetch_optionals();
1482 foreach ($object->array_options as $options_key => $value) {
1483 $this->array_options[$options_key] = $value;
1487 $this->linked_objects[$this->origin] = $this->origin_id;
1488 if (!empty($object->other_linked_objects) && is_array($object->other_linked_objects)) {
1489 $this->linked_objects = array_merge($this->linked_objects, $object->other_linked_objects);
1492 $ret = $this->
create($user);
1496 $hookmanager->initHooks(array(
'invoicedao'));
1498 $parameters = array(
'objFrom'=>$object);
1500 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $this, $action);
1526 global $conf, $hookmanager;
1534 $use_all_lines = empty($lines);
1535 $num = count($object->lines);
1536 for ($i = 0; $i < $num; $i++) {
1537 if (!$use_all_lines && !in_array($object->lines[$i]->id, $lines)) {
1543 $line->libelle = $object->lines[$i]->libelle;
1544 $line->label = $object->lines[$i]->label;
1545 $line->desc = $object->lines[$i]->desc;
1546 $line->subprice = $object->lines[$i]->subprice;
1547 $line->total_ht = $object->lines[$i]->total_ht;
1548 $line->total_tva = $object->lines[$i]->total_tva;
1549 $line->total_localtax1 = $object->lines[$i]->total_localtax1;
1550 $line->total_localtax2 = $object->lines[$i]->total_localtax2;
1551 $line->total_ttc = $object->lines[$i]->total_ttc;
1552 $line->vat_src_code = $object->lines[$i]->vat_src_code;
1553 $line->tva_tx = $object->lines[$i]->tva_tx;
1554 $line->localtax1_tx = $object->lines[$i]->localtax1_tx;
1555 $line->localtax2_tx = $object->lines[$i]->localtax2_tx;
1556 $line->qty = $object->lines[$i]->qty;
1557 $line->fk_remise_except = $object->lines[$i]->fk_remise_except;
1558 $line->remise_percent = $object->lines[$i]->remise_percent;
1559 $line->fk_product = $object->lines[$i]->fk_product;
1560 $line->info_bits = $object->lines[$i]->info_bits;
1561 $line->product_type = $object->lines[$i]->product_type;
1562 $line->rang = $object->lines[$i]->rang;
1563 $line->special_code = $object->lines[$i]->special_code;
1564 $line->fk_parent_line = $object->lines[$i]->fk_parent_line;
1565 $line->fk_unit = $object->lines[$i]->fk_unit;
1566 $line->date_start = $object->lines[$i]->date_start;
1567 $line->date_end = $object->lines[$i]->date_end;
1570 $line->fk_multicurrency = $object->lines[$i]->fk_multicurrency;
1571 $line->multicurrency_code = $object->lines[$i]->multicurrency_code;
1572 $line->multicurrency_subprice = $object->lines[$i]->multicurrency_subprice;
1573 $line->multicurrency_total_ht = $object->lines[$i]->multicurrency_total_ht;
1574 $line->multicurrency_total_tva = $object->lines[$i]->multicurrency_total_tva;
1575 $line->multicurrency_total_ttc = $object->lines[$i]->multicurrency_total_ttc;
1577 $line->fk_fournprice = $object->lines[$i]->fk_fournprice;
1578 $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);
1579 $line->pa_ht = $marginInfos[0];
1582 $object->lines[$i]->fetch_optionals();
1583 foreach ($object->lines[$i]->array_options as $options_key => $value) {
1584 $line->array_options[$options_key] = $value;
1587 $this->lines[$i] = $line;
1590 $this->socid = $object->socid;
1591 $this->fk_project = $object->fk_project;
1592 $this->fk_account = $object->fk_account;
1593 $this->cond_reglement_id = $object->cond_reglement_id;
1594 $this->mode_reglement_id = $object->mode_reglement_id;
1595 $this->availability_id = $object->availability_id;
1596 $this->demand_reason_id = $object->demand_reason_id;
1597 $this->delivery_date = (empty($object->delivery_date) ? $object->date_livraison : $object->delivery_date);
1598 $this->date_livraison = $object->delivery_date;
1599 $this->fk_delivery_address = $object->fk_delivery_address;
1600 $this->contact_id = $object->contact_id;
1601 $this->ref_client = $object->ref_client;
1603 if (empty($conf->global->MAIN_DISABLE_PROPAGATE_NOTES_FROM_ORIGIN)) {
1604 $this->note_private = $object->note_private;
1605 $this->note_public = $object->note_public;
1608 $this->module_source = $object->module_source;
1609 $this->pos_source = $object->pos_source;
1611 $this->origin = $object->element;
1612 $this->origin_id = $object->id;
1614 $this->fk_user_author = $user->id;
1617 $object->fetch_optionals();
1618 foreach ($object->array_options as $options_key => $value) {
1619 $this->array_options[$options_key] = $value;
1623 $this->linked_objects[$this->origin] = $this->origin_id;
1624 if (!empty($object->other_linked_objects) && is_array($object->other_linked_objects)) {
1625 $this->linked_objects = array_merge($this->linked_objects, $object->other_linked_objects);
1628 $ret = $this->
create($user);
1632 $hookmanager->initHooks(array(
'invoicedao'));
1634 $parameters = array(
'objFrom'=>$object);
1636 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $this, $action);
1666 global $conf, $langs, $hookmanager, $action;
1668 if (! in_array($origin->element, array(
'propal',
'commande'))) {
1669 $origin->error =
'ErrorCanOnlyAutomaticallyGenerateADepositFromProposalOrOrder';
1674 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'DateInvoice'));
1678 require_once DOL_DOCUMENT_ROOT .
'/core/lib/date.lib.php';
1680 if ($date > (
dol_get_last_hour(
dol_now(
'tzuserrel')) + (empty($conf->global->INVOICE_MAX_FUTURE_DELAY) ? 0 : $conf->global->INVOICE_MAX_FUTURE_DELAY))) {
1681 $origin->error =
'ErrorDateIsInFuture';
1685 if ($payment_terms_id <= 0) {
1686 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'PaymentConditionsShort'));
1690 $payment_conditions_deposit_percent =
getDictionaryValue(
'c_payment_term',
'deposit_percent', $origin->cond_reglement_id);
1692 if (empty($payment_conditions_deposit_percent)) {
1693 $origin->error =
'ErrorPaymentConditionsNotEligibleToDepositCreation';
1697 if (empty($origin->deposit_percent)) {
1698 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'DepositPercent'));
1702 $deposit =
new self($origin->db);
1703 $deposit->socid = $origin->socid;
1705 $deposit->fk_project = $origin->fk_project;
1706 $deposit->ref_client = $origin->ref_client;
1707 $deposit->date = $date;
1708 $deposit->mode_reglement_id = $origin->mode_reglement_id;
1709 $deposit->cond_reglement_id = $payment_terms_id;
1710 $deposit->availability_id = $origin->availability_id;
1711 $deposit->demand_reason_id = $origin->demand_reason_id;
1712 $deposit->fk_account = $origin->fk_account;
1713 $deposit->fk_incoterms = $origin->fk_incoterms;
1714 $deposit->location_incoterms = $origin->location_incoterms;
1715 $deposit->fk_multicurrency = $origin->fk_multicurrency;
1716 $deposit->multicurrency_code = $origin->multicurrency_code;
1717 $deposit->multicurrency_tx = $origin->multicurrency_tx;
1718 $deposit->module_source = $origin->module_source;
1719 $deposit->pos_source = $origin->pos_source;
1720 $deposit->model_pdf =
'crabe';
1722 $modelByTypeConfName =
'FACTURE_ADDON_PDF_' . $deposit->type;
1724 if (!empty($conf->global->$modelByTypeConfName)) {
1725 $deposit->model_pdf = $conf->global->$modelByTypeConfName;
1726 } elseif (!empty($conf->global->FACTURE_ADDON_PDF)) {
1727 $deposit->model_pdf = $conf->global->FACTURE_ADDON_PDF;
1730 if (empty($conf->global->MAIN_DISABLE_PROPAGATE_NOTES_FROM_ORIGIN)) {
1731 $deposit->note_private = $origin->note_private;
1732 $deposit->note_public = $origin->note_public;
1735 $deposit->origin = $origin->element;
1736 $deposit->origin_id = $origin->id;
1738 $origin->fetch_optionals();
1740 foreach ($origin->array_options as $extrakey => $value) {
1741 $deposit->array_options[$extrakey] = $value;
1744 $deposit->linked_objects[$deposit->origin] = $deposit->origin_id;
1746 foreach ($overrideFields as $key => $value) {
1747 $deposit->$key = $value;
1750 $deposit->context[
'createdepositfromorigin'] =
'createdepositfromorigin';
1752 $origin->db->begin();
1755 $createReturn = $deposit->create($user, $notrigger);
1757 if ($createReturn <= 0) {
1758 $origin->db->rollback();
1759 $origin->error = $deposit->error;
1760 $origin->errors = $deposit->errors;
1764 $amount_ttc_diff = 0;
1765 $amountdeposit = array();
1766 $descriptions = array();
1768 if (!empty($conf->global->MAIN_DEPOSIT_MULTI_TVA)) {
1769 $amount = $origin->total_ttc * ($origin->deposit_percent / 100);
1771 $TTotalByTva = array();
1772 foreach ($origin->lines as &$line) {
1773 if (!empty($line->special_code)) {
1776 $TTotalByTva[$line->tva_tx] += $line->total_ttc;
1777 $descriptions[$line->tva_tx] .=
'<li>' . (!empty($line->product_ref) ? $line->product_ref .
' - ' :
'');
1778 $descriptions[$line->tva_tx] .= (!empty($line->product_label) ? $line->product_label .
' - ' :
'');
1779 $descriptions[$line->tva_tx] .= $langs->trans(
'Qty') .
' : ' . $line->qty;
1780 $descriptions[$line->tva_tx] .=
' - ' . $langs->trans(
'TotalHT') .
' : ' .
price($line->total_ht) .
'</li>';
1783 foreach ($TTotalByTva as $tva => &$total) {
1784 $coef = $total / $origin->total_ttc;
1785 $am = $amount * $coef;
1786 $amount_ttc_diff += $am;
1787 $amountdeposit[$tva] += $am / (1 + $tva / 100);
1791 $lines = $origin->lines;
1792 $numlines = count($lines);
1793 for ($i = 0; $i < $numlines; $i++) {
1794 if (empty($lines[$i]->qty)) {
1797 if (!empty($lines[$i]->special_code)) {
1801 $totalamount += $lines[$i]->total_ht;
1802 $tva_tx = $lines[$i]->tva_tx;
1803 $amountdeposit[$tva_tx] += ($lines[$i]->total_ht * $origin->deposit_percent) / 100;
1804 $descriptions[$tva_tx] .=
'<li>' . (!empty($lines[$i]->product_ref) ? $lines[$i]->product_ref .
' - ' :
'');
1805 $descriptions[$tva_tx] .= (!empty($lines[$i]->product_label) ? $lines[$i]->product_label .
' - ' :
'');
1806 $descriptions[$tva_tx] .= $langs->trans(
'Qty') .
' : ' . $lines[$i]->qty;
1807 $descriptions[$tva_tx] .=
' - ' . $langs->trans(
'TotalHT') .
' : ' .
price($lines[$i]->total_ht) .
'</li>';
1810 if ($totalamount == 0) {
1811 $amountdeposit[0] = 0;
1814 $amount_ttc_diff = $amountdeposit[0];
1817 foreach ($amountdeposit as $tva => $amount) {
1818 if (empty($amount)) {
1822 $descline =
'(DEPOSIT) ('. $origin->deposit_percent .
'%) - '.$origin->ref;
1825 if (!empty($conf->global->INVOICE_DEPOSIT_VARIABLE_MODE_DETAIL_LINES_IN_DESCRIPTION) && !empty($descriptions[$tva])) {
1826 $descline .=
'<ul>' . $descriptions[$tva] .
'</ul>';
1829 $addlineResult = $deposit->addline(
1836 (empty($conf->global->INVOICE_PRODUCTID_DEPOSIT) ? 0 : $conf->global->INVOICE_PRODUCTID_DEPOSIT),
1856 if ($addlineResult < 0) {
1857 $origin->db->rollback();
1858 $origin->error = $deposit->error;
1859 $origin->errors = $deposit->errors;
1864 $diff = $deposit->total_ttc - $amount_ttc_diff;
1866 if (!empty($conf->global->MAIN_DEPOSIT_MULTI_TVA) && $diff != 0) {
1867 $deposit->fetch_lines();
1868 $subprice_diff = $deposit->lines[0]->subprice - $diff / (1 + $deposit->lines[0]->tva_tx / 100);
1870 $updatelineResult = $deposit->updateline(
1871 $deposit->lines[0]->id,
1872 $deposit->lines[0]->desc,
1874 $deposit->lines[0]->qty,
1875 $deposit->lines[0]->remise_percent,
1876 $deposit->lines[0]->date_start,
1877 $deposit->lines[0]->date_end,
1878 $deposit->lines[0]->tva_tx,
1882 $deposit->lines[0]->info_bits,
1883 $deposit->lines[0]->product_type,
1887 $deposit->lines[0]->pa_ht,
1888 $deposit->lines[0]->label,
1894 if ($updatelineResult < 0) {
1895 $origin->db->rollback();
1896 $origin->error = $deposit->error;
1897 $origin->errors = $deposit->errors;
1902 $hookmanager->initHooks(array(
'invoicedao'));
1904 $parameters = array(
'objFrom' => $origin);
1905 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $deposit, $action);
1908 $origin->db->rollback();
1909 $origin->error = $hookmanager->error;
1910 $origin->errors = $hookmanager->errors;
1914 if (!empty($autoValidateDeposit)) {
1915 $validateReturn = $deposit->validate($user,
'', 0, $notrigger);
1917 if ($validateReturn < 0) {
1918 $origin->db->rollback();
1919 $origin->error = $deposit->error;
1920 $origin->errors = $deposit->errors;
1925 unset($deposit->context[
'createdepositfromorigin']);
1927 $origin->db->commit();
1941 global $conf, $langs, $mysoc, $user;
1943 $langs->load(
'bills');
1946 $moretitle = $params[
'moretitle'] ??
'';
1947 $picto = $this->picto;
1948 if ($this->
type == self::TYPE_REPLACEMENT) {
1951 if ($this->
type == self::TYPE_CREDIT_NOTE) {
1954 if ($this->
type == self::TYPE_DEPOSIT) {
1958 if ($user->hasRight(
"facture",
"read")) {
1959 $datas[
'picto'] =
img_picto(
'', $picto).
' <u class="paddingrightonly">'.$langs->trans(
"Invoice").
'</u>';
1961 $datas[
'picto'] .=
' '.$this->getLibType(1);
1964 if (!empty($params[
'fromajaxtooltip']) && !isset($this->alreadypaid)) {
1968 if (isset($this->
statut) && isset($this->alreadypaid)) {
1969 $datas[
'picto'] .=
' '.$this->getLibStatut(5, $this->alreadypaid);
1972 $datas[
'picto'] .=
' - '.$moretitle;
1974 if (!empty($this->
ref)) {
1975 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
1977 if (!empty($this->ref_customer)) {
1978 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.$this->ref_customer;
1980 if (!empty($this->date)) {
1981 $datas[
'date'] =
'<br><b>'.$langs->trans(
'Date').
':</b> '.
dol_print_date($this->date,
'day');
1983 if (!empty($this->total_ht)) {
1984 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
1986 if (!empty($this->total_tva)) {
1987 $datas[
'amountvat'] =
'<br><b>'.$langs->trans(
'AmountVAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
1989 if (!empty($this->revenuestamp) && $this->revenuestamp != 0) {
1990 $datas[
'amountrevenustamp'] =
'<br><b>'.$langs->trans(
'RevenueStamp').
':</b> '.
price($this->revenuestamp, 0, $langs, 0, -1, -1, $conf->currency);
1992 if (!empty($this->total_localtax1) && $this->total_localtax1 != 0) {
1994 $datas[
'amountlt1'] =
'<br><b>'.$langs->transcountry(
'AmountLT1', $mysoc->country_code).
':</b> '.
price($this->total_localtax1, 0, $langs, 0, -1, -1, $conf->currency);
1996 if (!empty($this->total_localtax2) && $this->total_localtax2 != 0) {
1997 $datas[
'amountlt2'] =
'<br><b>'.$langs->transcountry(
'AmountLT2', $mysoc->country_code).
':</b> '.
price($this->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency);
1999 if (!empty($this->total_ttc)) {
2000 $datas[
'amountttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
2021 public function getNomUrl($withpicto = 0, $option =
'', $max = 0, $short = 0, $moretitle =
'', $notooltip = 0, $addlinktonotes = 0, $save_lastsearch_value = -1, $target =
'')
2023 global $langs, $conf, $user, $mysoc;
2025 if (!empty($conf->dol_no_mouse_hover)) {
2031 if ($option ==
'withdraw') {
2032 $url = DOL_URL_ROOT.
'/compta/facture/prelevement.php?facid='.$this->id;
2034 $url = DOL_URL_ROOT.
'/compta/facture/card.php?facid='.$this->id;
2037 if (!$user->hasRight(
"facture",
"read")) {
2041 if ($option !==
'nolink') {
2043 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2044 if ($save_lastsearch_value == -1 && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
2045 $add_save_lastsearch_values = 1;
2047 if ($add_save_lastsearch_values) {
2048 $url .=
'&save_lastsearch_values=1';
2056 $picto = $this->picto;
2057 if ($this->
type == self::TYPE_REPLACEMENT) {
2060 if ($this->
type == self::TYPE_CREDIT_NOTE) {
2063 if ($this->
type == self::TYPE_DEPOSIT) {
2068 'objecttype' => $this->element,
2069 'moretitle' => $moretitle,
2070 'option' => $option,
2072 $classfortooltip =
'classfortooltip';
2075 $classfortooltip =
'classforajaxtooltip';
2076 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
2082 $linkclose = ($target ?
' target="'.$target.
'"' :
'');
2083 if (empty($notooltip) && $user->hasRight(
"facture",
"read")) {
2084 if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2085 $label = $langs->trans(
"Invoice");
2086 $linkclose .=
' alt="'.dol_escape_htmltag($label, 1).
'"';
2088 $linkclose .= ($label ?
' title="'.dol_escape_htmltag($label, 1).
'"' :
' title="tocomplete"');
2089 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
2092 $linkstart =
'<a href="'.$url.
'"';
2093 $linkstart .= $linkclose.
'>';
2096 if ($option ==
'nolink') {
2101 $result .= $linkstart;
2103 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), ($notooltip ? (($withpicto != 2) ?
'class="paddingright"' :
'') :
'class="'.(($withpicto != 2) ?
'paddingright ' :
'').
'"'), 0, 0, $notooltip ? 0 : 1);
2105 if ($withpicto != 2) {
2106 $result .= ($max ?
dol_trunc($this->
ref, $max) : $this->ref);
2108 $result .= $linkend;
2110 if ($addlinktonotes) {
2111 $txttoshow = ($user->socid > 0 ? $this->note_public : $this->note_private);
2114 $notetoshow = $langs->trans(
"ViewPrivateNote").
':<br>'.$txttoshow;
2115 $result .=
' <span class="note inline-block">';
2116 $result .=
'<a href="'.DOL_URL_ROOT.
'/compta/facture/note.php?id='.$this->
id.
'" class="classfortooltip" title="'.
dol_escape_htmltag($notetoshow, 1, 1).
'">';
2121 $result .=
'</span>';
2125 global $action, $hookmanager;
2126 $hookmanager->initHooks(array(
'invoicedao'));
2127 $parameters = array(
'id'=>$this->
id,
'getnomurl' => &$result,
'notooltip' => $notooltip,
'addlinktonotes' => $addlinktonotes,
'save_lastsearch_value'=> $save_lastsearch_value,
'target' => $target);
2128 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
2130 $result = $hookmanager->resPrint;
2132 $result .= $hookmanager->resPrint;
2148 public function fetch($rowid, $ref =
'', $ref_ext =
'', $notused =
'', $fetch_situation =
false)
2150 if (empty($rowid) && empty($ref) && empty($ref_ext)) {
2154 $sql =
'SELECT f.rowid, f.entity, f.ref, f.ref_client, f.ref_ext, f.type, f.fk_soc';
2155 $sql .=
', f.total_tva, f.localtax1, f.localtax2, f.total_ht, f.total_ttc, f.revenuestamp';
2156 $sql .=
', f.remise_percent, f.remise_absolue, f.remise';
2157 $sql .=
', f.datef as df, f.date_pointoftax';
2158 $sql .=
', f.date_lim_reglement as dlr';
2159 $sql .=
', f.datec as datec';
2160 $sql .=
', f.date_valid as datev';
2161 $sql .=
', f.tms as datem';
2162 $sql .=
', f.note_private, f.note_public, f.fk_statut, 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';
2163 $sql .=
', f.fk_facture_source, f.fk_fac_rec_source';
2164 $sql .=
', f.fk_mode_reglement, f.fk_cond_reglement, f.fk_projet as fk_project, f.extraparams';
2165 $sql .=
', f.situation_cycle_ref, f.situation_counter, f.situation_final';
2166 $sql .=
', f.fk_account';
2167 $sql .=
", f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc";
2168 $sql .=
', p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
2169 $sql .=
', c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_doc';
2170 $sql .=
', f.fk_incoterms, f.location_incoterms';
2171 $sql .=
', f.module_source, f.pos_source';
2172 $sql .=
", i.libelle as label_incoterms";
2173 $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";
2174 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facture as f';
2175 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_payment_term as c ON f.fk_cond_reglement = c.rowid';
2176 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_paiement as p ON f.fk_mode_reglement = p.id';
2177 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON f.fk_incoterms = i.rowid';
2180 $sql .=
" WHERE f.rowid = ".((int) $rowid);
2182 $sql .=
' WHERE f.entity IN ('.getEntity(
'invoice').
')';
2184 $sql .=
" AND f.ref = '".$this->db->escape($ref).
"'";
2187 $sql .=
" AND f.ref_ext = '".$this->db->escape($ref_ext).
"'";
2191 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
2192 $resql = $this->db->query($sql);
2194 if ($this->db->num_rows($resql)) {
2195 $obj = $this->db->fetch_object($resql);
2197 $this->
id = $obj->rowid;
2198 $this->entity = $obj->entity;
2200 $this->
ref = $obj->ref;
2201 $this->ref_client = $obj->ref_client;
2202 $this->ref_customer = $obj->ref_client;
2203 $this->ref_ext = $obj->ref_ext;
2204 $this->
type = $obj->type;
2205 $this->date = $this->db->jdate($obj->df);
2206 $this->date_pointoftax = $this->db->jdate($obj->date_pointoftax);
2207 $this->date_creation = $this->db->jdate($obj->datec);
2208 $this->date_validation = $this->db->jdate($obj->datev);
2209 $this->date_modification = $this->db->jdate($obj->datem);
2210 $this->datem = $this->db->jdate($obj->datem);
2211 $this->remise_percent = $obj->remise_percent;
2212 $this->remise_absolue = $obj->remise_absolue;
2213 $this->total_ht = $obj->total_ht;
2214 $this->total_tva = $obj->total_tva;
2215 $this->total_localtax1 = $obj->localtax1;
2216 $this->total_localtax2 = $obj->localtax2;
2217 $this->total_ttc = $obj->total_ttc;
2218 $this->revenuestamp = $obj->revenuestamp;
2219 $this->paye = $obj->paye;
2220 $this->close_code = $obj->close_code;
2221 $this->close_note = $obj->close_note;
2223 $this->socid = $obj->fk_soc;
2224 $this->thirdparty =
null;
2226 $this->fk_project = $obj->fk_project;
2227 $this->project =
null;
2229 $this->
statut = $obj->fk_statut;
2230 $this->status = $obj->fk_statut;
2232 $this->date_lim_reglement = $this->db->jdate($obj->dlr);
2233 $this->mode_reglement_id = $obj->fk_mode_reglement;
2234 $this->mode_reglement_code = $obj->mode_reglement_code;
2235 $this->mode_reglement = $obj->mode_reglement_libelle;
2236 $this->cond_reglement_id = $obj->fk_cond_reglement;
2237 $this->cond_reglement_code = $obj->cond_reglement_code;
2238 $this->cond_reglement = $obj->cond_reglement_libelle;
2239 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
2240 $this->fk_account = ($obj->fk_account > 0) ? $obj->fk_account :
null;
2241 $this->fk_facture_source = $obj->fk_facture_source;
2242 $this->fk_fac_rec_source = $obj->fk_fac_rec_source;
2243 $this->note = $obj->note_private;
2244 $this->note_private = $obj->note_private;
2245 $this->note_public = $obj->note_public;
2246 $this->user_author = $obj->fk_user_author;
2247 $this->user_valid = $obj->fk_user_valid;
2248 $this->user_modification = $obj->fk_user_modif;
2249 $this->fk_user_author = $obj->fk_user_author;
2250 $this->fk_user_valid = $obj->fk_user_valid;
2251 $this->fk_user_modif = $obj->fk_user_modif;
2252 $this->model_pdf = $obj->model_pdf;
2253 $this->modelpdf = $obj->model_pdf;
2254 $this->last_main_doc = $obj->last_main_doc;
2255 $this->situation_cycle_ref = $obj->situation_cycle_ref;
2256 $this->situation_counter = $obj->situation_counter;
2257 $this->situation_final = $obj->situation_final;
2258 $this->retained_warranty = $obj->retained_warranty;
2259 $this->retained_warranty_date_limit = $this->db->jdate($obj->retained_warranty_date_limit);
2260 $this->retained_warranty_fk_cond_reglement = $obj->retained_warranty_fk_cond_reglement;
2262 $this->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
2265 $this->fk_incoterms = $obj->fk_incoterms;
2266 $this->location_incoterms = $obj->location_incoterms;
2267 $this->label_incoterms = $obj->label_incoterms;
2269 $this->module_source = $obj->module_source;
2270 $this->pos_source = $obj->pos_source;
2273 $this->fk_multicurrency = $obj->fk_multicurrency;
2274 $this->multicurrency_code = $obj->multicurrency_code;
2275 $this->multicurrency_tx = $obj->multicurrency_tx;
2276 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
2277 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
2278 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
2280 if (($this->
type == self::TYPE_SITUATION || ($this->
type == self::TYPE_CREDIT_NOTE && $this->situation_cycle_ref > 0)) && $fetch_situation) {
2284 if ($this->status == self::STATUS_DRAFT) {
2285 $this->brouillon = 1;
2293 $this->lines = array();
2297 $this->error = $this->db->error();
2301 $this->db->free($resql);
2305 $this->error =
'Invoice with id='.$rowid.
' or ref='.$ref.
' or ref_ext='.$ref_ext.
' not found';
2307 dol_syslog(__METHOD__.$this->error, LOG_WARNING);
2311 $this->error = $this->db->lasterror();
2326 public function fetch_lines($only_product = 0, $loadalsotranslation = 0)
2329 global $langs, $conf;
2331 $this->lines = array();
2333 $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,';
2334 $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,';
2335 $sql .=
' l.situation_percent, l.fk_prev_id,';
2336 $sql .=
' l.rang, l.special_code,';
2337 $sql .=
' l.date_start as date_start, l.date_end as date_end,';
2338 $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,';
2339 $sql .=
' l.fk_unit,';
2340 $sql .=
' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
2341 $sql .=
' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc';
2342 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facturedet as l';
2343 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON l.fk_product = p.rowid';
2344 $sql .=
' WHERE l.fk_facture = '.((int) $this->
id);
2345 $sql .=
' ORDER BY l.rang, l.rowid';
2347 dol_syslog(get_class($this).
'::fetch_lines', LOG_DEBUG);
2348 $result = $this->db->query($sql);
2350 $num = $this->db->num_rows($result);
2353 $objp = $this->db->fetch_object($result);
2356 $line->id = $objp->rowid;
2357 $line->rowid = $objp->rowid;
2358 $line->fk_facture = $objp->fk_facture;
2359 $line->label = $objp->custom_label;
2360 $line->desc = $objp->description;
2361 $line->description = $objp->description;
2362 $line->product_type = $objp->product_type;
2363 $line->ref = $objp->product_ref;
2364 $line->product_ref = $objp->product_ref;
2365 $line->libelle = $objp->product_label;
2366 $line->product_label = $objp->product_label;
2367 $line->product_desc = $objp->product_desc;
2368 $line->fk_product_type = $objp->fk_product_type;
2369 $line->qty = $objp->qty;
2370 $line->subprice = $objp->subprice;
2371 $line->ref_ext = $objp->ref_ext;
2373 $line->vat_src_code = $objp->vat_src_code;
2374 $line->tva_tx = $objp->tva_tx;
2375 $line->localtax1_tx = $objp->localtax1_tx;
2376 $line->localtax2_tx = $objp->localtax2_tx;
2377 $line->localtax1_type = $objp->localtax1_type;
2378 $line->localtax2_type = $objp->localtax2_type;
2379 $line->remise_percent = $objp->remise_percent;
2380 $line->fk_remise_except = $objp->fk_remise_except;
2381 $line->fk_product = $objp->fk_product;
2382 $line->date_start = $this->db->jdate($objp->date_start);
2383 $line->date_end = $this->db->jdate($objp->date_end);
2384 $line->info_bits = $objp->info_bits;
2385 $line->total_ht = $objp->total_ht;
2386 $line->total_tva = $objp->total_tva;
2387 $line->total_localtax1 = $objp->total_localtax1;
2388 $line->total_localtax2 = $objp->total_localtax2;
2389 $line->total_ttc = $objp->total_ttc;
2390 $line->code_ventilation = $objp->fk_code_ventilation;
2391 $line->fk_fournprice = $objp->fk_fournprice;
2392 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
2393 $line->pa_ht = $marginInfos[0];
2394 $line->marge_tx = $marginInfos[1];
2395 $line->marque_tx = $marginInfos[2];
2396 $line->rang = $objp->rang;
2397 $line->special_code = $objp->special_code;
2398 $line->fk_parent_line = $objp->fk_parent_line;
2399 $line->situation_percent = $objp->situation_percent;
2400 $line->fk_prev_id = $objp->fk_prev_id;
2401 $line->fk_unit = $objp->fk_unit;
2404 $line->fk_accounting_account = $objp->fk_code_ventilation;
2407 $line->fk_multicurrency = $objp->fk_multicurrency;
2408 $line->multicurrency_code = $objp->multicurrency_code;
2409 $line->multicurrency_subprice = $objp->multicurrency_subprice;
2410 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
2411 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
2412 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
2414 $line->fetch_optionals();
2417 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
2418 $tmpproduct =
new Product($this->db);
2419 $tmpproduct->fetch($objp->fk_product);
2420 $tmpproduct->getMultiLangs();
2422 $line->multilangs = $tmpproduct->multilangs;
2425 $this->lines[$i] = $line;
2429 $this->db->free($result);
2432 $this->error = $this->db->error();
2447 $this->tab_previous_situation_invoice = array();
2448 $this->tab_next_situation_invoice = array();
2450 $sql =
'SELECT rowid, type, situation_cycle_ref, situation_counter FROM '.MAIN_DB_PREFIX.
'facture';
2451 $sql .=
" WHERE rowid <> ".((int) $this->
id);
2452 $sql .=
' AND entity = '.((int) $this->entity);
2453 $sql .=
' AND situation_cycle_ref = '.(int) $this->situation_cycle_ref;
2454 $sql .=
' ORDER BY situation_counter ASC';
2456 dol_syslog(get_class($this).
'::fetchPreviousNextSituationInvoice ', LOG_DEBUG);
2457 $result = $this->db->query($sql);
2458 if ($result && $this->db->num_rows($result) > 0) {
2459 while ($objp = $this->db->fetch_object($result)) {
2460 $invoice =
new Facture($this->db);
2461 if ($invoice->fetch($objp->rowid) > 0) {
2462 if ($objp->situation_counter < $this->situation_counter
2463 || ($objp->situation_counter == $this->situation_counter && $objp->rowid < $this->id)
2465 $this->tab_previous_situation_invoice[] = $invoice;
2467 $this->tab_next_situation_invoice[] = $invoice;
2486 if (empty($this->
type)) {
2489 if (isset($this->
ref)) {
2490 $this->
ref = trim($this->
ref);
2492 if (isset($this->ref_ext)) {
2493 $this->ref_ext = trim($this->ref_ext);
2495 if (isset($this->ref_client)) {
2496 $this->ref_client = trim($this->ref_client);
2498 if (isset($this->increment)) {
2499 $this->increment = trim($this->increment);
2501 if (isset($this->close_code)) {
2502 $this->close_code = trim($this->close_code);
2504 if (isset($this->close_note)) {
2505 $this->close_note = trim($this->close_note);
2507 if (isset($this->note) || isset($this->note_private)) {
2508 $this->note = (isset($this->note) ? trim($this->note) : trim($this->note_private));
2510 if (isset($this->note) || isset($this->note_private)) {
2511 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note));
2513 if (isset($this->note_public)) {
2514 $this->note_public = trim($this->note_public);
2516 if (isset($this->model_pdf)) {
2517 $this->model_pdf = trim($this->model_pdf);
2519 if (isset($this->import_key)) {
2520 $this->import_key = trim($this->import_key);
2522 if (isset($this->retained_warranty)) {
2523 $this->retained_warranty = floatval($this->retained_warranty);
2531 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facture SET";
2532 $sql .=
" ref=".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
2533 $sql .=
" ref_ext=".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
2534 $sql .=
" type=".(isset($this->
type) ? $this->db->escape($this->
type) :
"null").
",";
2535 $sql .=
" ref_client=".(isset($this->ref_client) ?
"'".$this->db->escape($this->ref_client).
"'" :
"null").
",";
2536 $sql .=
" increment=".(isset($this->increment) ?
"'".$this->db->escape($this->increment).
"'" :
"null").
",";
2537 $sql .=
" fk_soc=".(isset($this->socid) ? $this->db->escape($this->socid) :
"null").
",";
2538 $sql .=
" datec=".(strval($this->date_creation) !=
'' ?
"'".$this->db->idate($this->date_creation).
"'" :
'null').
",";
2539 $sql .=
" datef=".(strval($this->date) !=
'' ?
"'".$this->db->idate($this->date).
"'" :
'null').
",";
2540 $sql .=
" date_pointoftax=".(strval($this->date_pointoftax) !=
'' ?
"'".$this->db->idate($this->date_pointoftax).
"'" :
'null').
",";
2541 $sql .=
" date_valid=".(strval($this->date_validation) !=
'' ?
"'".$this->db->idate($this->date_validation).
"'" :
'null').
",";
2542 $sql .=
" paye=".(isset($this->paye) ? $this->db->escape($this->paye) : 0).
",";
2543 $sql .=
" remise_percent=".(isset($this->remise_percent) ? $this->db->escape($this->remise_percent) :
"null").
",";
2544 $sql .=
" remise_absolue=".(isset($this->remise_absolue) ? $this->db->escape($this->remise_absolue) :
"null").
",";
2545 $sql .=
" close_code=".(isset($this->close_code) ?
"'".$this->db->escape($this->close_code).
"'" :
"null").
",";
2546 $sql .=
" close_note=".(isset($this->close_note) ?
"'".$this->db->escape($this->close_note).
"'" :
"null").
",";
2547 $sql .=
" total_tva=".(isset($this->total_tva) ? $this->total_tva :
"null").
",";
2548 $sql .=
" localtax1=".(isset($this->total_localtax1) ? $this->total_localtax1 :
"null").
",";
2549 $sql .=
" localtax2=".(isset($this->total_localtax2) ? $this->total_localtax2 :
"null").
",";
2550 $sql .=
" total_ht=".(isset($this->total_ht) ? $this->total_ht :
"null").
",";
2551 $sql .=
" total_ttc=".(isset($this->total_ttc) ? $this->total_ttc :
"null").
",";
2552 $sql .=
" revenuestamp=".((isset($this->revenuestamp) && $this->revenuestamp !=
'') ? $this->db->escape($this->revenuestamp) :
"null").
",";
2553 $sql .=
" fk_statut=".(isset($this->
statut) ? $this->db->escape($this->
statut) :
"null").
",";
2554 $sql .=
" fk_user_author=".(isset($this->user_author) ? $this->db->escape($this->user_author) :
"null").
",";
2555 $sql .=
" fk_user_valid=".(isset($this->fk_user_valid) ? $this->db->escape($this->fk_user_valid) :
"null").
",";
2556 $sql .=
" fk_facture_source=".(isset($this->fk_facture_source) ? $this->db->escape($this->fk_facture_source) :
"null").
",";
2557 $sql .=
" fk_projet=".(isset($this->fk_project) ? $this->db->escape($this->fk_project) :
"null").
",";
2558 $sql .=
" fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->db->escape($this->cond_reglement_id) :
"null").
",";
2559 $sql .=
" fk_mode_reglement=".(isset($this->mode_reglement_id) ? $this->db->escape($this->mode_reglement_id) :
"null").
",";
2560 $sql .=
" date_lim_reglement=".(strval($this->date_lim_reglement) !=
'' ?
"'".$this->db->idate($this->date_lim_reglement).
"'" :
'null').
",";
2561 $sql .=
" note_private=".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
2562 $sql .=
" note_public=".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
2563 $sql .=
" model_pdf=".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
2564 $sql .=
" import_key=".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null").
",";
2565 $sql .=
" situation_cycle_ref=".(empty($this->situation_cycle_ref) ?
"null" : $this->db->escape($this->situation_cycle_ref)).
",";
2566 $sql .=
" situation_counter=".(empty($this->situation_counter) ?
"null" : $this->db->escape($this->situation_counter)).
",";
2567 $sql .=
" situation_final=".(empty($this->situation_final) ?
"0" : $this->db->escape($this->situation_final)).
",";
2568 $sql .=
" retained_warranty=".(empty($this->retained_warranty) ?
"0" : $this->db->escape($this->retained_warranty)).
",";
2569 $sql .=
" retained_warranty_date_limit=".(strval($this->retained_warranty_date_limit) !=
'' ?
"'".$this->db->idate($this->retained_warranty_date_limit).
"'" :
'null').
",";
2570 $sql .=
" retained_warranty_fk_cond_reglement=".(isset($this->retained_warranty_fk_cond_reglement) ?intval($this->retained_warranty_fk_cond_reglement) :
"null");
2571 $sql .=
" WHERE rowid=".((int) $this->
id);
2575 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
2576 $resql = $this->db->query($sql);
2579 $this->errors[] =
"Error ".$this->db->lasterror();
2589 if (!$error && !$notrigger) {
2600 foreach ($this->errors as $errmsg) {
2601 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
2602 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2604 $this->db->rollback();
2607 $this->db->commit();
2623 global $conf, $langs;
2625 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
2626 include_once DOL_DOCUMENT_ROOT.
'/core/class/discount.class.php';
2631 $result = $remise->fetch($idremise);
2634 if ($remise->fk_facture) {
2635 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed");
2636 $this->db->rollback();
2641 $facligne->fk_facture = $this->id;
2642 $facligne->fk_remise_except = $remise->id;
2643 $facligne->desc = $remise->description;
2644 $facligne->vat_src_code = $remise->vat_src_code;
2645 $facligne->tva_tx = $remise->tva_tx;
2646 $facligne->subprice = -$remise->amount_ht;
2647 $facligne->fk_product = 0;
2649 $facligne->remise_percent = 0;
2650 $facligne->rang = -1;
2651 $facligne->info_bits = 2;
2653 if (!empty($conf->global->MAIN_ADD_LINE_AT_POSITION)) {
2654 $facligne->rang = 1;
2655 $linecount = count($this->lines);
2656 for ($ii = 1; $ii <= $linecount; $ii++) {
2662 if ($remise->fk_facture_source > 0) {
2663 $srcinvoice =
new Facture($this->db);
2664 $srcinvoice->fetch($remise->fk_facture_source);
2665 include_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmargin.class.php';
2667 $arraytmp = $formmargin->getMarginInfosArray($srcinvoice,
false);
2668 $facligne->pa_ht = $arraytmp[
'pa_total'];
2671 $facligne->total_ht = -$remise->amount_ht;
2672 $facligne->total_tva = -$remise->amount_tva;
2673 $facligne->total_ttc = -$remise->amount_ttc;
2675 $facligne->multicurrency_subprice = -$remise->multicurrency_subprice;
2676 $facligne->multicurrency_total_ht = -$remise->multicurrency_amount_ht;
2677 $facligne->multicurrency_total_tva = -$remise->multicurrency_amount_tva;
2678 $facligne->multicurrency_total_ttc = -$remise->multicurrency_amount_ttc;
2680 $lineid = $facligne->insert();
2685 $result = $remise->link_to_invoice($lineid, 0);
2687 $this->error = $remise->error;
2688 $this->db->rollback();
2692 $this->db->commit();
2695 $this->error = $facligne->error;
2696 $this->db->rollback();
2700 $this->error = $facligne->error;
2701 $this->db->rollback();
2705 $this->db->rollback();
2727 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
2728 if (empty($ref_client)) {
2729 $sql .=
' SET ref_client = NULL';
2731 $sql .=
' SET ref_client = \''.$this->db->escape($ref_client).
'\'';
2733 $sql .=
" WHERE rowid = ".((int) $this->
id);
2735 dol_syslog(__METHOD__.
' this->id='.$this->id.
', ref_client='.$ref_client, LOG_DEBUG);
2736 $resql = $this->db->query($sql);
2738 $this->errors[] = $this->db->error();
2743 $this->ref_client = $ref_client;
2746 if (!$notrigger && empty($error)) {
2756 $this->ref_client = $ref_client;
2758 $this->db->commit();
2761 foreach ($this->errors as $errmsg) {
2762 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2763 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2765 $this->db->rollback();
2778 public function delete($user, $notrigger = 0, $idwarehouse = -1)
2780 global $langs, $conf;
2781 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
2785 dol_syslog(get_class($this).
"::delete rowid=".$rowid.
", ref=".$this->ref.
", thirdparty=".(empty($this->thirdparty) ?
'' : $this->thirdparty->name), LOG_DEBUG);
2798 if (!$error && !$notrigger) {
2812 dol_syslog(get_class($this).
"::delete error deleteExtraFields ".$this->error, LOG_ERR);
2826 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'societe_remise_except';
2827 $sql .=
' WHERE fk_facture_source = '.((int) $rowid);
2828 $sql .=
' AND fk_facture_line IS NULL';
2829 $resql = $this->db->query($sql);
2833 $list_rowid_det = array();
2834 foreach ($this->lines as $key => $invoiceline) {
2835 $list_rowid_det[] = $invoiceline->id;
2839 if (count($list_rowid_det)) {
2840 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
2841 $sql .=
' SET fk_facture = NULL, fk_facture_line = NULL';
2842 $sql .=
' WHERE fk_facture_line IN ('.$this->db->sanitize(join(
',', $list_rowid_det)).
')';
2844 if (!$this->db->query($sql)) {
2845 $this->error = $this->db->error().
" sql=".$sql;
2846 $this->errors[] = $this->error;
2847 $this->db->rollback();
2854 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'eventorganization_conferenceorboothattendee';
2855 $sql .=
' SET fk_invoice = NULL';
2856 $sql .=
' WHERE fk_invoice = '.((int) $rowid);
2858 if (!$this->db->query($sql)) {
2859 $this->error = $this->db->error().
" sql=".$sql;
2860 $this->errors[] = $this->error;
2861 $this->db->rollback();
2865 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'element_time';
2866 $sql .=
' SET invoice_id = NULL, invoice_line_id = NULL';
2867 $sql .=
' WHERE invoice_id = '.((int) $rowid);
2869 if (!$this->db->query($sql)) {
2870 $this->error = $this->db->error().
" sql=".$sql;
2871 $this->errors[] = $this->error;
2872 $this->db->rollback();
2877 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') && !empty($conf->global->STOCK_CALCULATE_ON_BILL) && $idwarehouse != -1) {
2878 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
2879 $langs->load(
"agenda");
2881 $num = count($this->lines);
2882 for ($i = 0; $i < $num; $i++) {
2883 if ($this->lines[$i]->fk_product > 0) {
2885 $mouvP->origin = &$this;
2886 $mouvP->setOrigin($this->element, $this->
id);
2888 if ($this->
type == self::TYPE_CREDIT_NOTE) {
2889 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceDeleteDolibarr", $this->ref));
2891 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceDeleteDolibarr", $this->ref));
2898 $main = MAIN_DB_PREFIX.
'facturedet';
2899 $ef = $main.
"_extrafields";
2900 $sqlef =
"DELETE FROM ".$ef.
" WHERE fk_object IN (SELECT rowid FROM ".$main.
" WHERE fk_facture = ".((int) $rowid).
")";
2902 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'facturedet WHERE fk_facture = '.((int) $rowid);
2905 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'facture WHERE rowid = '.((int) $rowid);
2907 $resql = $this->db->query($sql);
2914 if ($conf->facture->dir_output && !empty($this->
ref)) {
2915 $dir = $conf->facture->dir_output.
"/".$ref;
2916 $file = $conf->facture->dir_output.
"/".$ref.
"/".$ref.
".pdf";
2917 if (file_exists($file)) {
2921 $langs->load(
"errors");
2922 $this->error = $langs->trans(
"ErrorFailToDeleteFile", $file);
2923 $this->errors[] = $this->error;
2924 $this->db->rollback();
2928 if (file_exists($dir)) {
2930 $langs->load(
"errors");
2931 $this->error = $langs->trans(
"ErrorFailToDeleteDir", $dir);
2932 $this->errors[] = $this->error;
2933 $this->db->rollback();
2939 $this->db->commit();
2942 $this->error = $this->db->lasterror().
" sql=".$sql;
2943 $this->errors[] = $this->error;
2944 $this->db->rollback();
2948 $this->error = $this->db->lasterror().
" sql=".$sql;
2949 $this->errors[] = $this->error;
2950 $this->db->rollback();
2954 $this->db->rollback();
2971 public function set_paid($user, $close_code =
'', $close_note =
'')
2974 dol_syslog(get_class($this).
"::set_paid is deprecated, use setPaid instead", LOG_NOTICE);
2975 return $this->
setPaid($user, $close_code, $close_note);
2987 public function setPaid($user, $close_code =
'', $close_note =
'')
2991 if ($this->paye != 1) {
2996 dol_syslog(get_class($this).
"::setPaid rowid=".((
int) $this->
id), LOG_DEBUG);
2998 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET';
2999 $sql .=
' fk_statut='.self::STATUS_CLOSED;
3004 $sql .=
", close_code='".$this->db->escape($close_code).
"'";
3007 $sql .=
", close_note='".$this->db->escape($close_note).
"'";
3009 $sql .=
', fk_user_closing = '.((int) $user->id);
3010 $sql .=
", date_closing = '".$this->db->idate($now).
"'";
3011 $sql .=
" WHERE rowid = ".((int) $this->
id);
3013 $resql = $this->db->query($sql);
3023 $this->error = $this->db->lasterror();
3027 $this->db->commit();
3030 $this->db->rollback();
3053 dol_syslog(get_class($this).
"::set_unpaid is deprecated, use setUnpaid instead", LOG_NOTICE);
3071 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
3072 $sql .=
' SET paye=0, fk_statut='.self::STATUS_VALIDATED.
', close_code=null, close_note=null,';
3073 $sql .=
' date_closing=null,';
3074 $sql .=
' fk_user_closing=null';
3075 $sql .=
" WHERE rowid = ".((int) $this->
id);
3077 dol_syslog(get_class($this).
"::setUnpaid", LOG_DEBUG);
3078 $resql = $this->db->query($sql);
3088 $this->error = $this->db->error();
3093 $this->db->commit();
3096 $this->db->rollback();
3118 dol_syslog(get_class($this).
"::set_canceled is deprecated, use setCanceled instead", LOG_NOTICE);
3119 return $this->
setCanceled($user, $close_code, $close_note);
3132 public function setCanceled($user, $close_code =
'', $close_note =
'')
3134 dol_syslog(get_class($this).
"::setCanceled rowid=".((
int) $this->
id), LOG_DEBUG);
3138 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET';
3139 $sql .=
' fk_statut='.self::STATUS_ABANDONED;
3141 $sql .=
", close_code='".$this->db->escape($close_code).
"'";
3144 $sql .=
", close_note='".$this->db->escape($close_note).
"'";
3146 $sql .=
" WHERE rowid = ".((int) $this->
id);
3148 $resql = $this->db->query($sql);
3152 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
3153 $sql .=
' SET fk_facture = NULL';
3154 $sql .=
' WHERE fk_facture = '.((int) $this->
id);
3156 $resql = $this->db->query($sql);
3161 $this->db->rollback();
3166 $this->db->commit();
3169 $this->error = $this->db->error().
" sql=".$sql;
3170 $this->db->rollback();
3174 $this->error = $this->db->error().
" sql=".$sql;
3175 $this->db->rollback();
3191 public function validate($user, $force_number =
'', $idwarehouse = 0, $notrigger = 0, $batch_rule = 0)
3193 global $conf, $langs, $mysoc;
3194 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
3196 $productStatic =
null;
3197 $warehouseStatic =
null;
3198 if ($batch_rule > 0) {
3199 require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
3200 require_once DOL_DOCUMENT_ROOT.
'/product/class/productbatch.class.php';
3201 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
3202 $productStatic =
new Product($this->db);
3203 $warehouseStatic =
new Entrepot($this->db);
3210 dol_syslog(get_class($this).
'::validate user='.$user->id.
', force_number='.$force_number.
', idwarehouse='.$idwarehouse);
3217 if ($this->
statut != self::STATUS_DRAFT) {
3218 dol_syslog(get_class($this).
"::validate status is not draft. operation canceled.", LOG_WARNING);
3221 if (count($this->lines) <= 0) {
3222 $langs->load(
"errors");
3223 $this->error = $langs->trans(
"ErrorObjectMustHaveLinesToBeValidated", $this->
ref);
3226 if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->facture->creer))
3227 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->facture->invoice_advance->validate))) {
3228 $this->error =
'Permission denied';
3229 dol_syslog(get_class($this).
"::validate ".$this->error.
' MAIN_USE_ADVANCED_PERMS='.$conf->global->MAIN_USE_ADVANCED_PERMS, LOG_ERR);
3232 if ((preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) &&
3233 !empty($conf->global->FAC_FORCE_DATE_VALIDATION)
3238 if (!empty($conf->global-> INVOICE_CHECK_POSTERIOR_DATE)) {
3240 if (!$last_of_type[0]) {
3241 $this->error = $langs->transnoentities(
"ErrorInvoiceIsNotLastOfSameType", $this->
ref,
dol_print_date($this->date,
'day'),
dol_print_date($last_of_type[1],
'day'));
3247 if (!empty($this->thirdparty) && is_object($this->thirdparty)) {
3248 $array_to_check = array(
'IDPROF1',
'IDPROF2',
'IDPROF3',
'IDPROF4',
'IDPROF5',
'IDPROF6',
'EMAIL',
'ACCOUNTANCY_CODE_CUSTOMER');
3249 foreach ($array_to_check as $key) {
3250 $keymin = strtolower($key);
3251 if (!property_exists($this->thirdparty, $keymin)) {
3254 $vallabel = $this->thirdparty->$keymin;
3256 $i = (int) preg_replace(
'/[^0-9]/',
'', $key);
3258 if ($this->thirdparty->isACompany()) {
3260 if ($mysoc->country_id > 0 && $this->thirdparty->country_id == $mysoc->country_id) {
3261 $idprof_mandatory =
'SOCIETE_'.$key.
'_INVOICE_MANDATORY';
3262 if (!$vallabel && !empty($conf->global->$idprof_mandatory)) {
3263 $langs->load(
"errors");
3264 $this->error = $langs->trans(
'ErrorProdIdIsMandatory', $langs->transcountry(
'ProfId'.$i, $this->thirdparty->country_code)).
' ('.$langs->trans(
"ForbiddenBySetupRules").
') ['.$langs->trans(
'Company').
' : '.$this->thirdparty->name.
']';
3265 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3271 if ($key ==
'EMAIL') {
3273 if (!empty($conf->global->SOCIETE_EMAIL_INVOICE_MANDATORY) && !isValidEMail($this->thirdparty->email)) {
3274 $langs->load(
"errors");
3275 $this->error = $langs->trans(
"ErrorBadEMail", $this->thirdparty->email).
' ('.$langs->trans(
"ForbiddenBySetupRules").
') ['.$langs->trans(
'Company').
' : '.$this->thirdparty->name.
']';
3276 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3280 if ($key ==
'ACCOUNTANCY_CODE_CUSTOMER') {
3282 if (!empty($conf->global->SOCIETE_ACCOUNTANCY_CODE_CUSTOMER_INVOICE_MANDATORY) && empty($this->thirdparty->code_compta)) {
3283 $langs->load(
"errors");
3284 $this->error = $langs->trans(
"ErrorAccountancyCodeCustomerIsMandatory", $this->thirdparty->name).
' ('.$langs->trans(
"ForbiddenBySetupRules").
')';
3285 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3294 $array_to_check = array(
'REF_CLIENT'=>
'RefCustomer');
3295 foreach ($array_to_check as $key => $val) {
3296 $keymin = strtolower($key);
3297 $vallabel = $this->$keymin;
3300 $keymandatory =
'INVOICE_'.$key.
'_MANDATORY_FOR_VALIDATION';
3301 if (!$vallabel && !empty($conf->global->$keymandatory)) {
3302 $langs->load(
"errors");
3304 setEventMessages($langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv($val)),
null,
'errors');
3311 if ($this->
type == self::TYPE_REPLACEMENT) {
3313 if ($this->fk_facture_source <= 0) {
3314 $this->error = $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"InvoiceReplacement"));
3315 $this->db->rollback();
3320 $facreplaced =
new Facture($this->db);
3321 $result = $facreplaced->fetch($this->fk_facture_source);
3323 $this->error = $langs->trans(
"ErrorBadInvoice");
3324 $this->db->rollback();
3329 $idreplacement = $facreplaced->getIdReplacingInvoice(
'validated');
3330 if ($idreplacement && $idreplacement != $this->
id) {
3331 $facreplacement =
new Facture($this->db);
3332 $facreplacement->fetch($idreplacement);
3333 $this->error = $langs->trans(
"ErrorInvoiceAlreadyReplaced", $facreplaced->ref, $facreplacement->ref);
3334 $this->db->rollback();
3338 $result = $facreplaced->setCanceled($user, self::CLOSECODE_REPLACED,
'');
3340 $this->error = $facreplaced->error;
3341 $this->db->rollback();
3347 if ($force_number) {
3348 $num = $force_number;
3349 } elseif (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
3361 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
3362 $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).
"'";
3363 if (!empty($conf->global->FAC_FORCE_DATE_VALIDATION)) {
3364 $sql .=
", datef='".$this->db->idate($this->date).
"'";
3365 $sql .=
", date_lim_reglement='".$this->db->idate($this->date_lim_reglement).
"'";
3367 $sql .=
" WHERE rowid = ".((int) $this->
id);
3369 dol_syslog(get_class($this).
"::validate", LOG_DEBUG);
3370 $resql = $this->db->query($sql);
3377 if (!$error && (preg_match(
'/^[\(]?PROV/i', $this->
ref))) {
3383 $result = $this->thirdparty->set_as_client();
3386 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') && !empty($conf->global->STOCK_CALCULATE_ON_BILL) && $idwarehouse > 0) {
3387 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3388 $langs->load(
"agenda");
3391 $cpt = count($this->lines);
3392 for ($i = 0; $i < $cpt; $i++) {
3393 if ($this->lines[$i]->fk_product > 0) {
3395 $mouvP->origin = &$this;
3396 $mouvP->setOrigin($this->element, $this->
id);
3398 if ($this->
type == self::TYPE_CREDIT_NOTE) {
3399 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceValidatedInDolibarr", $num));
3402 $this->error = $mouvP->error;
3405 $is_batch_line =
false;
3406 if ($batch_rule > 0) {
3407 $productStatic->fetch($this->lines[$i]->fk_product);
3408 if ($productStatic->hasbatch()) {
3409 $is_batch_line =
true;
3410 $product_qty_remain = $this->lines[$i]->qty;
3416 $sortfield =
'pl.sellby,pl.eatby,pb.qty,pl.rowid';
3417 $sortorder =
'ASC,ASC,ASC,ASC';
3420 $resBatchList = $productbatch->findAllForProduct($productStatic->id, $idwarehouse, (
getDolGlobalInt(
'STOCK_ALLOW_NEGATIVE_TRANSFER') ?
null : 0), $sortfield, $sortorder);
3421 if (!is_array($resBatchList)) {
3423 $this->error = $this->db->lasterror();
3427 $batchList = $resBatchList;
3428 if (empty($batchList)) {
3430 $langs->load(
'errors');
3431 $warehouseStatic->fetch($idwarehouse);
3432 $this->error = $langs->trans(
'ErrorBatchNoFoundForProductInWarehouse', $productStatic->label, $warehouseStatic->ref);
3433 dol_syslog(__METHOD__.
' Error: '.$langs->transnoentitiesnoconv(
'ErrorBatchNoFoundForProductInWarehouse', $productStatic->label, $warehouseStatic->ref), LOG_ERR);
3436 foreach ($batchList as $batch) {
3437 if ($batch->qty <= 0) {
3442 if ($batch->qty >= $product_qty_remain) {
3443 $product_batch_qty = $product_qty_remain;
3446 $product_batch_qty = $batch->qty;
3448 $result = $mouvP->livraison($user, $productStatic->id, $idwarehouse, $product_batch_qty, $this->lines[$i]->subprice, $langs->trans(
'InvoiceValidatedInDolibarr', $num),
'',
'',
'', $batch->batch);
3451 $this->error = $mouvP->error;
3452 $this->errors = $mouvP->errors;
3456 $product_qty_remain -= $product_batch_qty;
3458 if ($product_qty_remain <= 0) {
3463 if (!$error && $product_qty_remain > 0) {
3466 $batch = $batchList[0];
3467 $result = $mouvP->livraison($user, $productStatic->id, $idwarehouse, $product_qty_remain, $this->lines[$i]->subprice, $langs->trans(
'InvoiceValidatedInDolibarr', $num),
'',
'',
'', $batch->batch);
3470 $this->error = $mouvP->error;
3471 $this->errors = $mouvP->errors;
3475 $langs->load(
'errors');
3476 $warehouseStatic->fetch($idwarehouse);
3477 $this->error = $langs->trans(
'ErrorBatchNoFoundEnoughQuantityForProductInWarehouse', $productStatic->label, $warehouseStatic->ref);
3478 dol_syslog(__METHOD__.
' Error: '.$langs->transnoentitiesnoconv(
'ErrorBatchNoFoundEnoughQuantityForProductInWarehouse', $productStatic->label, $warehouseStatic->ref), LOG_ERR);
3485 if (!$is_batch_line) {
3486 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceValidatedInDolibarr", $num));
3489 $this->error = $mouvP->error;
3490 $this->errors = $mouvP->errors;
3503 if (!$error && $this->
type == self::TYPE_CREDIT_NOTE && $this->fk_facture_source > 0) {
3504 $invoice_situation =
new Facture($this->db);
3505 $result = $invoice_situation->fetch($this->fk_facture_source);
3506 if ($result > 0 && $invoice_situation->type == self::TYPE_SITUATION && $invoice_situation->situation_final == 1) {
3507 $invoice_situation->situation_final = 0;
3509 $result = $invoice_situation->setFinal($user, 1);
3512 $this->error = $invoice_situation->error;
3513 $this->errors = $invoice_situation->errors;
3519 if (!$error && !$notrigger) {
3529 $this->oldref = $this->ref;
3532 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
3534 $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).
"'";
3535 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'facture/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
3536 $resql = $this->db->query($sql);
3539 $this->error = $this->db->lasterror();
3541 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'facture/".$this->db->escape($this->newref).
"'";
3542 $sql .=
" WHERE filepath = 'facture/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
3543 $resql = $this->db->query($sql);
3545 $error++; $this->error = $this->db->lasterror();
3551 $dirsource = $conf->facture->dir_output.
'/'.$oldref;
3552 $dirdest = $conf->facture->dir_output.
'/'.$newref;
3553 if (!$error && file_exists($dirsource)) {
3554 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
3556 if (@rename($dirsource, $dirdest)) {
3559 $listoffiles =
dol_dir_list($conf->facture->dir_output.
'/'.$newref,
'files', 1,
'^'.preg_quote($oldref,
'/'));
3560 foreach ($listoffiles as $fileentry) {
3561 $dirsource = $fileentry[
'name'];
3562 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
3563 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
3564 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
3565 @rename($dirsource, $dirdest);
3583 $this->brouillon = 0;
3584 $this->date_validation = $now;
3587 if (!empty($conf->global->INVOICE_USE_SITUATION)) {
3589 $nboflines = count($this->lines);
3590 while (($i < $nboflines) && $final) {
3591 $final = ($this->lines[$i]->situation_percent == 100);
3595 if (empty($final)) {
3596 $this->situation_final = 0;
3598 $this->situation_final = 1;
3609 $this->db->commit();
3612 $this->db->rollback();
3625 foreach ($this->tab_next_situation_invoice as $next_invoice) {
3626 $is_last = $next_invoice->is_last_in_cycle();
3628 if ($next_invoice->statut == self::STATUS_DRAFT && $is_last != 1) {
3629 $this->error = $langs->trans(
'updatePriceNextInvoiceErrorUpdateline', $next_invoice->ref);
3633 $next_invoice->brouillon = 1;
3635 foreach ($next_invoice->lines as $line) {
3636 $result = $next_invoice->updateline(
3641 $line->remise_percent,
3645 $line->localtax1_tx,
3646 $line->localtax2_tx,
3649 $line->product_type,
3650 $line->fk_parent_line,
3652 $line->fk_fournprice,
3655 $line->special_code,
3656 $line->array_options,
3657 $line->situation_percent,
3662 $this->error = $langs->trans(
'updatePriceNextInvoiceErrorUpdateline', $next_invoice->ref);
3683 global $conf, $langs;
3687 if ($this->
statut == self::STATUS_DRAFT) {
3688 dol_syslog(__METHOD__.
" already draft status", LOG_WARNING);
3696 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facture";
3697 $sql .=
" SET fk_statut = ".self::STATUS_DRAFT;
3698 $sql .=
" WHERE rowid = ".((int) $this->
id);
3700 $result = $this->db->query($sql);
3703 $this->oldcopy = clone $this;
3707 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') && !empty($conf->global->STOCK_CALCULATE_ON_BILL)) {
3708 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3709 $langs->load(
"agenda");
3711 $num = count($this->lines);
3712 for ($i = 0; $i < $num; $i++) {
3713 if ($this->lines[$i]->fk_product > 0) {
3715 $mouvP->origin = &$this;
3716 $mouvP->setOrigin($this->element, $this->
id);
3718 if ($this->
type == self::TYPE_CREDIT_NOTE) {
3719 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceBackToDraftInDolibarr", $this->ref));
3721 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceBackToDraftInDolibarr", $this->ref));
3728 $old_statut = $this->statut;
3729 $this->brouillon = 1;
3734 $result = $this->
call_trigger(
'BILL_UNVALIDATE', $user);
3737 $this->
statut = $old_statut;
3738 $this->status = $old_statut;
3739 $this->brouillon = 0;
3743 $this->db->rollback();
3748 $this->db->commit();
3751 $this->db->rollback();
3755 $this->error = $this->db->error();
3756 $this->db->rollback();
3816 $fk_remise_except =
'',
3817 $price_base_type =
'HT',
3824 $fk_parent_line = 0,
3825 $fk_fournprice =
null,
3829 $situation_percent = 100,
3834 $noupdateafterinsertline = 0
3838 dol_syslog(__METHOD__.
": using line label is deprecated", LOG_WARNING);
3842 global $mysoc, $conf, $langs;
3844 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);
3846 if ($this->
statut == self::STATUS_DRAFT) {
3847 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
3856 if (empty($info_bits)) {
3862 if (empty($ventil)) {
3865 if (empty($txtva)) {
3868 if (empty($txlocaltax1)) {
3871 if (empty($txlocaltax2)) {
3874 if (empty($fk_parent_line) || $fk_parent_line < 0) {
3875 $fk_parent_line = 0;
3877 if (empty($fk_prev_id)) {
3878 $fk_prev_id =
'null';
3880 if (!isset($situation_percent) || $situation_percent > 100 || (
string) $situation_percent ==
'') {
3881 $situation_percent = 100;
3883 if (empty($ref_ext)) {
3890 $pu_ht_devise =
price2num($pu_ht_devise);
3893 if (!preg_match(
'/\((.*)\)/', $txtva)) {
3899 if ($price_base_type ==
'HT') {
3910 if ($date_start && $date_end && $date_start > $date_end) {
3911 $langs->load(
"errors");
3912 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
3918 $product_type = $type;
3919 if (!empty($fk_product) && $fk_product > 0) {
3920 $product =
new Product($this->db);
3921 $result = $product->fetch($fk_product);
3922 $product_type = $product->type;
3924 if (!empty($conf->global->STOCK_MUST_BE_ENOUGH_FOR_INVOICE) && $product_type == 0 && $product->stock_reel < $qty) {
3925 $langs->load(
"errors");
3926 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnInvoice', $product->ref);
3927 $this->db->rollback();
3937 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
3938 $vat_src_code = $reg[1];
3939 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
3947 $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);
3949 $total_ht = $tabprice[0];
3950 $total_tva = $tabprice[1];
3951 $total_ttc = $tabprice[2];
3952 $total_localtax1 = $tabprice[9];
3953 $total_localtax2 = $tabprice[10];
3954 $pu_ht = $tabprice[3];
3957 $multicurrency_total_ht = $tabprice[16];
3958 $multicurrency_total_tva = $tabprice[17];
3959 $multicurrency_total_ttc = $tabprice[18];
3960 $pu_ht_devise = $tabprice[19];
3964 if ($ranktouse == -1) {
3965 $rangmax = $this->
line_max($fk_parent_line);
3966 $ranktouse = $rangmax + 1;
3972 $this->line->context = $this->context;
3974 $this->line->fk_facture = $this->id;
3975 $this->line->label = $label;
3976 $this->line->desc = $desc;
3977 $this->line->ref_ext = $ref_ext;
3979 $this->line->qty = ($this->
type == self::TYPE_CREDIT_NOTE ? abs($qty) : $qty);
3980 $this->line->subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht) : $pu_ht);
3982 $this->line->vat_src_code = $vat_src_code;
3983 $this->line->tva_tx = $txtva;
3984 $this->line->localtax1_tx = ($total_localtax1 ? $localtaxes_type[1] : 0);
3985 $this->line->localtax2_tx = ($total_localtax2 ? $localtaxes_type[3] : 0);
3986 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
3987 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
3989 $this->line->total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ht) : $total_ht);
3990 $this->line->total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ttc) : $total_ttc);
3991 $this->line->total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_tva) : $total_tva);
3992 $this->line->total_localtax1 = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_localtax1) : $total_localtax1);
3993 $this->line->total_localtax2 = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_localtax2) : $total_localtax2);
3995 $this->line->fk_product = $fk_product;
3996 $this->line->product_type = $product_type;
3998 $this->line->date_start = $date_start;
3999 $this->line->date_end = $date_end;
4000 $this->line->ventil = $ventil;
4001 $this->line->rang = $ranktouse;
4002 $this->line->info_bits = $info_bits;
4003 $this->line->fk_remise_except = $fk_remise_except;
4005 $this->line->special_code = $special_code;
4006 $this->line->fk_parent_line = $fk_parent_line;
4007 $this->line->origin = $origin;
4008 $this->line->origin_id = $origin_id;
4009 $this->line->situation_percent = $situation_percent;
4010 $this->line->fk_prev_id = $fk_prev_id;
4011 $this->line->fk_unit = $fk_unit;
4014 $this->line->fk_fournprice = $fk_fournprice;
4015 $this->line->pa_ht = $pa_ht;
4018 $this->line->fk_multicurrency = $this->fk_multicurrency;
4019 $this->line->multicurrency_code = $this->multicurrency_code;
4020 $this->line->multicurrency_subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht_devise) : $pu_ht_devise);
4022 $this->line->multicurrency_total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ht) : $multicurrency_total_ht);
4023 $this->line->multicurrency_total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_tva) : $multicurrency_total_tva);
4024 $this->line->multicurrency_total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ttc) : $multicurrency_total_ttc);
4026 if (is_array($array_options) && count($array_options) > 0) {
4027 $this->line->array_options = $array_options;
4030 $result = $this->line->insert();
4033 if (!empty($fk_parent_line)) {
4035 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
4036 $linecount = count($this->lines);
4037 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
4043 if (empty($noupdateafterinsertline)) {
4048 $this->db->commit();
4049 return $this->line->id;
4051 $this->error = $this->db->lasterror();
4052 $this->db->rollback();
4056 $this->error = $this->line->error;
4057 $this->errors = $this->line->errors;
4058 $this->db->rollback();
4062 $this->errors[]=
'status of invoice must be Draft to allow use of ->addline()';
4063 dol_syslog(get_class($this).
"::addline status of invoice must be Draft to allow use of ->addline()", LOG_ERR);
4099 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 = 0, $situation_percent = 100, $fk_unit =
null, $pu_ht_devise = 0, $notrigger = 0, $ref_ext =
'', $rang = 0)
4101 global $conf, $user;
4104 dol_syslog(__METHOD__.
": using line label is deprecated", LOG_WARNING);
4107 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
4109 global $mysoc, $langs;
4111 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);
4113 if ($this->
statut == self::STATUS_DRAFT) {
4116 if (!$this->error) {
4117 $this->error = $langs->trans(
'invoiceLineProgressError');
4123 if ($date_start && $date_end && $date_start > $date_end) {
4124 $langs->load(
"errors");
4125 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
4135 if (empty($fk_parent_line) || $fk_parent_line < 0) {
4136 $fk_parent_line = 0;
4138 if (empty($special_code) || $special_code == 3) {
4141 if (!isset($situation_percent) || $situation_percent > 100 || (
string) $situation_percent ==
'') {
4142 $situation_percent = 100;
4144 if (empty($ref_ext)) {
4151 $pu_ht_devise =
price2num($pu_ht_devise);
4153 if (!preg_match(
'/\((.*)\)/', $txtva)) {
4173 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
4174 $vat_src_code = $reg[1];
4175 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
4178 $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);
4180 $total_ht = $tabprice[0];
4181 $total_tva = $tabprice[1];
4182 $total_ttc = $tabprice[2];
4183 $total_localtax1 = $tabprice[9];
4184 $total_localtax2 = $tabprice[10];
4185 $pu_ht = $tabprice[3];
4186 $pu_tva = $tabprice[4];
4187 $pu_ttc = $tabprice[5];
4190 $multicurrency_total_ht = $tabprice[16];
4191 $multicurrency_total_tva = $tabprice[17];
4192 $multicurrency_total_ttc = $tabprice[18];
4193 $pu_ht_devise = $tabprice[19];
4200 $price = ($pu - $remise);
4206 $line->fetch($rowid);
4207 $line->fetch_optionals();
4209 if (!empty($line->fk_product)) {
4210 $product =
new Product($this->db);
4211 $result = $product->fetch($line->fk_product);
4212 $product_type = $product->type;
4214 if (!empty($conf->global->STOCK_MUST_BE_ENOUGH_FOR_INVOICE) && $product_type == 0 && $product->stock_reel < $qty) {
4215 $langs->load(
"errors");
4216 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnInvoice', $product->ref);
4217 $this->db->rollback();
4222 $staticline = clone $line;
4224 $line->oldline = $staticline;
4225 $this->line = $line;
4226 $this->line->context = $this->context;
4227 $this->line->rang = $rang;
4230 if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
4231 $rangmax = $this->
line_max($fk_parent_line);
4232 $this->line->rang = $rangmax + 1;
4235 $this->line->id = $rowid;
4236 $this->line->rowid = $rowid;
4237 $this->line->label = $label;
4238 $this->line->desc = $desc;
4239 $this->line->ref_ext = $ref_ext;
4240 $this->line->qty = ($this->
type == self::TYPE_CREDIT_NOTE ?abs($qty) : $qty);
4242 $this->line->vat_src_code = $vat_src_code;
4243 $this->line->tva_tx = $txtva;
4244 $this->line->localtax1_tx = $txlocaltax1;
4245 $this->line->localtax2_tx = $txlocaltax2;
4246 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
4247 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
4250 $this->line->subprice = ($this->
type == self::TYPE_CREDIT_NOTE ?-abs($pu_ht) : $pu_ht);
4251 $this->line->date_start = $date_start;
4252 $this->line->date_end = $date_end;
4253 $this->line->total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ?-abs($total_ht) : $total_ht);
4254 $this->line->total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ?-abs($total_tva) : $total_tva);
4255 $this->line->total_localtax1 = $total_localtax1;
4256 $this->line->total_localtax2 = $total_localtax2;
4257 $this->line->total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ?-abs($total_ttc) : $total_ttc);
4258 $this->line->info_bits = $info_bits;
4259 $this->line->special_code = $special_code;
4260 $this->line->product_type = $type;
4261 $this->line->fk_parent_line = $fk_parent_line;
4262 $this->line->skip_update_total = $skip_update_total;
4263 $this->line->situation_percent = $situation_percent;
4264 $this->line->fk_unit = $fk_unit;
4266 $this->line->fk_fournprice = $fk_fournprice;
4267 $this->line->pa_ht = $pa_ht;
4270 $this->line->multicurrency_subprice = ($this->
type == self::TYPE_CREDIT_NOTE ?-abs($pu_ht_devise) : $pu_ht_devise);
4271 $this->line->multicurrency_total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ?-abs($multicurrency_total_ht) : $multicurrency_total_ht);
4272 $this->line->multicurrency_total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ?-abs($multicurrency_total_tva) : $multicurrency_total_tva);
4273 $this->line->multicurrency_total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ?-abs($multicurrency_total_ttc) : $multicurrency_total_ttc);
4275 if (is_array($array_options) && count($array_options) > 0) {
4277 foreach ($array_options as $key => $value) {
4278 $this->line->array_options[$key] = $array_options[$key];
4282 $result = $this->line->update($user, $notrigger);
4285 if (!empty($fk_parent_line)) {
4291 $this->db->commit();
4294 $this->error = $this->line->error;
4295 $this->db->rollback();
4299 $this->error =
"Invoice statut makes operation forbidden";
4313 $sql =
'SELECT fd.situation_percent FROM '.MAIN_DB_PREFIX.
'facturedet fd
4314 INNER JOIN '.MAIN_DB_PREFIX.
'facture f ON (fd.fk_facture = f.rowid)
4315 WHERE fd.fk_prev_id = '.((int) $idline).
' AND f.fk_statut <> 0';
4317 $result = $this->db->query($sql);
4319 $this->error = $this->db->error();
4323 $obj = $this->db->fetch_object($result);
4325 if ($obj ===
null) {
4328 return ($situation_percent < $obj->situation_percent);
4344 global $mysoc, $user;
4347 if (($line->info_bits & 2) == 2) {
4351 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
4354 if ($percent > 100) {
4357 $line->situation_percent = $percent;
4358 $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);
4359 $line->total_ht = $tabprice[0];
4360 $line->total_tva = $tabprice[1];
4361 $line->total_ttc = $tabprice[2];
4362 $line->total_localtax1 = $tabprice[9];
4363 $line->total_localtax2 = $tabprice[10];
4364 $line->multicurrency_total_ht = $tabprice[16];
4365 $line->multicurrency_total_tva = $tabprice[17];
4366 $line->multicurrency_total_ttc = $tabprice[18];
4367 $line->update($user);
4370 if ($update_price) {
4386 dol_syslog(get_class($this).
"::deleteline rowid=".((
int) $rowid), LOG_DEBUG);
4388 if ($this->
statut != self::STATUS_DRAFT) {
4389 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
4395 $line->context = $this->context;
4398 $result = $line->fetch($rowid);
4399 if (!($result > 0)) {
4404 if ($id > 0 && $line->fk_facture != $id) {
4405 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
4412 $staticline = clone $line;
4413 $line->oldline = $staticline;
4415 if ($line->delete($user) > 0) {
4419 $this->db->commit();
4422 $this->db->rollback();
4423 $this->error = $this->db->lasterror();
4427 $this->db->rollback();
4428 $this->error = $line->error;
4447 dol_syslog(get_class($this).
"::set_remise is deprecated, use setDiscount instead", LOG_NOTICE);
4448 return $this->
setDiscount($user, $remise, $notrigger);
4463 if (empty($remise)) {
4467 if ($user->hasRight(
'facture',
'creer')) {
4474 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
4475 $sql .=
' SET remise_percent = '.((float) $remise);
4476 $sql .=
" WHERE rowid = ".((int) $this->
id);
4477 $sql .=
' AND fk_statut = '.self::STATUS_DRAFT;
4480 $resql = $this->db->query($sql);
4482 $this->errors[] = $this->db->error();
4486 if (!$notrigger && empty($error)) {
4496 $this->remise_percent = $remise;
4499 $this->db->commit();
4502 foreach ($this->errors as $errmsg) {
4503 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
4504 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
4506 $this->db->rollback();
4527 if (empty($remise)) {
4531 if ($user->hasRight(
'facture',
'creer')) {
4538 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
4539 $sql .=
' SET remise_absolue = '.((float) $remise);
4540 $sql .=
" WHERE rowid = ".((int) $this->
id);
4541 $sql .=
' AND fk_statut = '.self::STATUS_DRAFT;
4544 $resql = $this->db->query($sql);
4546 $this->errors[] = $this->db->error();
4551 $this->oldcopy = clone $this;
4552 $this->remise_absolue = $remise;
4556 if (!$notrigger && empty($error)) {
4566 $this->db->commit();
4569 foreach ($this->errors as $errmsg) {
4570 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
4571 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
4573 $this->db->rollback();
4591 global $conf, $langs;
4593 if ($this->module_source ==
'takepos') {
4594 $langs->load(
'cashdesk');
4596 $moduleName =
'takepos';
4597 $moduleSourceName =
'Takepos';
4598 $addonConstName =
'TAKEPOS_REF_ADDON';
4601 if (empty($conf->global->TAKEPOS_REF_ADDON)) {
4602 $conf->global->TAKEPOS_REF_ADDON =
'mod_takepos_ref_simple';
4605 $addon = $conf->global->TAKEPOS_REF_ADDON;
4607 $langs->load(
'bills');
4609 $moduleName =
'facture';
4610 $moduleSourceName =
'Invoice';
4611 $addonConstName =
'FACTURE_ADDON';
4614 if (empty($conf->global->FACTURE_ADDON)) {
4615 $conf->global->FACTURE_ADDON =
'mod_facture_terre';
4616 } elseif ($conf->global->FACTURE_ADDON ==
'terre') {
4617 $conf->global->FACTURE_ADDON =
'mod_facture_terre';
4618 } elseif ($conf->global->FACTURE_ADDON ==
'mercure') {
4619 $conf->global->FACTURE_ADDON =
'mod_facture_mercure';
4622 $addon = $conf->global->FACTURE_ADDON;
4625 if (!empty($addon)) {
4626 dol_syslog(
"Call getNextNumRef with ".$addonConstName.
" = ".$conf->global->FACTURE_ADDON.
", thirdparty=".$soc->name.
", type=".$soc->typent_code.
", mode=".$mode, LOG_DEBUG);
4630 $file = $addon.
'.php';
4631 $classname = $addon;
4635 $dirmodels = array_merge(array(
'/'), (array) $conf->modules_parts[
'models']);
4636 foreach ($dirmodels as $reldir) {
4637 $dir =
dol_buildpath($reldir.
'core/modules/'.$moduleName.
'/');
4640 if (is_file($dir.$file) && is_readable($dir.$file)) {
4641 $mybool |= include_once $dir.$file;
4647 $file = $addon.
'/'.$addon.
'.modules.php';
4648 $classname =
'mod_'.$moduleName.
'_'.$addon;
4649 $classname = preg_replace(
'/\-.*$/',
'', $classname);
4651 foreach ($conf->file->dol_document_root as $dirroot) {
4652 $dir = $dirroot.
'/core/modules/'.$moduleName.
'/';
4655 if (is_file($dir.$file) && is_readable($dir.$file)) {
4656 $mybool |= include_once $dir.$file;
4666 $obj =
new $classname();
4668 $numref = $obj->getNextValue($soc, $this, $mode);
4675 if ($mode !=
'last' && !$numref) {
4676 $this->error = $obj->error;
4682 $langs->load(
'errors');
4683 print $langs->trans(
'Error').
' '.$langs->trans(
'ErrorModuleSetupNotComplete', $langs->transnoentitiesnoconv($moduleSourceName));
4696 $sql =
'SELECT c.rowid, datec, date_valid as datev, tms as datem,';
4697 $sql .=
' date_closing as dateclosing,';
4698 $sql .=
' fk_user_author, fk_user_valid, fk_user_closing';
4699 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facture as c';
4700 $sql .=
' WHERE c.rowid = '.((int) $id);
4702 $result = $this->db->query($sql);
4704 if ($this->db->num_rows($result)) {
4705 $obj = $this->db->fetch_object($result);
4706 $this->
id = $obj->rowid;
4707 if ($obj->fk_user_author) {
4708 $cuser =
new User($this->db);
4709 $cuser->fetch($obj->fk_user_author);
4710 $this->user_creation = $cuser;
4712 if ($obj->fk_user_valid) {
4713 $vuser =
new User($this->db);
4714 $vuser->fetch($obj->fk_user_valid);
4715 $this->user_validation = $vuser;
4717 if ($obj->fk_user_closing) {
4718 $cluser =
new User($this->db);
4719 $cluser->fetch($obj->fk_user_closing);
4720 $this->user_closing = $cluser;
4723 $this->date_creation = $this->db->jdate($obj->datec);
4724 $this->date_modification = $this->db->jdate($obj->datem);
4725 $this->date_validation = $this->db->jdate($obj->datev);
4726 $this->date_closing = $this->db->jdate($obj->dateclosing);
4728 $this->db->free($result);
4749 public function liste_array($shortlist = 0, $draft = 0, $excluser =
'', $socid = 0, $limit = 0, $offset = 0, $sortfield =
'f.datef,f.rowid', $sortorder =
'DESC')
4752 global $conf, $user;
4756 $sql =
"SELECT s.rowid, s.nom as name, s.client,";
4757 $sql .=
" f.rowid as fid, f.ref as ref, f.datef as df";
4758 if (empty($user->rights->societe->client->voir) && !$socid) {
4759 $sql .=
", sc.fk_soc, sc.fk_user";
4761 $sql .=
" FROM ".MAIN_DB_PREFIX.
"societe as s, ".MAIN_DB_PREFIX.
"facture as f";
4762 if (empty($user->rights->societe->client->voir) && !$socid) {
4763 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
4765 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice').
")";
4766 $sql .=
" AND f.fk_soc = s.rowid";
4767 if (empty($user->rights->societe->client->voir) && !$socid) {
4768 $sql .=
" AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4771 $sql .=
" AND s.rowid = ".((int) $socid);
4774 $sql .=
" AND f.fk_statut = ".self::STATUS_DRAFT;
4776 if (is_object($excluser)) {
4777 $sql .=
" AND f.fk_user_author <> ".((int) $excluser->id);
4779 $sql .= $this->db->order($sortfield, $sortorder);
4780 $sql .= $this->db->plimit($limit, $offset);
4782 $result = $this->db->query($sql);
4784 $numc = $this->db->num_rows($result);
4787 while ($i < $numc) {
4788 $obj = $this->db->fetch_object($result);
4790 if ($shortlist == 1) {
4791 $ga[$obj->fid] = $obj->ref;
4792 } elseif ($shortlist == 2) {
4793 $ga[$obj->fid] = $obj->ref.
' ('.$obj->name.
')';
4795 $ga[$i][
'id'] = $obj->fid;
4796 $ga[$i][
'ref'] = $obj->ref;
4797 $ga[$i][
'name'] = $obj->name;
4826 $sql =
"SELECT f.rowid as rowid, f.ref, f.fk_statut as status, f.paye as paid,";
4827 $sql .=
" ff.rowid as rowidnext";
4829 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4830 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"paiement_facture as pf ON f.rowid = pf.fk_facture";
4831 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facture as ff ON f.rowid = ff.fk_facture_source";
4832 $sql .=
" WHERE (f.fk_statut = ".self::STATUS_VALIDATED.
" OR (f.fk_statut = ".self::STATUS_ABANDONED.
" AND f.close_code = '".self::CLOSECODE_ABANDONED.
"'))";
4833 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4834 $sql .=
" AND f.paye = 0";
4835 $sql .=
" AND pf.fk_paiement IS NULL";
4836 $sql .=
" AND ff.fk_statut IS NULL";
4838 $sql .=
" AND f.fk_soc = ".((int) $socid);
4841 $sql .=
" ORDER BY f.ref";
4843 dol_syslog(get_class($this).
"::list_replacable_invoices", LOG_DEBUG);
4844 $resql = $this->db->query($sql);
4846 while ($obj = $this->db->fetch_object($resql)) {
4847 $return[$obj->rowid] = array(
4848 'id' => $obj->rowid,
4850 'status' => $obj->status,
4851 'paid' => $obj->paid,
4858 $this->error = $this->db->error();
4881 $sql =
"SELECT f.rowid as rowid, f.ref, f.fk_statut, f.type, f.paye, pf.fk_paiement";
4882 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4883 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"paiement_facture as pf ON f.rowid = pf.fk_facture";
4884 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facture as ff ON (f.rowid = ff.fk_facture_source AND ff.type=".self::TYPE_REPLACEMENT.
")";
4885 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice').
")";
4886 $sql .=
" AND f.fk_statut in (".self::STATUS_VALIDATED.
",".self::STATUS_CLOSED.
")";
4890 $sql .=
" AND ff.type IS NULL";
4891 $sql .=
" AND f.type <> ".self::TYPE_CREDIT_NOTE;
4893 if (!empty($conf->global->INVOICE_USE_SITUATION_CREDIT_NOTE)) {
4895 $sql .=
" AND (f.type <> ".self::TYPE_SITUATION.
" OR f.rowid IN ";
4896 $sql .=
'(SELECT MAX(fs.rowid)';
4897 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as fs";
4898 $sql .=
" WHERE fs.entity IN (".getEntity(
'invoice').
")";
4899 $sql .=
" AND fs.type = ".self::TYPE_SITUATION;
4900 $sql .=
" AND fs.fk_statut IN (".self::STATUS_VALIDATED.
",".self::STATUS_CLOSED.
")";
4902 $sql .=
" AND fs.fk_soc = ".((int) $socid);
4904 $sql .=
" GROUP BY fs.situation_cycle_ref)";
4907 $sql .=
" AND f.type <> ".self::TYPE_SITUATION;
4911 $sql .=
" AND f.fk_soc = ".((int) $socid);
4913 $sql .=
" ORDER BY f.ref";
4915 dol_syslog(get_class($this).
"::list_qualified_avoir_invoices", LOG_DEBUG);
4916 $resql = $this->db->query($sql);
4918 while ($obj = $this->db->fetch_object($resql)) {
4920 if ($obj->fk_statut == self::STATUS_VALIDATED) {
4923 if ($obj->fk_statut == self::STATUS_CLOSED) {
4928 $paymentornot = ($obj->fk_paiement ? 1 : 0);
4929 $return[$obj->rowid] = array(
'ref'=>$obj->ref,
'status'=>$obj->fk_statut,
'type'=>$obj->type,
'paye'=>$obj->paye,
'paymentornot'=>$paymentornot);
4935 $this->error = $this->db->error();
4951 global $conf, $langs;
4955 $sql =
"SELECT f.rowid, f.date_lim_reglement as datefin, f.fk_statut, f.total_ht";
4956 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4957 if (empty($user->rights->societe->client->voir) && !$user->socid) {
4958 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON f.fk_soc = sc.fk_soc";
4959 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
4962 $sql .= $clause.
" f.paye=0";
4963 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4964 $sql .=
" AND f.fk_statut = ".self::STATUS_VALIDATED;
4966 $sql .=
" AND f.fk_soc = ".((int) $user->socid);
4969 $resql = $this->db->query($sql);
4971 $langs->load(
"bills");
4975 $response->warning_delay = $conf->facture->client->warning_delay / 60 / 60 / 24;
4976 $response->label = $langs->trans(
"CustomerBillsUnpaid");
4977 $response->labelShort = $langs->trans(
"Unpaid");
4978 $response->url = DOL_URL_ROOT.
'/compta/facture/list.php?search_status=1&mainmenu=billing&leftmenu=customers_bills';
4981 $generic_facture =
new Facture($this->db);
4983 while ($obj = $this->db->fetch_object($resql)) {
4984 $generic_facture->date_lim_reglement = $this->db->jdate($obj->datefin);
4985 $generic_facture->statut = $obj->fk_statut;
4987 $response->nbtodo++;
4988 $response->total += $obj->total_ht;
4990 if ($generic_facture->hasDelay()) {
4991 $response->nbtodolate++;
4992 $response->url_late = DOL_URL_ROOT.
'/compta/facture/list.php?search_option=late&mainmenu=billing&leftmenu=customers_bills';
4996 $this->db->free($resql);
5000 $this->error = $this->db->error();
5039 global $conf, $langs, $user;
5043 $nownotime =
dol_mktime(0, 0, 0, $arraynow[
'mon'], $arraynow[
'mday'], $arraynow[
'year']);
5048 $sql =
"SELECT rowid";
5049 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
5050 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
5051 $sql .= $this->db->plimit(100);
5053 $resql = $this->db->query($sql);
5055 $num_prods = $this->db->num_rows($resql);
5057 while ($i < $num_prods) {
5059 $row = $this->db->fetch_row($resql);
5060 $prodids[$i] = $row[0];
5064 if (empty($num_prods)) {
5071 $this->
ref =
'SPECIMEN';
5072 $this->specimen = 1;
5074 $this->date = $nownotime;
5075 $this->date_lim_reglement = $nownotime + 3600 * 24 * 30;
5076 $this->cond_reglement_id = 1;
5077 $this->cond_reglement_code =
'RECEP';
5079 $this->mode_reglement_id = 0;
5080 $this->mode_reglement_code =
'';
5082 $this->note_public =
'This is a comment (public)';
5083 $this->note_private =
'This is a comment (private)';
5084 $this->note =
'This is a comment (private)';
5086 $this->fk_user_author = $user->id;
5088 $this->multicurrency_tx = 1;
5089 $this->multicurrency_code = $conf->currency;
5091 $this->fk_incoterms = 0;
5092 $this->location_incoterms =
'';
5094 if (empty($option) || $option !=
'nolines') {
5098 while ($xnbp < $nbp) {
5100 $line->desc = $langs->trans(
"Description").
" ".$xnbp;
5102 $line->subprice = 100;
5103 $line->tva_tx = 19.6;
5104 $line->localtax1_tx = 0;
5105 $line->localtax2_tx = 0;
5106 $line->remise_percent = 0;
5108 $prodid = mt_rand(1, $num_prods);
5109 $line->fk_product = $prodids[$prodid];
5111 $line->total_ht = -100;
5112 $line->total_ttc = -119.6;
5113 $line->total_tva = -19.6;
5114 $line->multicurrency_total_ht = -200;
5115 $line->multicurrency_total_ttc = -239.2;
5116 $line->multicurrency_total_tva = -39.2;
5117 } elseif ($xnbp == 2) {
5118 $line->subprice = -100;
5119 $line->total_ht = -100;
5120 $line->total_ttc = -119.6;
5121 $line->total_tva = -19.6;
5122 $line->remise_percent = 0;
5123 $line->multicurrency_total_ht = -200;
5124 $line->multicurrency_total_ttc = -239.2;
5125 $line->multicurrency_total_tva = -39.2;
5126 } elseif ($xnbp == 3) {
5127 $prodid = mt_rand(1, $num_prods);
5128 $line->fk_product = $prodids[$prodid];
5129 $line->total_ht = 50;
5130 $line->total_ttc = 59.8;
5131 $line->total_tva = 9.8;
5132 $line->multicurrency_total_ht = 100;
5133 $line->multicurrency_total_ttc = 119.6;
5134 $line->multicurrency_total_tva = 19.6;
5135 $line->remise_percent = 50;
5138 $prodid = mt_rand(1, $num_prods);
5139 $line->fk_product = $prodids[$prodid];
5140 $line->total_ht = 100;
5141 $line->total_ttc = 119.6;
5142 $line->total_tva = 19.6;
5143 $line->multicurrency_total_ht = 200;
5144 $line->multicurrency_total_ttc = 239.2;
5145 $line->multicurrency_total_tva = 39.2;
5146 $line->remise_percent = 0;
5149 $this->lines[$xnbp] = $line;
5152 $this->total_ht += $line->total_ht;
5153 $this->total_tva += $line->total_tva;
5154 $this->total_ttc += $line->total_ttc;
5156 $this->multicurrency_total_ht += $line->multicurrency_total_ht;
5157 $this->multicurrency_total_tva += $line->multicurrency_total_tva;
5158 $this->multicurrency_total_ttc += $line->multicurrency_total_ttc;
5162 $this->revenuestamp = 0;
5166 $line->desc = $langs->trans(
"Description").
" (offered line)";
5168 $line->subprice = 100;
5169 $line->tva_tx = 19.6;
5170 $line->localtax1_tx = 0;
5171 $line->localtax2_tx = 0;
5172 $line->remise_percent = 100;
5173 $line->total_ht = 0;
5174 $line->total_ttc = 0;
5175 $line->total_tva = 0;
5176 $line->multicurrency_total_ht = 0;
5177 $line->multicurrency_total_ttc = 0;
5178 $line->multicurrency_total_tva = 0;
5179 $prodid = mt_rand(1, $num_prods);
5180 $line->fk_product = $prodids[$prodid];
5182 $this->lines[$xnbp] = $line;
5196 global $conf, $user;
5198 $this->nb = array();
5202 $sql =
"SELECT count(f.rowid) as nb";
5203 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
5204 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON f.fk_soc = s.rowid";
5205 if (empty($user->rights->societe->client->voir) && !$user->socid) {
5206 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON s.rowid = sc.fk_soc";
5207 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
5210 $sql .=
" ".$clause.
" f.entity IN (".
getEntity(
'invoice').
")";
5212 $resql = $this->db->query($sql);
5214 while ($obj = $this->db->fetch_object($resql)) {
5215 $this->nb[
"invoices"] = $obj->nb;
5217 $this->db->free($resql);
5221 $this->error = $this->db->error();
5247 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
5249 global $conf, $langs;
5251 $outputlangs->loadLangs(array(
"bills",
"products"));
5255 $thisTypeConfName =
'FACTURE_ADDON_PDF_'.$this->type;
5257 if (!empty($this->model_pdf)) {
5258 $modele = $this->model_pdf;
5259 } elseif (!empty($this->modelpdf)) {
5260 $modele = $this->modelpdf;
5261 } elseif (!empty($conf->global->$thisTypeConfName)) {
5262 $modele = $conf->global->$thisTypeConfName;
5263 } elseif (!empty($conf->global->FACTURE_ADDON_PDF)) {
5264 $modele = $conf->global->FACTURE_ADDON_PDF;
5268 $modelpath =
"core/modules/facture/doc/";
5270 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
5280 $sql =
'SELECT max(situation_cycle_ref) FROM '.MAIN_DB_PREFIX.
'facture as f';
5281 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice', 0).
")";
5282 $resql = $this->db->query($sql);
5284 if ($this->db->num_rows($resql) > 0) {
5285 $res = $this->db->fetch_array($resql);
5286 $ref = $res[
'max(situation_cycle_ref)'];
5291 $this->db->free($resql);
5294 $this->error = $this->db->lasterror();
5295 dol_syslog(
"Error sql=".$sql.
", error=".$this->error, LOG_ERR);
5309 return ($this->situation_counter == 1);
5323 $sql =
'SELECT rowid FROM '.MAIN_DB_PREFIX.
'facture';
5324 $sql .=
' WHERE situation_cycle_ref = '.((int) $this->situation_cycle_ref);
5325 $sql .=
' AND situation_counter < '.((int) $this->situation_counter);
5326 $sql .=
' AND entity = '.($this->entity > 0 ? $this->entity : $conf->entity);
5327 $resql = $this->db->query($sql);
5329 if ($resql && $this->db->num_rows($resql) > 0) {
5330 while ($row = $this->db->fetch_object($resql)) {
5332 $situation =
new Facture($this->db);
5333 $situation->fetch($id);
5334 $res[] = $situation;
5337 $this->error = $this->db->error();
5338 dol_syslog(
"Error sql=".$sql.
", error=".$this->error, LOG_ERR);
5358 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET situation_final = '.((int) $this->situation_final).
' WHERE rowid = '.((int) $this->
id);
5361 $resql = $this->db->query($sql);
5363 $this->errors[] = $this->db->error();
5367 if (!$notrigger && empty($error)) {
5377 $this->db->commit();
5380 foreach ($this->errors as $errmsg) {
5381 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
5382 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
5384 $this->db->rollback();
5400 if (!empty($this->situation_cycle_ref)) {
5402 $sql =
'SELECT max(situation_counter) FROM '.MAIN_DB_PREFIX.
'facture';
5403 $sql .=
' WHERE situation_cycle_ref = '.((int) $this->situation_cycle_ref);
5404 $sql .=
' AND entity = '.($this->entity > 0 ? $this->entity : $conf->entity);
5405 $resql = $this->db->query($sql);
5407 if ($resql && $this->db->num_rows($resql) > 0) {
5408 $res = $this->db->fetch_array($resql);
5409 $last = $res[
'max(situation_counter)'];
5410 return ($last == $this->situation_counter);
5412 $this->error = $this->db->lasterror();
5413 dol_syslog(get_class($this).
"::select Error ".$this->error, LOG_ERR);
5471 $hasDelay = $this->date_lim_reglement < ($now - $conf->facture->client->warning_delay);
5472 if ($hasDelay && !empty($this->retained_warranty) && !empty($this->retained_warranty_date_limit)) {
5474 $totalpaid = floatval($totalpaid);
5476 if ($totalpaid >= 0 && $RetainedWarrantyAmount >= 0) {
5477 if (($totalpaid < $this->total_ttc - $RetainedWarrantyAmount) && $this->date_lim_reglement < ($now - $conf->facture->client->warning_delay)) {
5479 } elseif ($totalpaid < $this->total_ttc && $this->retained_warranty_date_limit < ($now - $conf->facture->client->warning_delay)) {
5502 $displayWarranty =
false;
5503 if (!empty($this->retained_warranty)) {
5504 $displayWarranty =
true;
5508 $displayWarranty =
false;
5509 if (!empty($this->situation_final)) {
5510 $displayWarranty =
true;
5513 $displayWarranty =
true;
5515 foreach ($this->lines as $i => $line) {
5516 if ($line->product_type < 2 && $line->situation_percent < 100) {
5517 $displayWarranty =
false;
5525 return $displayWarranty;
5535 if (empty($this->retained_warranty)) {
5539 $retainedWarrantyAmount = 0;
5543 $displayWarranty =
true;
5545 if (!empty($this->lines)) {
5546 foreach ($this->lines as $i => $line) {
5547 if ($line->product_type < 2 && $line->situation_percent < 100) {
5548 $displayWarranty =
false;
5554 if ($displayWarranty && !empty($this->situation_final)) {
5556 $TPreviousIncoice = $this->tab_previous_situation_invoice;
5559 foreach ($TPreviousIncoice as &$fac) {
5560 $total2BillWT += $fac->total_ttc;
5562 $total2BillWT += $this->total_ttc;
5564 $retainedWarrantyAmount = $total2BillWT * $this->retained_warranty / 100;
5570 $retainedWarrantyAmount = $this->total_ttc * $this->retained_warranty / 100;
5573 if ($rounding < 0) {
5574 $rounding = min($conf->global->MAIN_MAX_DECIMALS_UNIT, $conf->global->MAIN_MAX_DECIMALS_TOT);
5577 if ($rounding > 0) {
5578 return round($retainedWarrantyAmount, $rounding);
5581 return $retainedWarrantyAmount;
5592 dol_syslog(get_class($this).
'::setRetainedWarranty('.$value.
')');
5594 if ($this->
statut >= 0) {
5595 $fieldname =
'retained_warranty';
5596 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
5597 $sql .=
" SET ".$fieldname.
" = ".((float) $value);
5598 $sql .=
' WHERE rowid='.((int) $this->
id);
5600 if ($this->db->query($sql)) {
5601 $this->retained_warranty = floatval($value);
5604 dol_syslog(get_class($this).
'::setRetainedWarranty Erreur '.$sql.
' - '.$this->db->error());
5605 $this->error = $this->db->error();
5609 dol_syslog(get_class($this).
'::setRetainedWarranty, status of the object is incompatible');
5610 $this->error =
'Status of the object is incompatible '.$this->statut;
5625 if (!$timestamp && $dateYmd) {
5626 $timestamp = $this->db->jdate($dateYmd);
5630 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit('.$timestamp.
')');
5631 if ($this->
statut >= 0) {
5632 $fieldname =
'retained_warranty_date_limit';
5633 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
5634 $sql .=
" SET ".$fieldname.
" = ".(strval($timestamp) !=
'' ?
"'".$this->db->idate($timestamp).
"'" :
'null');
5635 $sql .=
' WHERE rowid = '.((int) $this->
id);
5637 if ($this->db->query($sql)) {
5638 $this->retained_warranty_date_limit = $timestamp;
5641 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit Erreur '.$sql.
' - '.$this->db->error());
5642 $this->error = $this->db->error();
5646 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit, status of the object is incompatible');
5647 $this->error =
'Status of the object is incompatible '.$this->statut;
5666 global $conf, $langs, $user;
5672 $errorsMsg = array();
5674 $langs->load(
"bills");
5676 if (!isModEnabled(
'facture')) {
5677 $this->output .= $langs->trans(
'ModuleNotEnabled', $langs->transnoentitiesnoconv(
"Facture"));
5680 if (!in_array($datetouse, array(
'duedate',
'invoicedate'))) {
5681 $this->output .=
'Bad value for parameter datetouse. Must be "duedate" or "invoicedate"';
5691 require_once DOL_DOCUMENT_ROOT.
'/core/lib/date.lib.php';
5692 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmail.class.php';
5693 require_once DOL_DOCUMENT_ROOT.
'/core/class/CMailFile.class.php';
5694 $formmail =
new FormMail($this->db);
5699 $tmpinvoice =
new Facture($this->db);
5704 $sql =
"SELECT rowid as id FROM ".MAIN_DB_PREFIX.
"facture as f";
5705 if (!empty($paymentmode) && $paymentmode !=
'all') {
5706 $sql .=
", ".MAIN_DB_PREFIX.
"c_paiement as cp";
5708 $sql .=
" WHERE f.paye = 0";
5709 $sql .=
" AND f.fk_statut = ".self::STATUS_VALIDATED;
5710 if ($datetouse ==
'invoicedate') {
5711 $sql .=
" AND f.datef = '".$this->db->idate($tmpidate,
'gmt').
"'";
5713 $sql .=
" AND f.date_lim_reglement = '".$this->db->idate($tmpidate,
'gmt').
"'";
5715 $sql .=
" AND f.entity IN (".getEntity(
'facture', 0).
")";
5716 if (!empty($paymentmode) && $paymentmode !=
'all') {
5717 $sql .=
" AND f.fk_mode_reglement = cp.id AND cp.code = '".$this->db->escape($paymentmode).
"'";
5720 if ($datetouse ==
'invoicedate') {
5721 $sql .= $this->db->order(
"datef",
"ASC");
5723 $sql .= $this->db->order(
"date_lim_reglement",
"ASC");
5726 $resql = $this->db->query($sql);
5729 if ($datetouse ==
'invoicedate') {
5730 $this->output .= $langs->transnoentitiesnoconv(
"SearchValidatedInvoicesWithDate", $stmpidate);
5732 $this->output .= $langs->transnoentitiesnoconv(
"SearchUnpaidInvoicesWithDueDate", $stmpidate);
5734 if (!empty($paymentmode) && $paymentmode !=
'all') {
5735 $this->output .=
' ('.$langs->transnoentitiesnoconv(
"PaymentMode").
' '.$paymentmode.
')';
5737 $this->output .=
'<br>';
5740 while ($obj = $this->db->fetch_object($resql)) {
5743 $res = $tmpinvoice->fetch($obj->id);
5745 $tmpinvoice->fetch_thirdparty();
5747 $outputlangs =
new Translate(
'', $conf);
5748 if ($tmpinvoice->thirdparty->default_lang) {
5749 $outputlangs->setDefaultLang($tmpinvoice->thirdparty->default_lang);
5750 $outputlangs->loadLangs(array(
"main",
"bills"));
5752 $outputlangs = $langs;
5756 $arraymessage = $formmail->getEMailTemplate($this->db,
'facture_send', $user, $outputlangs, (is_numeric($template) ? $template : 0), 1, (is_numeric($template) ?
'' : $template));
5757 if (is_numeric($arraymessage) && $arraymessage <= 0) {
5758 $langs->load(
"errors");
5759 $this->output .= $langs->trans(
'ErrorFailedToFindEmailTemplate', $template);
5772 $sendTopic =
make_substitutions(empty($arraymessage->topic) ? $outputlangs->transnoentitiesnoconv(
'InformationMessage') : $arraymessage->topic, $substitutionarray, $outputlangs, 1);
5775 $content = $outputlangs->transnoentitiesnoconv($arraymessage->content);
5781 if ($forcerecipient) {
5782 $to = array($forcerecipient);
5784 $res = $tmpinvoice->fetch_thirdparty();
5785 $recipient = $tmpinvoice->thirdparty;
5787 $tmparraycontact = $tmpinvoice->liste_contact(-1,
'external', 0,
'BILLING');
5788 if (is_array($tmparraycontact) && count($tmparraycontact) > 0) {
5789 foreach ($tmparraycontact as $data_email) {
5790 if (!empty($data_email[
'email'])) {
5791 $to[] = $tmpinvoice->thirdparty->contact_get_property($data_email[
'id'],
'email');
5795 if (empty($to) && !empty($recipient->email)) {
5796 $to[] = $recipient->email;
5799 $errormesg =
"Failed to send remind to thirdparty id=".$tmpinvoice->socid.
". No email defined for invoice or customer.";
5803 $errormesg =
"Failed to load recipient with thirdparty id=".$tmpinvoice->socid;
5810 if (!empty($arraymessage->email_from)) {
5811 $from = $arraymessage->email_from;
5814 $errormesg =
"Failed to get sender into global setup MAIN_MAIL_EMAIL_FROM";
5818 if (!$error && !empty($to)) {
5821 $to = implode(
',', $to);
5822 if (!empty($arraymessage->email_to)) {
5823 $to = $to.
','.$arraymessage->email_to;
5827 $errors_to = $conf->global->MAIN_MAIL_ERRORS_TO;
5829 $trackid =
'inv'.$tmpinvoice->id;
5830 $sendcontext =
'standard';
5833 if (!empty($arraymessage->email_tocc)) {
5834 $email_tocc = $arraymessage->email_tocc;
5838 if (!empty($arraymessage->email_tobcc)) {
5839 $email_tobcc = $arraymessage->email_tobcc;
5846 if ($arraymessage->joinfiles == 1 && !empty($tmpinvoice->last_main_doc)) {
5847 $joinFile[] = DOL_DATA_ROOT.
'/'.$tmpinvoice->last_main_doc;
5848 $joinFileName[] = basename($tmpinvoice->last_main_doc);
5849 $joinFileMime[] =
dol_mimetype(DOL_DATA_ROOT.
'/'.$tmpinvoice->last_main_doc);
5853 $cMailFile =
new CMailFile($sendTopic, $to, $from, $sendContent, $joinFile, $joinFileMime, $joinFileName, $email_tocc, $email_tobcc, 0, 1, $errors_to,
'', $trackid,
'', $sendcontext,
'');
5856 if ($cMailFile->sendfile()) {
5860 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
5865 $actioncomm->type_code =
'AC_OTH_AUTO';
5866 $actioncomm->socid = $tmpinvoice->thirdparty->id;
5867 $actioncomm->contact_id = 0;
5869 $actioncomm->code =
'AC_EMAIL';
5870 $actioncomm->label =
'sendEmailsRemindersOnInvoiceDueDateOK (nbdays='.$nbdays.
' paymentmode='.$paymentmode.
' template='.$template.
' datetouse='.$datetouse.
' forcerecipient='.$forcerecipient.
')';
5871 $actioncomm->note_private = $sendContent;
5872 $actioncomm->fk_project = $tmpinvoice->fk_project;
5873 $actioncomm->datep =
dol_now();
5874 $actioncomm->datef = $actioncomm->datep;
5875 $actioncomm->percentage = -1;
5876 $actioncomm->authorid = $user->id;
5877 $actioncomm->userownerid = $user->id;
5879 $actioncomm->email_msgid = $cMailFile->msgid;
5880 $actioncomm->email_subject = $sendTopic;
5881 $actioncomm->email_from = $from;
5882 $actioncomm->email_sender =
'';
5883 $actioncomm->email_to = $to;
5887 $actioncomm->errors_to = $errors_to;
5889 $actioncomm->elementtype =
'invoice';
5890 $actioncomm->fk_element = $tmpinvoice->id;
5894 $actioncomm->create($user);
5896 $errormesg = $cMailFile->error.
' : '.$to;
5900 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
5905 $actioncomm->type_code =
'AC_OTH_AUTO';
5906 $actioncomm->socid = $tmpinvoice->thirdparty->id;
5907 $actioncomm->contact_id = 0;
5909 $actioncomm->code =
'AC_EMAIL';
5910 $actioncomm->label =
'sendEmailsRemindersOnInvoiceDueDateKO';
5911 $actioncomm->note_private = $errormesg;
5912 $actioncomm->fk_project = $tmpinvoice->fk_project;
5913 $actioncomm->datep =
dol_now();
5914 $actioncomm->datef = $actioncomm->datep;
5915 $actioncomm->percentage = -1;
5916 $actioncomm->authorid = $user->id;
5917 $actioncomm->userownerid = $user->id;
5919 $actioncomm->email_msgid = $cMailFile->msgid;
5920 $actioncomm->email_from = $from;
5921 $actioncomm->email_sender =
'';
5922 $actioncomm->email_to = $to;
5926 $actioncomm->errors_to = $errors_to;
5930 $actioncomm->create($user);
5933 $this->db->commit();
5937 $errorsMsg[] = $errormesg;
5940 $errorsMsg[] =
'Failed to fetch record invoice with ID = '.$obj->id;
5950 $this->output .=
'Nb of emails sent : '.$nbMailSend;
5952 dol_syslog(__METHOD__.
" end - ".$this->output, LOG_INFO);
5956 $this->error =
'Nb of emails sent : '.$nbMailSend.
', '.(!empty($errorsMsg)) ? join(
', ', $errorsMsg) : $error;
5958 dol_syslog(__METHOD__.
" end - ".$this->error, LOG_INFO);
5973 $sql =
"SELECT datef";
5974 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture";
5975 $sql .=
" WHERE type = " . (int) $this->
type ;
5976 $sql .=
" AND date_valid IS NOT NULL";
5977 $sql .=
" AND entity IN (".getEntity(
'invoice').
")";
5978 $sql .=
" ORDER BY datef DESC LIMIT 1";
5980 $result = $this->db->query($sql);
5983 if ($this->db->num_rows($result)) {
5984 $obj = $this->db->fetch_object($result);
5985 $last_date = $this->db->jdate($obj->datef);
5986 $invoice_date = $this->date;
5988 $is_last_of_same_type = $invoice_date >= $last_date;
5989 if ($allow_validated_drafts) {
5990 $is_last_of_same_type = $is_last_of_same_type || (!strpos($this->
ref,
'PROV') && $this->status ==
self::STATUS_DRAFT);
5993 return array($is_last_of_same_type, $last_date);
6014 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
6016 $return =
'<div class="box-flex-item box-flex-grow-zero">';
6017 $return .=
'<div class="info-box info-box-sm">';
6018 $return .=
'<span class="info-box-icon bg-infobox-action">';
6021 $return .=
'</span>';
6022 $return .=
'<div class="info-box-content">';
6023 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl(1) : $this->ref).
'</span>';
6024 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
6025 if (property_exists($this,
'socid')) {
6026 $return .=
'<br><span class="info-box-label">'.$this->socid.
'</span>';
6028 if (property_exists($this,
'fk_user_author')) {
6029 $return .=
'<br><span class="info-box-label">'.$this->fk_user_author.
'</span>';
6031 if (method_exists($this,
'getLibStatut')) {
6032 $return .=
'<br><div class="info-box-status margintoponly">'.$this->getLibStatut(3).
'</div>';
6034 $return .=
'</div>';
6035 $return .=
'</div>';
6036 $return .=
'</div>';
6050 public $element =
'facturedet';
6055 public $table_element =
'facturedet';
6072 public $localtax1_type;
6073 public $localtax2_type;
6074 public $fk_remise_except;
6077 public $fk_fournprice;
6082 public $remise_percent;
6084 public $special_code;
6092 public $fk_code_ventilation = 0;
6097 public $skip_update_total;
6102 public $situation_percent;
6110 public $fk_multicurrency;
6111 public $multicurrency_code;
6112 public $multicurrency_subprice;
6113 public $multicurrency_total_ht;
6114 public $multicurrency_total_tva;
6115 public $multicurrency_total_ttc;
6135 $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,';
6136 $sql .=
' fd.localtax1_tx, fd. localtax2_tx, fd.remise, fd.remise_percent, fd.fk_remise_except, fd.subprice, fd.ref_ext,';
6137 $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,';
6138 $sql .=
' fd.info_bits, fd.special_code, fd.total_ht, fd.total_tva, fd.total_ttc, fd.total_localtax1, fd.total_localtax2, fd.rang,';
6139 $sql .=
' fd.fk_code_ventilation,';
6140 $sql .=
' fd.fk_unit, fd.fk_user_author, fd.fk_user_modif,';
6141 $sql .=
' fd.situation_percent, fd.fk_prev_id,';
6142 $sql .=
' fd.multicurrency_subprice,';
6143 $sql .=
' fd.multicurrency_total_ht,';
6144 $sql .=
' fd.multicurrency_total_tva,';
6145 $sql .=
' fd.multicurrency_total_ttc,';
6146 $sql .=
' p.ref as product_ref, p.label as product_label, p.description as product_desc';
6147 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facturedet as fd';
6148 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON fd.fk_product = p.rowid';
6149 $sql .=
' WHERE fd.rowid = '.((int) $rowid);
6151 $result = $this->db->query($sql);
6153 $objp = $this->db->fetch_object($result);
6156 $this->error =
'InvoiceLine with id '. $rowid .
' not found sql='.$sql;
6160 $this->
rowid = $objp->rowid;
6161 $this->
id = $objp->rowid;
6162 $this->fk_facture = $objp->fk_facture;
6163 $this->fk_parent_line = $objp->fk_parent_line;
6164 $this->label = $objp->custom_label;
6165 $this->desc = $objp->description;
6166 $this->qty = $objp->qty;
6167 $this->subprice = $objp->subprice;
6168 $this->ref_ext = $objp->ref_ext;
6169 $this->vat_src_code = $objp->vat_src_code;
6170 $this->tva_tx = $objp->tva_tx;
6171 $this->localtax1_tx = $objp->localtax1_tx;
6172 $this->localtax2_tx = $objp->localtax2_tx;
6173 $this->remise_percent = $objp->remise_percent;
6174 $this->fk_remise_except = $objp->fk_remise_except;
6175 $this->fk_product = $objp->fk_product;
6176 $this->product_type = $objp->product_type;
6177 $this->date_start = $this->db->jdate($objp->date_start);
6178 $this->date_end = $this->db->jdate($objp->date_end);
6179 $this->info_bits = $objp->info_bits;
6180 $this->tva_npr = ($objp->info_bits & 1 == 1) ? 1 : 0;
6181 $this->special_code = $objp->special_code;
6182 $this->total_ht = $objp->total_ht;
6183 $this->total_tva = $objp->total_tva;
6184 $this->total_localtax1 = $objp->total_localtax1;
6185 $this->total_localtax2 = $objp->total_localtax2;
6186 $this->total_ttc = $objp->total_ttc;
6187 $this->fk_code_ventilation = $objp->fk_code_ventilation;
6188 $this->rang = $objp->rang;
6189 $this->fk_fournprice = $objp->fk_fournprice;
6190 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $this->fk_fournprice, $objp->pa_ht);
6191 $this->pa_ht = $marginInfos[0];
6192 $this->marge_tx = $marginInfos[1];
6193 $this->marque_tx = $marginInfos[2];
6195 $this->
ref = $objp->product_ref;
6197 $this->product_ref = $objp->product_ref;
6198 $this->product_label = $objp->product_label;
6199 $this->product_desc = $objp->product_desc;
6201 $this->fk_unit = $objp->fk_unit;
6202 $this->fk_user_modif = $objp->fk_user_modif;
6203 $this->fk_user_author = $objp->fk_user_author;
6205 $this->situation_percent = $objp->situation_percent;
6206 $this->fk_prev_id = $objp->fk_prev_id;
6208 $this->multicurrency_subprice = $objp->multicurrency_subprice;
6209 $this->multicurrency_total_ht = $objp->multicurrency_total_ht;
6210 $this->multicurrency_total_tva = $objp->multicurrency_total_tva;
6211 $this->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
6215 $this->db->free($result);
6219 $this->error = $this->db->lasterror();
6231 public function insert($notrigger = 0, $noerrorifdiscountalreadylinked = 0)
6233 global $langs, $user, $conf;
6237 $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht ==
'');
6239 dol_syslog(get_class($this).
"::insert rang=".$this->rang, LOG_DEBUG);
6242 $this->desc = trim($this->desc);
6243 if (empty($this->tva_tx)) {
6246 if (empty($this->localtax1_tx)) {
6247 $this->localtax1_tx = 0;
6249 if (empty($this->localtax2_tx)) {
6250 $this->localtax2_tx = 0;
6252 if (empty($this->localtax1_type)) {
6253 $this->localtax1_type = 0;
6255 if (empty($this->localtax2_type)) {
6256 $this->localtax2_type = 0;
6258 if (empty($this->total_localtax1)) {
6259 $this->total_localtax1 = 0;
6261 if (empty($this->total_localtax2)) {
6262 $this->total_localtax2 = 0;
6264 if (empty($this->rang)) {
6267 if (empty($this->remise_percent)) {
6268 $this->remise_percent = 0;
6270 if (empty($this->info_bits)) {
6271 $this->info_bits = 0;
6273 if (empty($this->subprice)) {
6274 $this->subprice = 0;
6276 if (empty($this->ref_ext)) {
6277 $this->ref_ext =
'';
6279 if (empty($this->special_code)) {
6280 $this->special_code = 0;
6282 if (empty($this->fk_parent_line)) {
6283 $this->fk_parent_line = 0;
6285 if (empty($this->fk_prev_id)) {
6286 $this->fk_prev_id = 0;
6288 if (!isset($this->situation_percent) || $this->situation_percent > 100 || (
string) $this->situation_percent ==
'') {
6289 $this->situation_percent = 100;
6292 if (empty($this->pa_ht)) {
6295 if (empty($this->multicurrency_subprice)) {
6296 $this->multicurrency_subprice = 0;
6298 if (empty($this->multicurrency_total_ht)) {
6299 $this->multicurrency_total_ht = 0;
6301 if (empty($this->multicurrency_total_tva)) {
6302 $this->multicurrency_total_tva = 0;
6304 if (empty($this->multicurrency_total_ttc)) {
6305 $this->multicurrency_total_ttc = 0;
6309 if ($this->pa_ht == 0 && $pa_ht_isemptystring) {
6310 if (($result = $this->
defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0) {
6313 $this->pa_ht = $result;
6318 if ($this->product_type < 0) {
6319 $this->error =
'ErrorProductTypeMustBe0orMore';
6322 if (!empty($this->fk_product) && $this->fk_product > 0) {
6326 $this->error =
'ErrorProductIdDoesNotExists';
6327 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6335 $sql =
'INSERT INTO '.MAIN_DB_PREFIX.
'facturedet';
6336 $sql .=
' (fk_facture, fk_parent_line, label, description, qty,';
6337 $sql .=
' vat_src_code, tva_tx, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type,';
6338 $sql .=
' fk_product, product_type, remise_percent, subprice, ref_ext, fk_remise_except,';
6339 $sql .=
' date_start, date_end, fk_code_ventilation, ';
6340 $sql .=
' rang, special_code, fk_product_fournisseur_price, buy_price_ht,';
6341 $sql .=
' info_bits, total_ht, total_tva, total_ttc, total_localtax1, total_localtax2,';
6342 $sql .=
' situation_percent, fk_prev_id,';
6343 $sql .=
' fk_unit, fk_user_author, fk_user_modif,';
6344 $sql .=
' fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc';
6346 $sql .=
" VALUES (".$this->fk_facture.
",";
6347 $sql .=
" ".($this->fk_parent_line > 0 ? $this->fk_parent_line :
"null").
",";
6348 $sql .=
" ".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null").
",";
6349 $sql .=
" '".$this->db->escape($this->desc).
"',";
6350 $sql .=
" ".price2num($this->qty).
",";
6351 $sql .=
" ".(empty($this->vat_src_code) ?
"''" :
"'".$this->db->escape($this->vat_src_code).
"'").
",";
6352 $sql .=
" ".price2num($this->tva_tx).
",";
6353 $sql .=
" ".price2num($this->localtax1_tx).
",";
6354 $sql .=
" ".price2num($this->localtax2_tx).
",";
6355 $sql .=
" '".$this->db->escape($this->localtax1_type).
"',";
6356 $sql .=
" '".$this->db->escape($this->localtax2_type).
"',";
6357 $sql .=
' '.((!empty($this->fk_product) && $this->fk_product > 0) ? $this->fk_product :
"null").
',';
6358 $sql .=
" ".((int) $this->product_type).
",";
6359 $sql .=
" ".price2num($this->remise_percent).
",";
6360 $sql .=
" ".price2num($this->subprice).
",";
6361 $sql .=
" '".$this->db->escape($this->ref_ext).
"',";
6362 $sql .=
' '.(!empty($this->fk_remise_except) ? $this->fk_remise_except :
"null").
',';
6363 $sql .=
" ".(!empty($this->date_start) ?
"'".$this->db->idate($this->date_start).
"'" :
"null").
",";
6364 $sql .=
" ".(!empty($this->date_end) ?
"'".$this->db->idate($this->date_end).
"'" :
"null").
",";
6365 $sql .=
' '.((int) $this->fk_code_ventilation).
',';
6366 $sql .=
' '.((int) $this->rang).
',';
6367 $sql .=
' '.((int) $this->special_code).
',';
6368 $sql .=
' '.(!empty($this->fk_fournprice) ? $this->fk_fournprice :
"null").
',';
6369 $sql .=
' '.price2num($this->pa_ht).
',';
6370 $sql .=
" '".$this->db->escape($this->info_bits).
"',";
6371 $sql .=
" ".price2num($this->total_ht).
",";
6372 $sql .=
" ".price2num($this->total_tva).
",";
6373 $sql .=
" ".price2num($this->total_ttc).
",";
6374 $sql .=
" ".price2num($this->total_localtax1).
",";
6375 $sql .=
" ".price2num($this->total_localtax2);
6376 $sql .=
", ".((float) $this->situation_percent);
6377 $sql .=
", ".(!empty($this->fk_prev_id) ? $this->fk_prev_id :
"null");
6378 $sql .=
", ".(!$this->fk_unit ?
'NULL' : $this->fk_unit);
6379 $sql .=
", ".((int) $user->id);
6380 $sql .=
", ".((int) $user->id);
6381 $sql .=
", ".(int) $this->fk_multicurrency;
6382 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
6383 $sql .=
", ".price2num($this->multicurrency_subprice);
6384 $sql .=
", ".price2num($this->multicurrency_total_ht);
6385 $sql .=
", ".price2num($this->multicurrency_total_tva);
6386 $sql .=
", ".price2num($this->multicurrency_total_ttc);
6389 dol_syslog(get_class($this).
"::insert", LOG_DEBUG);
6390 $resql = $this->db->query($sql);
6392 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
'facturedet');
6393 $this->
rowid = $this->id;
6404 if ($this->fk_remise_except) {
6406 $result = $discount->fetch($this->fk_remise_except);
6411 if ($discount->fk_facture_line > 0) {
6412 if (empty($noerrorifdiscountalreadylinked)) {
6413 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed", $discount->id);
6414 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6415 $this->db->rollback();
6419 $result = $discount->link_to_invoice($this->
rowid, 0);
6421 $this->error = $discount->error;
6422 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6423 $this->db->rollback();
6428 $this->error = $langs->trans(
"ErrorADiscountThatHasBeenRemovedIsIncluded");
6429 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6430 $this->db->rollback();
6434 $this->error = $discount->error;
6435 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6436 $this->db->rollback();
6443 $result = $this->
call_trigger(
'LINEBILL_INSERT', $user);
6445 $this->db->rollback();
6451 $this->db->commit();
6454 $this->error = $this->db->lasterror();
6455 $this->db->rollback();
6467 public function update($user =
'', $notrigger = 0)
6469 global $user, $conf;
6473 $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht ==
'');
6476 $this->desc = trim($this->desc);
6477 if (empty($this->ref_ext)) {
6478 $this->ref_ext =
'';
6480 if (empty($this->tva_tx)) {
6483 if (empty($this->localtax1_tx)) {
6484 $this->localtax1_tx = 0;
6486 if (empty($this->localtax2_tx)) {
6487 $this->localtax2_tx = 0;
6489 if (empty($this->localtax1_type)) {
6490 $this->localtax1_type = 0;
6492 if (empty($this->localtax2_type)) {
6493 $this->localtax2_type = 0;
6495 if (empty($this->total_localtax1)) {
6496 $this->total_localtax1 = 0;
6498 if (empty($this->total_localtax2)) {
6499 $this->total_localtax2 = 0;
6501 if (empty($this->remise_percent)) {
6502 $this->remise_percent = 0;
6504 if (empty($this->info_bits)) {
6505 $this->info_bits = 0;
6507 if (empty($this->special_code)) {
6508 $this->special_code = 0;
6510 if (empty($this->product_type)) {
6511 $this->product_type = 0;
6513 if (empty($this->fk_parent_line)) {
6514 $this->fk_parent_line = 0;
6516 if (!isset($this->situation_percent) || $this->situation_percent > 100 || (
string) $this->situation_percent ==
'') {
6517 $this->situation_percent = 100;
6519 if (empty($this->pa_ht)) {
6523 if (empty($this->multicurrency_subprice)) {
6524 $this->multicurrency_subprice = 0;
6526 if (empty($this->multicurrency_total_ht)) {
6527 $this->multicurrency_total_ht = 0;
6529 if (empty($this->multicurrency_total_tva)) {
6530 $this->multicurrency_total_tva = 0;
6532 if (empty($this->multicurrency_total_ttc)) {
6533 $this->multicurrency_total_ttc = 0;
6537 if ($this->product_type < 0) {
6542 if ($this->pa_ht == 0 && $pa_ht_isemptystring) {
6544 $result = $this->
defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product);
6548 $this->pa_ht = $result;
6555 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facturedet SET";
6556 $sql .=
" description='".$this->db->escape($this->desc).
"'";
6557 $sql .=
", ref_ext='".$this->db->escape($this->ref_ext).
"'";
6558 $sql .=
", label=".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null");
6559 $sql .=
", subprice=".price2num($this->subprice);
6560 $sql .=
", remise_percent=".price2num($this->remise_percent);
6561 if ($this->fk_remise_except) {
6562 $sql .=
", fk_remise_except=".$this->fk_remise_except;
6564 $sql .=
", fk_remise_except=null";
6566 $sql .=
", vat_src_code = '".(empty($this->vat_src_code) ?
'' : $this->db->escape($this->vat_src_code)).
"'";
6567 $sql .=
", tva_tx=".price2num($this->tva_tx);
6568 $sql .=
", localtax1_tx=".price2num($this->localtax1_tx);
6569 $sql .=
", localtax2_tx=".price2num($this->localtax2_tx);
6570 $sql .=
", localtax1_type='".$this->db->escape($this->localtax1_type).
"'";
6571 $sql .=
", localtax2_type='".$this->db->escape($this->localtax2_type).
"'";
6572 $sql .=
", qty=".price2num($this->qty);
6573 $sql .=
", date_start=".(!empty($this->date_start) ?
"'".$this->db->idate($this->date_start).
"'" :
"null");
6574 $sql .=
", date_end=".(!empty($this->date_end) ?
"'".$this->db->idate($this->date_end).
"'" :
"null");
6575 $sql .=
", product_type=".$this->product_type;
6576 $sql .=
", info_bits='".$this->db->escape($this->info_bits).
"'";
6577 $sql .=
", special_code='".$this->db->escape($this->special_code).
"'";
6578 if (empty($this->skip_update_total)) {
6579 $sql .=
", total_ht=".price2num($this->total_ht);
6580 $sql .=
", total_tva=".price2num($this->total_tva);
6581 $sql .=
", total_ttc=".price2num($this->total_ttc);
6582 $sql .=
", total_localtax1=".price2num($this->total_localtax1);
6583 $sql .=
", total_localtax2=".price2num($this->total_localtax2);
6585 $sql .=
", fk_product_fournisseur_price=".(!empty($this->fk_fournprice) ?
"'".$this->db->escape($this->fk_fournprice).
"'" :
"null");
6586 $sql .=
", buy_price_ht=".(($this->pa_ht || (string) $this->pa_ht ===
'0') ?
price2num($this->pa_ht) :
"null");
6587 $sql .=
", fk_parent_line=".($this->fk_parent_line > 0 ? $this->fk_parent_line :
"null");
6588 if (!empty($this->rang)) {
6589 $sql .=
", rang=".((int) $this->rang);
6591 $sql .=
", situation_percent = ".((float) $this->situation_percent);
6592 $sql .=
", fk_unit = ".(!$this->fk_unit ?
'NULL' : $this->fk_unit);
6593 $sql .=
", fk_user_modif = ".((int) $user->id);
6596 $sql .=
", multicurrency_subprice=".price2num($this->multicurrency_subprice);
6597 $sql .=
", multicurrency_total_ht=".price2num($this->multicurrency_total_ht);
6598 $sql .=
", multicurrency_total_tva=".price2num($this->multicurrency_total_tva);
6599 $sql .=
", multicurrency_total_ttc=".price2num($this->multicurrency_total_ttc);
6601 $sql .=
" WHERE rowid = ".((int) $this->
rowid);
6603 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
6604 $resql = $this->db->query($sql);
6607 $this->
id = $this->rowid;
6614 if (!$error && !$notrigger) {
6616 $result = $this->
call_trigger(
'LINEBILL_MODIFY', $user);
6618 $this->db->rollback();
6623 $this->db->commit();
6626 $this->error = $this->db->error();
6627 $this->db->rollback();
6639 public function delete($tmpuser =
null, $notrigger =
false)
6646 if (empty($notrigger)) {
6647 $result = $this->
call_trigger(
'LINEBILL_DELETE', $user);
6649 $this->db->rollback();
6658 $this->db->rollback();
6663 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
6664 $sql .=
' SET fk_facture_line = NULL';
6665 $sql .=
' WHERE fk_facture_line = '.((int) $this->
id);
6667 dol_syslog(get_class($this).
"::deleteline", LOG_DEBUG);
6668 $result = $this->db->query($sql);
6670 $this->error = $this->db->error();
6671 $this->errors[] = $this->error;
6672 $this->db->rollback();
6676 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'element_time';
6677 $sql .=
' SET invoice_id = NULL, invoice_line_id = NULL';
6678 $sql .=
' WHERE invoice_line_id = '.((int) $this->
id);
6679 if (!$this->db->query($sql)) {
6680 $this->error = $this->db->error().
" sql=".$sql;
6681 $this->errors[] = $this->error;
6682 $this->db->rollback();
6686 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"facturedet WHERE rowid = ".((int) $this->
id);
6688 if ($this->db->query($sql)) {
6689 $this->db->commit();
6692 $this->error = $this->db->error().
" sql=".$sql;
6693 $this->errors[] = $this->error;
6694 $this->db->rollback();
6710 dol_syslog(get_class($this).
"::update_total", LOG_DEBUG);
6713 if (empty($this->total_localtax1)) {
6714 $this->total_localtax1 = 0;
6716 if (empty($this->total_localtax2)) {
6717 $this->total_localtax2 = 0;
6721 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facturedet SET";
6722 $sql .=
" total_ht=".price2num($this->total_ht);
6723 $sql .=
",total_tva=".price2num($this->total_tva);
6724 $sql .=
",total_localtax1=".price2num($this->total_localtax1);
6725 $sql .=
",total_localtax2=".price2num($this->total_localtax2);
6726 $sql .=
",total_ttc=".price2num($this->total_ttc);
6727 $sql .=
" WHERE rowid = ".((int) $this->
rowid);
6729 dol_syslog(get_class($this).
"::update_total", LOG_DEBUG);
6731 $resql = $this->db->query($sql);
6733 $this->db->commit();
6736 $this->error = $this->db->error();
6737 $this->db->rollback();
6754 global $invoicecache;
6756 if (is_null($this->fk_prev_id) || empty($this->fk_prev_id) || $this->fk_prev_id ==
"") {
6760 if (!isset($invoicecache[$invoiceid])) {
6761 $invoicecache[$invoiceid] =
new Facture($this->db);
6762 $invoicecache[$invoiceid]->fetch($invoiceid);
6768 $sql =
"SELECT situation_percent FROM ".MAIN_DB_PREFIX.
"facturedet WHERE rowid = ".((int) $this->fk_prev_id);
6769 $resql = $this->db->query($sql);
6770 if ($resql && $this->db->num_rows($resql) > 0) {
6771 $res = $this->db->fetch_array($resql);
6773 $returnPercent = floatval($res[
'situation_percent']);
6775 if ($include_credit_note) {
6776 $sql =
'SELECT fd.situation_percent FROM '.MAIN_DB_PREFIX.
'facturedet fd';
6777 $sql .=
' JOIN '.MAIN_DB_PREFIX.
'facture f ON (f.rowid = fd.fk_facture) ';
6778 $sql .=
" WHERE fd.fk_prev_id = ".((int) $this->fk_prev_id);
6779 $sql .=
" AND f.situation_cycle_ref = ".((int) $invoicecache[$invoiceid]->situation_cycle_ref);
6780 $sql .=
" AND f.type = ".Facture::TYPE_CREDIT_NOTE;
6782 $res = $this->db->query($sql);
6784 while ($obj = $this->db->fetch_object($res)) {
6785 $returnPercent = $returnPercent + floatval($obj->situation_percent);
6792 return $returnPercent;
6794 $this->error = $this->db->error();
6795 dol_syslog(get_class($this).
"::select Error ".$this->error, LOG_ERR);
6796 $this->db->rollback();
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.
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)
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid='', $f_user=null, $notrigger=0)
Delete all links between an object $this.
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.
fetch($rowid, $ref='', $ref_ext='', $notused='', $fetch_situation=false)
Get object from database.
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
getIdBillingContact()
Retourne id des contacts clients de facturation.
__construct(DoliDB $db)
Constructor.
const STATUS_DRAFT
Draft status.
setRetainedWarrantyDateLimit($timestamp, $dateYmd=false)
Change the retained_warranty_date_limit.
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.
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.
$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.
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.
set_remise_absolue($user, $remise, $notrigger=0)
Set absolute discount.
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...
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=0, $situation_percent=100, $fk_unit=null, $pu_ht_devise=0, $notrigger=0, $ref_ext='', $rang=0)
Update a detail line.
newCycle()
Gets the smallest reference available for a new cycle.
liste_array($shortlist=0, $draft=0, $excluser='', $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.
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')
Return next reference of customer invoice not already used (or last reference) according to numbering...
checkProgressLine($idline, $situation_percent)
Check if the percent edited is lower of next invoice line.
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='', $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=0, $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).
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 paid completely (if close_code is filled) => this->fk_statut=2,...
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.
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='', $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.
print $langs trans("Ref").' m m m statut
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 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
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