44require_once DOL_DOCUMENT_ROOT.
'/core/class/commoninvoice.class.php';
45require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobjectline.class.php';
46require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
47require_once DOL_DOCUMENT_ROOT.
'/societe/class/client.class.php';
48require_once DOL_DOCUMENT_ROOT.
'/margin/lib/margins.lib.php';
49require_once DOL_DOCUMENT_ROOT.
'/multicurrency/class/multicurrency.class.php';
51if (isModEnabled(
'accounting')) {
52 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formaccounting.class.php';
54if (isModEnabled(
'accounting')) {
55 require_once DOL_DOCUMENT_ROOT.
'/accountancy/class/accountingaccount.class.php';
66 public $element =
'facture';
71 public $table_element =
'facture';
76 public $table_element_line =
'facturedet';
81 public $class_element_line =
'FactureLigne';
86 public $fk_element =
'fk_facture';
91 public $picto =
'bill';
97 public $ismultientitymanaged = 1;
102 public $isextrafieldmanaged = 1;
108 public $restrictiononfksoc = 1;
127 public $fk_user_author;
139 public $fk_user_valid;
144 public $fk_user_modif;
151 public $delivery_date;
163 public $ref_customer;
167 public $total_localtax1;
168 public $total_localtax2;
170 public $revenuestamp;
187 public $linked_objects = array();
197 public $lines = array();
203 public $extraparams = array();
210 public $date_pointoftax;
216 public $situation_cycle_ref;
221 public $situation_counter;
226 public $situation_final;
231 public $tab_previous_situation_invoice = array();
236 public $tab_next_situation_invoice = array();
246 public $retained_warranty;
251 public $retained_warranty_date_limit;
256 public $retained_warranty_fk_cond_reglement;
261 public $availability_id;
263 public $date_closing;
273 public $remise_percent;
304 public $fields = array(
305 'rowid' =>array(
'type'=>
'integer',
'label'=>
'TechnicalID',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>1),
306 'ref' =>array(
'type'=>
'varchar(30)',
'label'=>
'Ref',
'enabled'=>1,
'visible'=>1,
'notnull'=>1,
'showoncombobox'=>1,
'position'=>5),
307 'entity' =>array(
'type'=>
'integer',
'label'=>
'Entity',
'default'=>1,
'enabled'=>1,
'visible'=>-2,
'notnull'=>1,
'position'=>20,
'index'=>1),
308 'ref_client' =>array(
'type'=>
'varchar(255)',
'label'=>
'RefCustomer',
'enabled'=>1,
'visible'=>-1,
'position'=>10),
309 'ref_ext' =>array(
'type'=>
'varchar(255)',
'label'=>
'Ref ext',
'enabled'=>1,
'visible'=>0,
'position'=>12),
310 'type' =>array(
'type'=>
'smallint(6)',
'label'=>
'Type',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>15),
311 'subtype' =>array(
'type'=>
'smallint(6)',
'label'=>
'InvoiceSubtype',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>15),
313 'fk_soc' =>array(
'type'=>
'integer:Societe:societe/class/societe.class.php',
'label'=>
'ThirdParty',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>50),
314 'datef' =>array(
'type'=>
'date',
'label'=>
'DateInvoice',
'enabled'=>1,
'visible'=>1,
'position'=>20),
315 'date_valid' =>array(
'type'=>
'date',
'label'=>
'DateValidation',
'enabled'=>1,
'visible'=>-1,
'position'=>22),
316 'date_lim_reglement' =>array(
'type'=>
'date',
'label'=>
'DateDue',
'enabled'=>1,
'visible'=>1,
'position'=>25),
317 'date_closing' =>array(
'type'=>
'datetime',
'label'=>
'Date closing',
'enabled'=>1,
'visible'=>-1,
'position'=>30),
318 'paye' =>array(
'type'=>
'smallint(6)',
'label'=>
'InvoicePaidCompletely',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>80),
323 'close_code' =>array(
'type'=>
'varchar(16)',
'label'=>
'EarlyClosingReason',
'enabled'=>1,
'visible'=>-1,
'position'=>92),
324 'close_note' =>array(
'type'=>
'varchar(128)',
'label'=>
'EarlyClosingComment',
'enabled'=>1,
'visible'=>-1,
'position'=>93),
325 'total_ht' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountHT',
'enabled'=>1,
'visible'=>1,
'position'=>95,
'isameasure'=>1),
326 'total_tva' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountVAT',
'enabled'=>1,
'visible'=>-1,
'position'=>100,
'isameasure'=>1),
327 'localtax1' =>array(
'type'=>
'double(24,8)',
'label'=>
'LT1',
'enabled'=>1,
'visible'=>-1,
'position'=>110,
'isameasure'=>1),
328 'localtax2' =>array(
'type'=>
'double(24,8)',
'label'=>
'LT2',
'enabled'=>1,
'visible'=>-1,
'position'=>120,
'isameasure'=>1),
329 'revenuestamp' =>array(
'type'=>
'double(24,8)',
'label'=>
'RevenueStamp',
'enabled'=>1,
'visible'=>-1,
'position'=>115,
'isameasure'=>1),
330 'total_ttc' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountTTC',
'enabled'=>1,
'visible'=>1,
'position'=>130,
'isameasure'=>1),
331 'fk_facture_source' =>array(
'type'=>
'integer',
'label'=>
'SourceInvoice',
'enabled'=>1,
'visible'=>-1,
'position'=>170),
332 'fk_projet' =>array(
'type'=>
'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)',
'label'=>
'Project',
'enabled'=>1,
'visible'=>-1,
'position'=>175),
333 'fk_account' =>array(
'type'=>
'integer',
'label'=>
'Fk account',
'enabled'=>1,
'visible'=>-1,
'position'=>180),
334 'fk_currency' =>array(
'type'=>
'varchar(3)',
'label'=>
'CurrencyCode',
'enabled'=>1,
'visible'=>-1,
'position'=>185),
335 'fk_cond_reglement' =>array(
'type'=>
'integer',
'label'=>
'PaymentTerm',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>190),
336 'fk_mode_reglement' =>array(
'type'=>
'integer',
'label'=>
'PaymentMode',
'enabled'=>1,
'visible'=>-1,
'position'=>195),
337 'note_private' =>array(
'type'=>
'html',
'label'=>
'NotePrivate',
'enabled'=>1,
'visible'=>0,
'position'=>205),
338 'note_public' =>array(
'type'=>
'html',
'label'=>
'NotePublic',
'enabled'=>1,
'visible'=>0,
'position'=>210),
339 'model_pdf' =>array(
'type'=>
'varchar(255)',
'label'=>
'Model pdf',
'enabled'=>1,
'visible'=>0,
'position'=>215),
340 'extraparams' =>array(
'type'=>
'varchar(255)',
'label'=>
'Extraparams',
'enabled'=>1,
'visible'=>-1,
'position'=>225),
341 'situation_cycle_ref' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation cycle ref',
'enabled'=>
'$conf->global->INVOICE_USE_SITUATION',
'visible'=>-1,
'position'=>230),
342 'situation_counter' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation counter',
'enabled'=>
'$conf->global->INVOICE_USE_SITUATION',
'visible'=>-1,
'position'=>235),
343 'situation_final' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation final',
'enabled'=>
'empty($conf->global->INVOICE_USE_SITUATION) ? 0 : 1',
'visible'=>-1,
'position'=>240),
344 'retained_warranty' =>array(
'type'=>
'double',
'label'=>
'Retained warranty',
'enabled'=>
'$conf->global->INVOICE_USE_RETAINED_WARRANTY',
'visible'=>-1,
'position'=>245),
345 'retained_warranty_date_limit' =>array(
'type'=>
'date',
'label'=>
'Retained warranty date limit',
'enabled'=>
'$conf->global->INVOICE_USE_RETAINED_WARRANTY',
'visible'=>-1,
'position'=>250),
346 'retained_warranty_fk_cond_reglement' =>array(
'type'=>
'integer',
'label'=>
'Retained warranty fk cond reglement',
'enabled'=>
'$conf->global->INVOICE_USE_RETAINED_WARRANTY',
'visible'=>-1,
'position'=>255),
347 'fk_incoterms' =>array(
'type'=>
'integer',
'label'=>
'IncotermCode',
'enabled'=>
'$conf->incoterm->enabled',
'visible'=>-1,
'position'=>260),
348 'location_incoterms' =>array(
'type'=>
'varchar(255)',
'label'=>
'IncotermLabel',
'enabled'=>
'$conf->incoterm->enabled',
'visible'=>-1,
'position'=>265),
349 'date_pointoftax' =>array(
'type'=>
'date',
'label'=>
'DatePointOfTax',
'enabled'=>
'$conf->global->INVOICE_POINTOFTAX_DATE',
'visible'=>-1,
'position'=>270),
350 'fk_multicurrency' =>array(
'type'=>
'integer',
'label'=>
'MulticurrencyID',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>275),
351 'multicurrency_code' =>array(
'type'=>
'varchar(255)',
'label'=>
'Currency',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>280),
352 'multicurrency_tx' =>array(
'type'=>
'double(24,8)',
'label'=>
'CurrencyRate',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>285,
'isameasure'=>1),
353 'multicurrency_total_ht' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountHT',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>290,
'isameasure'=>1),
354 'multicurrency_total_tva' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountVAT',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>291,
'isameasure'=>1),
355 'multicurrency_total_ttc' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountTTC',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>292,
'isameasure'=>1),
356 'fk_fac_rec_source' =>array(
'type'=>
'integer',
'label'=>
'RecurringInvoiceSource',
'enabled'=>1,
'visible'=>-1,
'position'=>305),
357 'last_main_doc' =>array(
'type'=>
'varchar(255)',
'label'=>
'LastMainDoc',
'enabled'=>1,
'visible'=>-1,
'position'=>310),
358 'module_source' =>array(
'type'=>
'varchar(32)',
'label'=>
'POSModule',
'enabled'=>
"(isModEnabled('cashdesk') || isModEnabled('takepos') || getDolGlobalInt('INVOICE_SHOW_POS'))",
'visible'=>-1,
'position'=>315),
359 'pos_source' =>array(
'type'=>
'varchar(32)',
'label'=>
'POSTerminal',
'enabled'=>
"(isModEnabled('cashdesk') || isModEnabled('takepos') || getDolGlobalInt('INVOICE_SHOW_POS'))",
'visible'=>-1,
'position'=>320),
360 'datec' =>array(
'type'=>
'datetime',
'label'=>
'DateCreation',
'enabled'=>1,
'visible'=>-1,
'position'=>500),
361 'tms' =>array(
'type'=>
'timestamp',
'label'=>
'DateModificationShort',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>502),
362 'fk_user_author' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserAuthor',
'enabled'=>1,
'visible'=>-1,
'position'=>506),
363 'fk_user_modif' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserModif',
'enabled'=>1,
'visible'=>-1,
'notnull'=>-1,
'position'=>508),
364 'fk_user_valid' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserValidation',
'enabled'=>1,
'visible'=>-1,
'position'=>510),
365 'fk_user_closing' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserClosing',
'enabled'=>1,
'visible'=>-1,
'position'=>512),
366 'import_key' =>array(
'type'=>
'varchar(14)',
'label'=>
'ImportId',
'enabled'=>1,
'visible'=>-2,
'position'=>900),
367 'fk_statut' =>array(
'type'=>
'smallint(6)',
'label'=>
'Status',
'enabled'=>1,
'visible'=>1,
'notnull'=>1,
'position'=>1000,
'arrayofkeyval'=>array(0=>
'Draft', 1=>
'Validated', 2=>
'Paid', 3=>
'Abandonned')),
429 const CLOSECODE_DISCOUNTVAT =
'discount_vat';
430 const CLOSECODE_BADDEBT =
'badcustomer';
431 const CLOSECODE_BANKCHARGE =
'bankcharge';
432 const CLOSECODE_OTHER =
'other';
434 const CLOSECODE_ABANDONED =
'abandon';
435 const CLOSECODE_REPLACED =
'replaced';
458 public function create(
User $user, $notrigger = 0, $forceduedate = 0)
460 global $langs, $conf, $mysoc, $hookmanager;
464 if (empty($this->
type)) {
468 $this->ref_client = trim($this->ref_client);
470 $this->note = (isset($this->note) ? trim($this->note) : trim($this->note_private));
471 $this->note_private = (isset($this->note_private) ? trim($this->note_private) :
'');
472 $this->note_public = (isset($this->note_public) ? trim($this->note_public) :
'');
473 if (!$this->cond_reglement_id) {
474 $this->cond_reglement_id = 0;
476 if (!$this->mode_reglement_id) {
477 $this->mode_reglement_id = 0;
482 if (!empty($this->multicurrency_code)) {
484 if (empty($this->multicurrency_tx)) {
492 $this->fk_multicurrency = 0;
494 if (empty($this->fk_multicurrency)) {
495 $this->multicurrency_code = $conf->currency;
496 $this->fk_multicurrency = 0;
497 $this->multicurrency_tx = 1;
500 dol_syslog(get_class($this).
"::create user=".$user->id.
" date=".$this->date);
503 if (empty($this->date)) {
504 $this->error =
"Try to create an invoice with an empty parameter (date)";
505 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
509 $result = $soc->fetch($this->socid);
511 $this->error =
"Failed to fetch company: ".$soc->error;
512 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
517 $this->date_creation = $now;
521 $originaldatewhen =
null;
522 $nextdatewhen =
null;
523 $previousdaynextdatewhen =
null;
526 if ($this->fac_rec > 0) {
527 $this->fk_fac_rec_source = $this->fac_rec;
529 require_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture-rec.class.php';
531 $result = $_facrec->fetch($this->fac_rec);
532 $result = $_facrec->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 0);
535 $originaldatewhen = $_facrec->date_when;
536 $nextdatewhen =
null;
537 $previousdaynextdatewhen =
null;
538 if ($originaldatewhen) {
539 $nextdatewhen =
dol_time_plus_duree($originaldatewhen, $_facrec->frequency, $_facrec->unit_frequency);
543 if (!empty($_facrec->frequency)) {
544 $this->socid = $_facrec->socid;
546 $this->entity = $_facrec->entity;
549 $this->fk_project =
GETPOST(
'projectid',
'int') > 0 ? ((int)
GETPOST(
'projectid',
'int')) : $_facrec->fk_project;
550 $this->note_public = GETPOSTISSET(
'note_public') ?
GETPOST(
'note_public',
'restricthtml') : $_facrec->note_public;
551 $this->note_private = GETPOSTISSET(
'note_private') ?
GETPOST(
'note_private',
'restricthtml') : $_facrec->note_private;
552 $this->model_pdf = GETPOSTISSET(
'model') ?
GETPOST(
'model',
'alpha') : $_facrec->model_pdf;
553 $this->cond_reglement_id =
GETPOST(
'cond_reglement_id',
'int') > 0 ? ((int)
GETPOST(
'cond_reglement_id',
'int')) : $_facrec->cond_reglement_id;
554 $this->mode_reglement_id =
GETPOST(
'mode_reglement_id',
'int') > 0 ? ((int)
GETPOST(
'mode_reglement_id',
'int')) : $_facrec->mode_reglement_id;
555 $this->fk_account =
GETPOST(
'fk_account') > 0 ? ((int)
GETPOST(
'fk_account')) : $_facrec->fk_account;
558 $this->total_ht = $_facrec->total_ht;
559 $this->total_ttc = $_facrec->total_ttc;
564 $this->fk_incoterms = $_facrec->fk_incoterms;
565 $this->location_incoterms = $_facrec->location_incoterms;
571 $this->ref_client = trim($this->ref_client);
572 $this->ref_customer = trim($this->ref_customer);
573 $this->note_public = trim($this->note_public);
574 $this->note_private = trim($this->note_private);
575 $this->note_private =
dol_concatdesc($this->note_private, $langs->trans(
"GeneratedFromRecurringInvoice", $_facrec->ref));
577 $this->array_options = $_facrec->array_options;
579 if (!$this->mode_reglement_id) {
580 $this->mode_reglement_id = 0;
585 $this->linked_objects = $_facrec->linkedObjectsIds;
590 if ($_facrec->frequency > 0) {
591 dol_syslog(
"This is a recurring invoice so we set date_last_gen and next date_when");
592 if (empty($_facrec->date_when)) {
593 $_facrec->date_when = $now;
595 $next_date = $_facrec->getNextDate();
596 $result = $_facrec->setValueFrom(
'date_last_gen', $now,
'',
null,
'date',
'', $user,
'');
598 $result = $_facrec->setNextDate($next_date, 1);
602 $outputlangs = $langs;
605 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && empty($newlang) && isset($this->thirdparty->default_lang)) {
606 $newlang = $this->thirdparty->default_lang;
608 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && empty($newlang) && isset($this->default_lang)) {
609 $newlang = $this->default_lang;
611 if (!empty($newlang)) {
613 $outputlangs->setDefaultLang($newlang);
619 $substitutionarray[
'__INVOICE_MONTH__'] =
dol_print_date($this->date,
'%m');
622 $substitutionarray[
'__INVOICE_MONTH_TEXT__'] =
dol_print_date($this->date,
'%B');
625 $substitutionarray[
'__INVOICE_YEAR__'] =
dol_print_date($this->date,
'%Y');
628 $substitutionarray[
'__INVOICE_DATE_NEXT_INVOICE_BEFORE_GEN__'] = (isset($originaldatewhen) ?
dol_print_date($originaldatewhen,
'dayhour') :
'');
629 $substitutionarray[
'__INVOICE_DATE_NEXT_INVOICE_AFTER_GEN__'] = (isset($nextdatewhen) ?
dol_print_date($nextdatewhen,
'dayhour') :
'');
630 $substitutionarray[
'__INVOICE_PREVIOUS_DATE_NEXT_INVOICE_AFTER_GEN__'] = (isset($previousdaynextdatewhen) ?
dol_print_date($previousdaynextdatewhen,
'dayhour') :
'');
631 $substitutionarray[
'__INVOICE_COUNTER_CURRENT__'] = $_facrec->nb_gen_done;
632 $substitutionarray[
'__INVOICE_COUNTER_MAX__'] = $_facrec->nb_gen_max;
643 if (empty($forceduedate)) {
649 $this->date_lim_reglement = $duedate;
651 $this->date_lim_reglement = $forceduedate;
655 $socid = $this->socid;
657 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"facture (";
666 $sql .=
", date_pointoftax";
667 $sql .=
", note_private";
668 $sql .=
", note_public";
669 $sql .=
", ref_client";
670 $sql .=
", fk_account";
671 $sql .=
", module_source, pos_source, fk_fac_rec_source, fk_facture_source, fk_user_author, fk_projet";
672 $sql .=
", fk_cond_reglement, fk_mode_reglement, date_lim_reglement, model_pdf";
673 $sql .=
", situation_cycle_ref, situation_counter, situation_final";
674 $sql .=
", fk_incoterms, location_incoterms";
675 $sql .=
", fk_multicurrency";
676 $sql .=
", multicurrency_code";
677 $sql .=
", multicurrency_tx";
678 $sql .=
", retained_warranty";
679 $sql .=
", retained_warranty_date_limit";
680 $sql .=
", retained_warranty_fk_cond_reglement";
684 $sql .=
", ".setEntity($this);
685 $sql .=
", ".($this->ref_ext ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
686 $sql .=
", '".$this->db->escape($this->
type).
"'";
687 $sql .=
", ".($this->subtype ?
"'".$this->db->escape($this->subtype).
"'" :
"null");
688 $sql .=
", ".((int) $socid);
689 $sql .=
", '".$this->db->idate($this->date_creation).
"'";
690 $sql .=
", '".$this->db->idate($this->date).
"'";
691 $sql .=
", ".(empty($this->date_pointoftax) ?
"null" :
"'".$this->db->idate($this->date_pointoftax).
"'");
692 $sql .=
", ".($this->note_private ?
"'".$this->db->escape($this->note_private).
"'" :
"null");
693 $sql .=
", ".($this->note_public ?
"'".$this->db->escape($this->note_public).
"'" :
"null");
694 $sql .=
", ".($this->ref_customer ?
"'".$this->db->escape($this->ref_customer).
"'" : ($this->ref_client ?
"'".$this->db->escape($this->ref_client).
"'" :
"null"));
695 $sql .=
", ".($this->fk_account > 0 ? $this->fk_account :
'NULL');
696 $sql .=
", ".($this->module_source ?
"'".$this->db->escape($this->module_source).
"'" :
"null");
697 $sql .=
", ".($this->pos_source !=
'' ?
"'".$this->db->escape($this->pos_source).
"'" :
"null");
698 $sql .=
", ".($this->fk_fac_rec_source ?
"'".$this->db->escape($this->fk_fac_rec_source).
"'" :
"null");
699 $sql .=
", ".($this->fk_facture_source ?
"'".$this->db->escape($this->fk_facture_source).
"'" :
"null");
700 $sql .=
", ".($user->id > 0 ? (int) $user->id :
"null");
701 $sql .=
", ".($this->fk_project ? $this->fk_project :
"null");
702 $sql .=
", ".((int) $this->cond_reglement_id);
703 $sql .=
", ".((int) $this->mode_reglement_id);
704 $sql .=
", '".$this->db->idate($this->date_lim_reglement).
"'";
705 $sql .=
", ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null");
706 $sql .=
", ".($this->situation_cycle_ref ?
"'".$this->db->escape($this->situation_cycle_ref).
"'" :
"null");
707 $sql .=
", ".($this->situation_counter ?
"'".$this->db->escape($this->situation_counter).
"'" :
"null");
708 $sql .=
", ".($this->situation_final ? $this->situation_final : 0);
709 $sql .=
", ".(int) $this->fk_incoterms;
710 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
711 $sql .=
", ".(int) $this->fk_multicurrency;
712 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
713 $sql .=
", ".(float) $this->multicurrency_tx;
714 $sql .=
", ".(empty($this->retained_warranty) ?
"0" : $this->db->escape($this->retained_warranty));
715 $sql .=
", ".(!empty($this->retained_warranty_date_limit) ?
"'".$this->db->idate($this->retained_warranty_date_limit).
"'" :
'NULL');
716 $sql .=
", ".(int) $this->retained_warranty_fk_cond_reglement;
719 $resql = $this->db->query($sql);
721 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
'facture');
724 $this->
ref =
'(PROV'.$this->id.
')';
725 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"facture SET ref='".$this->db->escape($this->
ref).
"' WHERE rowid=".((int) $this->
id);
727 $resql = $this->db->query($sql);
732 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {
733 $this->linked_objects = $this->linkedObjectsIds;
737 if (!$error && $this->
id && !empty($this->linked_objects) && is_array($this->linked_objects)) {
738 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
739 if (is_array($tmp_origin_id)) {
740 foreach ($tmp_origin_id as $origin_id) {
743 $this->error = $this->db->lasterror();
748 $origin_id = $tmp_origin_id;
751 $this->error = $this->db->lasterror();
759 if (!$error && $this->
id &&
getDolGlobalString(
'MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN') && !empty($this->origin) && !empty($this->origin_id)) {
760 $originforcontact = $this->origin;
761 $originidforcontact = $this->origin_id;
762 if ($originforcontact ==
'shipping') {
763 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expedition.class.php';
765 $exp->fetch($this->origin_id);
766 $exp->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 0);
767 if (count($exp->linkedObjectsIds[
'commande']) > 0) {
768 foreach ($exp->linkedObjectsIds[
'commande'] as $key => $value) {
769 $originforcontact =
'commande';
770 if (is_object($value)) {
771 $originidforcontact = $value->id;
773 $originidforcontact = $value;
780 $sqlcontact =
"SELECT ctc.code, ctc.source, ec.fk_socpeople FROM ".MAIN_DB_PREFIX.
"element_contact as ec, ".MAIN_DB_PREFIX.
"c_type_contact as ctc";
781 $sqlcontact .=
" WHERE element_id = ".((int) $originidforcontact).
" AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$this->db->escape($originforcontact).
"'";
783 $resqlcontact = $this->db->query($sqlcontact);
785 while ($objcontact = $this->db->fetch_object($resqlcontact)) {
787 $this->
add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source);
797 if (!$error && empty($this->fac_rec) && count($this->lines) && is_object($this->lines[0])) {
800 dol_syslog(
"There is ".count($this->lines).
" lines into ->lines that are InvoiceLines");
801 foreach ($this->lines as $i => $val) {
802 $newinvoiceline = $this->lines[$i];
804 $newinvoiceline->context = $this->context;
806 $newinvoiceline->fk_facture = $this->id;
808 $newinvoiceline->origin = $this->lines[$i]->element;
809 $newinvoiceline->origin_id = $this->lines[$i]->id;
812 if ($this->lines[$i]->date_start_fill == 1 && $originaldatewhen) {
813 $newinvoiceline->date_start = $originaldatewhen;
815 if ($this->lines[$i]->date_end_fill == 1 && $previousdaynextdatewhen) {
816 $newinvoiceline->date_end = $previousdaynextdatewhen;
821 if (($newinvoiceline->product_type != 9 && empty($newinvoiceline->fk_parent_line)) || $newinvoiceline->product_type == 9) {
826 $vatrate = $newinvoiceline->tva_tx;
827 if ($newinvoiceline->vat_src_code && ! preg_match(
'/\(.*\)/', $vatrate)) {
828 $vatrate.=
' ('.$newinvoiceline->vat_src_code.
')';
831 $newinvoiceline->fk_parent_line = $fk_parent_line;
835 $discount->fetch($newinvoiceline->fk_remise_except);
837 $discountId = $soc->set_remise_except($discount->amount_ht, $user, $discount->description, $discount->tva_tx);
838 $newinvoiceline->fk_remise_except = $discountId;
842 $newinvoiceline->desc,
843 $newinvoiceline->subprice,
844 $newinvoiceline->qty,
846 $newinvoiceline->localtax1_tx,
847 $newinvoiceline->localtax2_tx,
848 $newinvoiceline->fk_product,
849 $newinvoiceline->remise_percent,
850 $newinvoiceline->date_start,
851 $newinvoiceline->date_end,
852 $newinvoiceline->fk_code_ventilation,
853 $newinvoiceline->info_bits,
854 $newinvoiceline->fk_remise_except,
857 $newinvoiceline->product_type,
858 $newinvoiceline->rang,
859 $newinvoiceline->special_code,
860 $newinvoiceline->element,
863 $newinvoiceline->fk_fournprice,
864 $newinvoiceline->pa_ht,
865 $newinvoiceline->label,
866 $newinvoiceline->array_options,
867 $newinvoiceline->situation_percent,
868 $newinvoiceline->fk_prev_id,
869 $newinvoiceline->fk_unit,
870 $newinvoiceline->multicurrency_subprice,
871 $newinvoiceline->ref_ext,
876 if ($result > 0 && $newinvoiceline->product_type == 9) {
877 $fk_parent_line = $result;
881 $this->error = $newinvoiceline->error;
882 $this->errors = $newinvoiceline->errors;
887 } elseif (!$error && empty($this->fac_rec)) {
890 dol_syslog(
"There is ".count($this->lines).
" lines into ->lines as a simple array");
892 foreach ($this->lines as $i => $val) {
893 $line = $this->lines[$i];
897 if (!is_object($line)) {
898 $line = (object) $line;
903 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
908 $vatrate = $line->tva_tx;
909 if ($line->vat_src_code && !preg_match(
'/\(.*\)/', $vatrate)) {
910 $vatrate .=
' ('.$line->vat_src_code.
')';
914 $originid = $line->origin_id;
915 $origintype = $line->origin;
917 $originid = $line->id;
918 $origintype = $this->element;
922 if (empty($line->ref_ext)) {
934 $line->remise_percent,
937 $line->fk_code_ventilation,
939 $line->fk_remise_except,
948 $line->fk_fournprice,
951 $line->array_options,
952 $line->situation_percent,
955 $line->multicurrency_subprice,
960 $this->error = $this->db->lasterror();
962 $this->db->rollback();
967 if ($result > 0 && $line->product_type == 9) {
968 $fk_parent_line = $result;
977 if (!$error && $this->fac_rec > 0) {
978 dol_syslog(
"There is ".count($_facrec->lines).
" lines from recurring invoice");
981 foreach ($_facrec->lines as $i => $val) {
983 if (($_facrec->lines[$i]->product_type != 9 && empty($_facrec->lines[$i]->fk_parent_line)) || $_facrec->lines[$i]->product_type == 9) {
1000 $tva_tx = $_facrec->lines[$i]->tva_tx.($_facrec->lines[$i]->vat_src_code ?
'('.$_facrec->lines[$i]->vat_src_code.
')' :
'');
1001 $tva_npr = $_facrec->lines[$i]->info_bits;
1002 if (empty($tva_tx)) {
1005 $localtax1_tx = $_facrec->lines[$i]->localtax1_tx;
1006 $localtax2_tx = $_facrec->lines[$i]->localtax2_tx;
1008 $fk_product_fournisseur_price = empty($_facrec->lines[$i]->fk_product_fournisseur_price) ? null : $_facrec->lines[$i]->fk_product_fournisseur_price;
1009 $buyprice = empty($_facrec->lines[$i]->buyprice) ? 0 : $_facrec->lines[$i]->buyprice;
1012 if (!$buyprice && $_facrec->lines[$i]->fk_product > 0) {
1013 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
1015 $producttmp->fetch($_facrec->lines[$i]->fk_product);
1020 if (
getDolGlobalString(
'MARGIN_TYPE') ==
'costprice' && !empty($producttmp->cost_price)) {
1021 $buyprice = $producttmp->cost_price;
1023 $buyprice = $producttmp->pmp;
1025 if ($producttmp->find_min_price_product_fournisseur($_facrec->lines[$i]->fk_product) > 0) {
1026 if ($producttmp->product_fourn_price_id > 0) {
1027 $buyprice =
price2num($producttmp->fourn_unitprice * (1 - $producttmp->fourn_remise_percent / 100) + $producttmp->fourn_remise,
'MU');
1033 $result_insert = $this->
addline(
1034 $_facrec->lines[$i]->desc,
1035 $_facrec->lines[$i]->subprice,
1036 $_facrec->lines[$i]->qty,
1040 $_facrec->lines[$i]->fk_product,
1041 $_facrec->lines[$i]->remise_percent,
1042 ($_facrec->lines[$i]->date_start_fill == 1 && $originaldatewhen) ? $originaldatewhen :
'',
1043 ($_facrec->lines[$i]->date_end_fill == 1 && $previousdaynextdatewhen) ? $previousdaynextdatewhen :
'',
1049 $_facrec->lines[$i]->product_type,
1050 $_facrec->lines[$i]->rang,
1051 $_facrec->lines[$i]->special_code,
1055 $fk_product_fournisseur_price,
1057 $_facrec->lines[$i]->label,
1058 empty($_facrec->lines[$i]->array_options) ? null : $_facrec->lines[$i]->array_options,
1061 $_facrec->lines[$i]->fk_unit,
1062 $_facrec->lines[$i]->multicurrency_subprice,
1063 $_facrec->lines[$i]->ref_ext,
1068 if ($result_insert > 0 && $_facrec->lines[$i]->product_type == 9) {
1069 $fk_parent_line = $result_insert;
1072 if ($result_insert < 0) {
1074 $this->error = $this->db->error();
1093 if (!$error && !$notrigger) {
1103 $this->db->commit();
1106 $this->db->rollback();
1110 $this->error = $langs->trans(
'FailedToUpdatePrice');
1111 $this->db->rollback();
1115 dol_syslog(get_class($this).
"::create error ".$this->error, LOG_ERR);
1116 $this->db->rollback();
1120 $this->error = $this->db->error();
1121 $this->db->rollback();
1139 $facture =
new Facture($this->db);
1145 if (!empty($this->array_options)) {
1146 $facture->array_options = $this->array_options;
1149 foreach ($this->lines as &$line) {
1150 $line->fetch_optionals();
1154 $facture->type = $this->type;
1155 $facture->subtype = $this->subtype;
1156 $facture->socid = $this->socid;
1157 $facture->date = $this->date;
1158 $facture->date_pointoftax = $this->date_pointoftax;
1159 $facture->note_public = $this->note_public;
1160 $facture->note_private = $this->note_private;
1161 $facture->ref_client = $this->ref_client;
1162 $facture->model_pdf = $this->model_pdf;
1163 $facture->fk_project = $this->fk_project;
1164 $facture->cond_reglement_id = $this->cond_reglement_id;
1165 $facture->mode_reglement_id = $this->mode_reglement_id;
1169 $facture->origin = $this->origin;
1170 $facture->origin_id = $this->origin_id;
1171 $facture->fk_account = $this->fk_account;
1173 $facture->lines = $this->lines;
1174 $facture->situation_counter = $this->situation_counter;
1175 $facture->situation_cycle_ref = $this->situation_cycle_ref;
1176 $facture->situation_final = $this->situation_final;
1178 $facture->retained_warranty = $this->retained_warranty;
1179 $facture->retained_warranty_fk_cond_reglement = $this->retained_warranty_fk_cond_reglement;
1180 $facture->retained_warranty_date_limit = $this->retained_warranty_date_limit;
1182 $facture->fk_user_author = $user->id;
1186 foreach ($facture->lines as $i => $tmpline) {
1187 $facture->lines[$i]->fk_prev_id = $this->lines[$i]->rowid;
1188 if ($invertdetail) {
1189 $facture->lines[$i]->subprice = -$facture->lines[$i]->subprice;
1190 $facture->lines[$i]->total_ht = -$facture->lines[$i]->total_ht;
1191 $facture->lines[$i]->total_tva = -$facture->lines[$i]->total_tva;
1192 $facture->lines[$i]->total_localtax1 = -$facture->lines[$i]->total_localtax1;
1193 $facture->lines[$i]->total_localtax2 = -$facture->lines[$i]->total_localtax2;
1194 $facture->lines[$i]->total_ttc = -$facture->lines[$i]->total_ttc;
1195 $facture->lines[$i]->ref_ext =
'';
1199 dol_syslog(get_class($this).
"::createFromCurrent invertdetail=".$invertdetail.
" socid=".$this->socid.
" nboflines=".count($facture->lines));
1201 $facid = $facture->create($user);
1203 $this->error = $facture->error;
1204 $this->errors = $facture->errors;
1208 foreach ($this->linkedObjectsIds as $typeObject => $Tfk_object) {
1209 foreach ($Tfk_object as $fk_object) {
1210 $facture->add_object_linked($typeObject, $fk_object);
1214 $facture->add_object_linked(
'facture', $this->fk_facture_source);
1230 global $conf, $hookmanager;
1234 $object =
new Facture($this->db);
1238 $object->fetch($fromid);
1241 $objFrom = clone $object;
1244 if (!empty($this->socid) && $this->socid != $object->socid) {
1245 $objsoc =
new Societe($this->db);
1247 if ($objsoc->fetch($this->socid) > 0) {
1248 $object->socid = $objsoc->id;
1249 $object->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1250 $object->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1251 $object->fk_project =
null;
1252 $object->fk_delivery_address =
'';
1263 $object->date = (empty($this->date) ?
dol_now() : $this->date);
1264 $object->user_creation_id = $user->id;
1265 $object->user_validation_id =
null;
1266 $object->fk_user_author = $user->id;
1267 $object->fk_user_valid =
null;
1268 $object->fk_facture_source = 0;
1269 $object->fk_fac_rec_source =
null;
1270 $object->date_creation =
'';
1271 $object->date_modification =
'';
1272 $object->date_validation =
'';
1273 $object->ref_client =
'';
1274 $object->ref_customer =
'';
1275 $object->close_code =
'';
1276 $object->close_note =
'';
1278 $object->note_private =
'';
1279 $object->note_public =
'';
1283 foreach ($object->lines as $i => $line) {
1284 if (($object->lines[$i]->info_bits & 0x02) == 0x02) {
1285 unset($object->lines[$i]);
1291 if (
getDolGlobalString(
'INVOICE_AUTO_NEXT_MONTH_ON_LINES') && !empty($line->date_start) && !empty($line->date_end)) {
1303 if (
dol_mktime(0, 0, 0, $start[
'mon'], $start[
'mday'], $start[
'year'],
'gmt') == $first
1304 &&
dol_mktime(23, 59, 59, $end[
'mon'], $end[
'mday'], $end[
'year'],
'gmt') == $last) {
1308 $object->lines[$i]->date_start = $newFirst;
1309 $object->lines[$i]->date_end = $newLast;
1313 $object->lines[$i]->ref_ext =
'';
1317 $object->context[
'createfromclone'] =
'createfromclone';
1318 $result = $object->create($user);
1321 $this->error = $object->error;
1322 $this->errors = $object->errors;
1325 if ($object->copy_linked_contact($objFrom,
'internal') < 0) {
1327 $this->error = $object->error;
1328 $this->errors = $object->errors;
1329 } elseif ($object->socid == $objFrom->socid) {
1331 if ($object->copy_linked_contact($objFrom,
'external') < 0) {
1333 $this->error = $object->error;
1334 $this->errors = $object->errors;
1341 if (is_object($hookmanager)) {
1342 $parameters = array(
'objFrom'=>$objFrom);
1344 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $object, $action);
1352 unset($object->context[
'createfromclone']);
1356 $this->db->commit();
1359 $this->db->rollback();
1373 global $conf, $hookmanager;
1381 $num = count($object->lines);
1382 for ($i = 0; $i < $num; $i++) {
1385 $line->libelle = $object->lines[$i]->libelle;
1386 $line->label = $object->lines[$i]->label;
1387 $line->desc = $object->lines[$i]->desc;
1388 $line->subprice = $object->lines[$i]->subprice;
1389 $line->total_ht = $object->lines[$i]->total_ht;
1390 $line->total_tva = $object->lines[$i]->total_tva;
1391 $line->total_localtax1 = $object->lines[$i]->total_localtax1;
1392 $line->total_localtax2 = $object->lines[$i]->total_localtax2;
1393 $line->total_ttc = $object->lines[$i]->total_ttc;
1394 $line->vat_src_code = $object->lines[$i]->vat_src_code;
1395 $line->tva_tx = $object->lines[$i]->tva_tx;
1396 $line->localtax1_tx = $object->lines[$i]->localtax1_tx;
1397 $line->localtax2_tx = $object->lines[$i]->localtax2_tx;
1398 $line->qty = $object->lines[$i]->qty;
1399 $line->fk_remise_except = $object->lines[$i]->fk_remise_except;
1400 $line->remise_percent = $object->lines[$i]->remise_percent;
1401 $line->fk_product = $object->lines[$i]->fk_product;
1402 $line->info_bits = $object->lines[$i]->info_bits;
1403 $line->product_type = $object->lines[$i]->product_type;
1404 $line->rang = $object->lines[$i]->rang;
1405 $line->special_code = $object->lines[$i]->special_code;
1406 $line->fk_parent_line = $object->lines[$i]->fk_parent_line;
1407 $line->fk_unit = $object->lines[$i]->fk_unit;
1408 $line->date_start = $object->lines[$i]->date_start;
1409 $line->date_end = $object->lines[$i]->date_end;
1412 $line->fk_multicurrency = $object->lines[$i]->fk_multicurrency;
1413 $line->multicurrency_code = $object->lines[$i]->multicurrency_code;
1414 $line->multicurrency_subprice = $object->lines[$i]->multicurrency_subprice;
1415 $line->multicurrency_total_ht = $object->lines[$i]->multicurrency_total_ht;
1416 $line->multicurrency_total_tva = $object->lines[$i]->multicurrency_total_tva;
1417 $line->multicurrency_total_ttc = $object->lines[$i]->multicurrency_total_ttc;
1419 $line->fk_fournprice = $object->lines[$i]->fk_fournprice;
1420 $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);
1421 $line->pa_ht = $marginInfos[0];
1424 $object->lines[$i]->fetch_optionals();
1425 foreach ($object->lines[$i]->array_options as $options_key => $value) {
1426 $line->array_options[$options_key] = $value;
1429 $this->lines[$i] = $line;
1432 $this->socid = $object->socid;
1433 $this->fk_project = $object->fk_project;
1434 $this->fk_account = $object->fk_account;
1435 $this->cond_reglement_id = $object->cond_reglement_id;
1436 $this->mode_reglement_id = $object->mode_reglement_id;
1437 $this->availability_id = $object->availability_id;
1438 $this->demand_reason_id = $object->demand_reason_id;
1439 $this->delivery_date = $object->delivery_date;
1440 $this->fk_delivery_address = $object->fk_delivery_address;
1441 $this->contact_id = $object->contact_id;
1442 $this->ref_client = $object->ref_client;
1445 $this->note_private = $object->note_private;
1446 $this->note_public = $object->note_public;
1449 $this->module_source = $object->module_source;
1450 $this->pos_source = $object->pos_source;
1452 $this->origin = $object->element;
1453 $this->origin_id = $object->id;
1455 $this->fk_user_author = $user->id;
1458 $object->fetch_optionals();
1459 foreach ($object->array_options as $options_key => $value) {
1460 $this->array_options[$options_key] = $value;
1464 $this->linked_objects[$this->origin] = $this->origin_id;
1465 if (!empty($object->other_linked_objects) && is_array($object->other_linked_objects)) {
1466 $this->linked_objects = array_merge($this->linked_objects, $object->other_linked_objects);
1469 $ret = $this->
create($user);
1473 $hookmanager->initHooks(array(
'invoicedao'));
1475 $parameters = array(
'objFrom'=>$object);
1477 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $this, $action);
1503 global $conf, $hookmanager;
1511 $use_all_lines = empty($lines);
1512 $num = count($object->lines);
1513 for ($i = 0; $i < $num; $i++) {
1514 if (!$use_all_lines && !in_array($object->lines[$i]->id, $lines)) {
1520 $line->libelle = $object->lines[$i]->libelle;
1521 $line->label = $object->lines[$i]->label;
1522 $line->desc = $object->lines[$i]->desc;
1523 $line->subprice = $object->lines[$i]->subprice;
1524 $line->total_ht = $object->lines[$i]->total_ht;
1525 $line->total_tva = $object->lines[$i]->total_tva;
1526 $line->total_localtax1 = $object->lines[$i]->total_localtax1;
1527 $line->total_localtax2 = $object->lines[$i]->total_localtax2;
1528 $line->total_ttc = $object->lines[$i]->total_ttc;
1529 $line->vat_src_code = $object->lines[$i]->vat_src_code;
1530 $line->tva_tx = $object->lines[$i]->tva_tx;
1531 $line->localtax1_tx = $object->lines[$i]->localtax1_tx;
1532 $line->localtax2_tx = $object->lines[$i]->localtax2_tx;
1533 $line->qty = $object->lines[$i]->qty;
1534 $line->fk_remise_except = $object->lines[$i]->fk_remise_except;
1535 $line->remise_percent = $object->lines[$i]->remise_percent;
1536 $line->fk_product = $object->lines[$i]->fk_product;
1537 $line->info_bits = $object->lines[$i]->info_bits;
1538 $line->product_type = $object->lines[$i]->product_type;
1539 $line->rang = $object->lines[$i]->rang;
1540 $line->special_code = $object->lines[$i]->special_code;
1541 $line->fk_parent_line = $object->lines[$i]->fk_parent_line;
1542 $line->fk_unit = $object->lines[$i]->fk_unit;
1543 $line->date_start = $object->lines[$i]->date_start;
1544 $line->date_end = $object->lines[$i]->date_end;
1547 $line->fk_multicurrency = $object->lines[$i]->fk_multicurrency;
1548 $line->multicurrency_code = $object->lines[$i]->multicurrency_code;
1549 $line->multicurrency_subprice = $object->lines[$i]->multicurrency_subprice;
1550 $line->multicurrency_total_ht = $object->lines[$i]->multicurrency_total_ht;
1551 $line->multicurrency_total_tva = $object->lines[$i]->multicurrency_total_tva;
1552 $line->multicurrency_total_ttc = $object->lines[$i]->multicurrency_total_ttc;
1554 $line->fk_fournprice = $object->lines[$i]->fk_fournprice;
1555 $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);
1556 $line->pa_ht = $marginInfos[0];
1559 $object->lines[$i]->fetch_optionals();
1560 foreach ($object->lines[$i]->array_options as $options_key => $value) {
1561 $line->array_options[$options_key] = $value;
1564 $this->lines[$i] = $line;
1567 $this->socid = $object->socid;
1568 $this->fk_project = $object->fk_project;
1569 $this->fk_account = $object->fk_account;
1570 $this->cond_reglement_id = $object->cond_reglement_id;
1571 $this->mode_reglement_id = $object->mode_reglement_id;
1572 $this->availability_id = $object->availability_id;
1573 $this->demand_reason_id = $object->demand_reason_id;
1574 $this->delivery_date = $object->delivery_date;
1575 $this->fk_delivery_address = $object->fk_delivery_address;
1576 $this->contact_id = $object->contact_id;
1577 $this->ref_client = $object->ref_client;
1580 $this->note_private = $object->note_private;
1581 $this->note_public = $object->note_public;
1584 $this->module_source = $object->module_source;
1585 $this->pos_source = $object->pos_source;
1587 $this->origin = $object->element;
1588 $this->origin_id = $object->id;
1590 $this->fk_user_author = $user->id;
1593 $object->fetch_optionals();
1594 foreach ($object->array_options as $options_key => $value) {
1595 $this->array_options[$options_key] = $value;
1599 $this->linked_objects[$this->origin] = $this->origin_id;
1600 if (!empty($object->other_linked_objects) && is_array($object->other_linked_objects)) {
1601 $this->linked_objects = array_merge($this->linked_objects, $object->other_linked_objects);
1604 $ret = $this->
create($user);
1608 $hookmanager->initHooks(array(
'invoicedao'));
1610 $parameters = array(
'objFrom'=>$object);
1612 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $this, $action);
1642 global $conf, $langs, $hookmanager, $action;
1644 if (! in_array($origin->element, array(
'propal',
'commande'))) {
1645 $origin->error =
'ErrorCanOnlyAutomaticallyGenerateADepositFromProposalOrOrder';
1650 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'DateInvoice'));
1654 require_once DOL_DOCUMENT_ROOT .
'/core/lib/date.lib.php';
1657 $origin->error =
'ErrorDateIsInFuture';
1661 if ($payment_terms_id <= 0) {
1662 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'PaymentConditionsShort'));
1666 $payment_conditions_deposit_percent =
getDictionaryValue(
'c_payment_term',
'deposit_percent', $origin->cond_reglement_id);
1668 if (empty($payment_conditions_deposit_percent)) {
1669 $origin->error =
'ErrorPaymentConditionsNotEligibleToDepositCreation';
1673 if (empty($origin->deposit_percent)) {
1674 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'DepositPercent'));
1678 $deposit =
new self($origin->db);
1679 $deposit->socid = $origin->socid;
1681 $deposit->fk_project = $origin->fk_project;
1682 $deposit->ref_client = $origin->ref_client;
1683 $deposit->date = $date;
1684 $deposit->mode_reglement_id = $origin->mode_reglement_id;
1685 $deposit->cond_reglement_id = $payment_terms_id;
1686 $deposit->availability_id = $origin->availability_id;
1687 $deposit->demand_reason_id = $origin->demand_reason_id;
1688 $deposit->fk_account = $origin->fk_account;
1689 $deposit->fk_incoterms = $origin->fk_incoterms;
1690 $deposit->location_incoterms = $origin->location_incoterms;
1691 $deposit->fk_multicurrency = $origin->fk_multicurrency;
1692 $deposit->multicurrency_code = $origin->multicurrency_code;
1693 $deposit->multicurrency_tx = $origin->multicurrency_tx;
1694 $deposit->module_source = $origin->module_source;
1695 $deposit->pos_source = $origin->pos_source;
1696 $deposit->model_pdf =
'crabe';
1698 $modelByTypeConfName =
'FACTURE_ADDON_PDF_' . $deposit->type;
1707 $deposit->note_private = $origin->note_private;
1708 $deposit->note_public = $origin->note_public;
1711 $deposit->origin = $origin->element;
1712 $deposit->origin_id = $origin->id;
1714 $origin->fetch_optionals();
1716 foreach ($origin->array_options as $extrakey => $value) {
1717 $deposit->array_options[$extrakey] = $value;
1720 $deposit->linked_objects[$deposit->origin] = $deposit->origin_id;
1722 foreach ($overrideFields as $key => $value) {
1723 $deposit->$key = $value;
1726 $deposit->context[
'createdepositfromorigin'] =
'createdepositfromorigin';
1728 $origin->db->begin();
1731 $createReturn = $deposit->create($user, $notrigger);
1733 if ($createReturn <= 0) {
1734 $origin->db->rollback();
1735 $origin->error = $deposit->error;
1736 $origin->errors = $deposit->errors;
1740 $amount_ttc_diff = 0;
1741 $amountdeposit = array();
1742 $descriptions = array();
1745 $amount = $origin->total_ttc * ($origin->deposit_percent / 100);
1747 $TTotalByTva = array();
1748 foreach ($origin->lines as &$line) {
1749 if (!empty($line->special_code)) {
1752 $TTotalByTva[$line->tva_tx] += $line->total_ttc;
1753 $descriptions[$line->tva_tx] .=
'<li>' . (!empty($line->product_ref) ? $line->product_ref .
' - ' :
'');
1754 $descriptions[$line->tva_tx] .= (!empty($line->product_label) ? $line->product_label .
' - ' :
'');
1755 $descriptions[$line->tva_tx] .= $langs->trans(
'Qty') .
' : ' . $line->qty;
1756 $descriptions[$line->tva_tx] .=
' - ' . $langs->trans(
'TotalHT') .
' : ' .
price($line->total_ht) .
'</li>';
1759 foreach ($TTotalByTva as $tva => &$total) {
1760 $coef = $total / $origin->total_ttc;
1761 $am = $amount * $coef;
1762 $amount_ttc_diff += $am;
1763 $amountdeposit[$tva] += $am / (1 + $tva / 100);
1767 $lines = $origin->lines;
1768 $numlines = count($lines);
1769 for ($i = 0; $i < $numlines; $i++) {
1770 if (empty($lines[$i]->qty)) {
1773 if (!empty($lines[$i]->special_code)) {
1777 $totalamount += $lines[$i]->total_ht;
1778 $tva_tx = $lines[$i]->tva_tx;
1779 $amountdeposit[$tva_tx] += ($lines[$i]->total_ht * $origin->deposit_percent) / 100;
1780 $descriptions[$tva_tx] .=
'<li>' . (!empty($lines[$i]->product_ref) ? $lines[$i]->product_ref .
' - ' :
'');
1781 $descriptions[$tva_tx] .= (!empty($lines[$i]->product_label) ? $lines[$i]->product_label .
' - ' :
'');
1782 $descriptions[$tva_tx] .= $langs->trans(
'Qty') .
' : ' . $lines[$i]->qty;
1783 $descriptions[$tva_tx] .=
' - ' . $langs->trans(
'TotalHT') .
' : ' .
price($lines[$i]->total_ht) .
'</li>';
1786 if ($totalamount == 0) {
1787 $amountdeposit[0] = 0;
1790 $amount_ttc_diff = $amountdeposit[0];
1793 foreach ($amountdeposit as $tva => $amount) {
1794 if (empty($amount)) {
1798 $descline =
'(DEPOSIT) ('. $origin->deposit_percent .
'%) - '.$origin->ref;
1801 if (
getDolGlobalString(
'INVOICE_DEPOSIT_VARIABLE_MODE_DETAIL_LINES_IN_DESCRIPTION') && !empty($descriptions[$tva])) {
1802 $descline .=
'<ul>' . $descriptions[$tva] .
'</ul>';
1805 $addlineResult = $deposit->addline(
1812 (!
getDolGlobalString(
'INVOICE_PRODUCTID_DEPOSIT') ? 0 : $conf->global->INVOICE_PRODUCTID_DEPOSIT),
1832 if ($addlineResult < 0) {
1833 $origin->db->rollback();
1834 $origin->error = $deposit->error;
1835 $origin->errors = $deposit->errors;
1840 $diff = $deposit->total_ttc - $amount_ttc_diff;
1843 $deposit->fetch_lines();
1844 $subprice_diff = $deposit->lines[0]->subprice - $diff / (1 + $deposit->lines[0]->tva_tx / 100);
1846 $updatelineResult = $deposit->updateline(
1847 $deposit->lines[0]->id,
1848 $deposit->lines[0]->desc,
1850 $deposit->lines[0]->qty,
1851 $deposit->lines[0]->remise_percent,
1852 $deposit->lines[0]->date_start,
1853 $deposit->lines[0]->date_end,
1854 $deposit->lines[0]->tva_tx,
1858 $deposit->lines[0]->info_bits,
1859 $deposit->lines[0]->product_type,
1863 $deposit->lines[0]->pa_ht,
1864 $deposit->lines[0]->label,
1870 if ($updatelineResult < 0) {
1871 $origin->db->rollback();
1872 $origin->error = $deposit->error;
1873 $origin->errors = $deposit->errors;
1878 $hookmanager->initHooks(array(
'invoicedao'));
1880 $parameters = array(
'objFrom' => $origin);
1881 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $deposit, $action);
1884 $origin->db->rollback();
1885 $origin->error = $hookmanager->error;
1886 $origin->errors = $hookmanager->errors;
1890 if (!empty($autoValidateDeposit)) {
1891 $validateReturn = $deposit->validate($user,
'', 0, $notrigger);
1893 if ($validateReturn < 0) {
1894 $origin->db->rollback();
1895 $origin->error = $deposit->error;
1896 $origin->errors = $deposit->errors;
1901 unset($deposit->context[
'createdepositfromorigin']);
1903 $origin->db->commit();
1917 global $conf, $langs, $mysoc, $user;
1919 $langs->load(
'bills');
1922 $moretitle = $params[
'moretitle'] ??
'';
1923 $picto = $this->picto;
1924 if ($this->
type == self::TYPE_REPLACEMENT) {
1927 if ($this->
type == self::TYPE_CREDIT_NOTE) {
1930 if ($this->
type == self::TYPE_DEPOSIT) {
1934 if ($user->hasRight(
"facture",
"read")) {
1935 $datas[
'picto'] =
img_picto(
'', $picto).
' <u class="paddingrightonly">'.$langs->trans(
"Invoice").
'</u>';
1937 $datas[
'picto'] .=
' '.$this->getLibType(1);
1940 if (!empty($params[
'fromajaxtooltip']) && !isset($this->alreadypaid)) {
1944 if (isset($this->
status) && isset($this->alreadypaid)) {
1945 $datas[
'picto'] .=
' '.$this->getLibStatut(5, $this->alreadypaid);
1948 $datas[
'picto'] .=
' - '.$moretitle;
1950 if (!empty($this->
ref)) {
1951 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
1953 if (!empty($this->ref_customer)) {
1954 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.$this->ref_customer;
1956 if (!empty($this->date)) {
1957 $datas[
'date'] =
'<br><b>'.$langs->trans(
'Date').
':</b> '.
dol_print_date($this->date,
'day');
1959 if (!empty($this->total_ht)) {
1960 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
1962 if (!empty($this->total_tva)) {
1963 $datas[
'amountvat'] =
'<br><b>'.$langs->trans(
'AmountVAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
1965 if (!empty($this->revenuestamp) && $this->revenuestamp != 0) {
1966 $datas[
'amountrevenustamp'] =
'<br><b>'.$langs->trans(
'RevenueStamp').
':</b> '.
price($this->revenuestamp, 0, $langs, 0, -1, -1, $conf->currency);
1968 if (!empty($this->total_localtax1) && $this->total_localtax1 != 0) {
1970 $datas[
'amountlt1'] =
'<br><b>'.$langs->transcountry(
'AmountLT1', $mysoc->country_code).
':</b> '.
price($this->total_localtax1, 0, $langs, 0, -1, -1, $conf->currency);
1972 if (!empty($this->total_localtax2) && $this->total_localtax2 != 0) {
1973 $datas[
'amountlt2'] =
'<br><b>'.$langs->transcountry(
'AmountLT2', $mysoc->country_code).
':</b> '.
price($this->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency);
1975 if (!empty($this->total_ttc)) {
1976 $datas[
'amountttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
1997 public function getNomUrl($withpicto = 0, $option =
'', $max = 0, $short = 0, $moretitle =
'', $notooltip = 0, $addlinktonotes = 0, $save_lastsearch_value = -1, $target =
'')
1999 global $langs, $conf, $user, $mysoc;
2001 if (!empty($conf->dol_no_mouse_hover)) {
2007 if ($option ==
'withdraw') {
2008 $url = DOL_URL_ROOT.
'/compta/facture/prelevement.php?facid='.$this->id;
2010 $url = DOL_URL_ROOT.
'/compta/facture/card.php?facid='.$this->id;
2013 if (!$user->hasRight(
"facture",
"read")) {
2017 if ($option !==
'nolink') {
2019 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2020 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
2021 $add_save_lastsearch_values = 1;
2023 if ($add_save_lastsearch_values) {
2024 $url .=
'&save_lastsearch_values=1';
2032 $picto = $this->picto;
2033 if ($this->
type == self::TYPE_REPLACEMENT) {
2036 if ($this->
type == self::TYPE_CREDIT_NOTE) {
2039 if ($this->
type == self::TYPE_DEPOSIT) {
2044 'objecttype' => $this->element,
2045 'moretitle' => $moretitle,
2046 'option' => $option,
2048 $classfortooltip =
'classfortooltip';
2051 $classfortooltip =
'classforajaxtooltip';
2052 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
2058 $linkclose = ($target ?
' target="'.$target.
'"' :
'');
2059 if (empty($notooltip) && $user->hasRight(
"facture",
"read")) {
2061 $label = $langs->trans(
"Invoice");
2062 $linkclose .=
' alt="'.dol_escape_htmltag($label, 1).
'"';
2064 $linkclose .= ($label ?
' title="'.dol_escape_htmltag($label, 1).
'"' :
' title="tocomplete"');
2065 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
2068 $linkstart =
'<a href="'.$url.
'"';
2069 $linkstart .= $linkclose.
'>';
2072 if ($option ==
'nolink') {
2077 $result .= $linkstart;
2079 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), ($notooltip ? (($withpicto != 2) ?
'class="paddingright"' :
'') :
'class="'.(($withpicto != 2) ?
'paddingright ' :
'').
'"'), 0, 0, $notooltip ? 0 : 1);
2081 if ($withpicto != 2) {
2082 $result .= ($max ?
dol_trunc($this->
ref, $max) : $this->ref);
2084 $result .= $linkend;
2086 if ($addlinktonotes) {
2087 $txttoshow = ($user->socid > 0 ? $this->note_public : $this->note_private);
2090 $notetoshow = $langs->trans(
"ViewPrivateNote").
':<br>'.$txttoshow;
2091 $result .=
' <span class="note inline-block">';
2092 $result .=
'<a href="'.DOL_URL_ROOT.
'/compta/facture/note.php?id='.$this->
id.
'" class="classfortooltip" title="'.
dol_escape_htmltag($notetoshow, 1, 1).
'">';
2097 $result .=
'</span>';
2101 global $action, $hookmanager;
2102 $hookmanager->initHooks(array(
'invoicedao'));
2103 $parameters = array(
'id'=>$this->
id,
'getnomurl' => &$result,
'notooltip' => $notooltip,
'addlinktonotes' => $addlinktonotes,
'save_lastsearch_value'=> $save_lastsearch_value,
'target' => $target);
2104 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
2106 $result = $hookmanager->resPrint;
2108 $result .= $hookmanager->resPrint;
2124 public function fetch($rowid, $ref =
'', $ref_ext =
'', $notused = 0, $fetch_situation =
false)
2126 if (empty($rowid) && empty($ref) && empty($ref_ext)) {
2130 $sql =
'SELECT f.rowid, f.entity, f.ref, f.ref_client, f.ref_ext, f.type, f.subtype, f.fk_soc';
2131 $sql .=
', f.total_tva, f.localtax1, f.localtax2, f.total_ht, f.total_ttc, f.revenuestamp';
2132 $sql .=
', f.datef as df, f.date_pointoftax';
2133 $sql .=
', f.date_lim_reglement as dlr';
2134 $sql .=
', f.datec as datec';
2135 $sql .=
', f.date_valid as datev';
2136 $sql .=
', f.tms as datem';
2137 $sql .=
', f.note_private, f.note_public, f.fk_statut as status, f.paye, f.close_code, f.close_note, f.fk_user_author, f.fk_user_valid, f.fk_user_modif, f.model_pdf, f.last_main_doc';
2138 $sql .=
', f.fk_facture_source, f.fk_fac_rec_source';
2139 $sql .=
', f.fk_mode_reglement, f.fk_cond_reglement, f.fk_projet as fk_project, f.extraparams';
2140 $sql .=
', f.situation_cycle_ref, f.situation_counter, f.situation_final';
2141 $sql .=
', f.fk_account';
2142 $sql .=
", f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc";
2143 $sql .=
', p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
2144 $sql .=
', c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_doc';
2145 $sql .=
', f.fk_incoterms, f.location_incoterms';
2146 $sql .=
', f.module_source, f.pos_source';
2147 $sql .=
", i.libelle as label_incoterms";
2148 $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";
2149 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facture as f';
2150 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_payment_term as c ON f.fk_cond_reglement = c.rowid';
2151 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_paiement as p ON f.fk_mode_reglement = p.id';
2152 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON f.fk_incoterms = i.rowid';
2155 $sql .=
" WHERE f.rowid = ".((int) $rowid);
2157 $sql .=
' WHERE f.entity IN ('.getEntity(
'invoice').
')';
2159 $sql .=
" AND f.ref = '".$this->db->escape($ref).
"'";
2162 $sql .=
" AND f.ref_ext = '".$this->db->escape($ref_ext).
"'";
2166 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
2167 $resql = $this->db->query($sql);
2169 if ($this->db->num_rows($resql)) {
2170 $obj = $this->db->fetch_object($resql);
2172 $this->
id = $obj->rowid;
2173 $this->entity = $obj->entity;
2175 $this->
ref = $obj->ref;
2176 $this->ref_client = $obj->ref_client;
2177 $this->ref_customer = $obj->ref_client;
2178 $this->ref_ext = $obj->ref_ext;
2179 $this->
type = $obj->type;
2180 $this->subtype = $obj->subtype;
2181 $this->date = $this->db->jdate($obj->df);
2182 $this->date_pointoftax = $this->db->jdate($obj->date_pointoftax);
2183 $this->date_creation = $this->db->jdate($obj->datec);
2184 $this->date_validation = $this->db->jdate($obj->datev);
2185 $this->date_modification = $this->db->jdate($obj->datem);
2186 $this->datem = $this->db->jdate($obj->datem);
2187 $this->total_ht = $obj->total_ht;
2188 $this->total_tva = $obj->total_tva;
2189 $this->total_localtax1 = $obj->localtax1;
2190 $this->total_localtax2 = $obj->localtax2;
2191 $this->total_ttc = $obj->total_ttc;
2192 $this->revenuestamp = $obj->revenuestamp;
2193 $this->paye = $obj->paye;
2194 $this->close_code = $obj->close_code;
2195 $this->close_note = $obj->close_note;
2197 $this->socid = $obj->fk_soc;
2198 $this->thirdparty =
null;
2200 $this->fk_project = $obj->fk_project;
2201 $this->project =
null;
2203 $this->
statut = $obj->status;
2204 $this->
status = $obj->status;
2206 $this->date_lim_reglement = $this->db->jdate($obj->dlr);
2207 $this->mode_reglement_id = $obj->fk_mode_reglement;
2208 $this->mode_reglement_code = $obj->mode_reglement_code;
2209 $this->mode_reglement = $obj->mode_reglement_libelle;
2210 $this->cond_reglement_id = $obj->fk_cond_reglement;
2211 $this->cond_reglement_code = $obj->cond_reglement_code;
2212 $this->cond_reglement = $obj->cond_reglement_libelle;
2213 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
2214 $this->fk_account = ($obj->fk_account > 0) ? $obj->fk_account :
null;
2215 $this->fk_facture_source = $obj->fk_facture_source;
2216 $this->fk_fac_rec_source = $obj->fk_fac_rec_source;
2217 $this->note = $obj->note_private;
2218 $this->note_private = $obj->note_private;
2219 $this->note_public = $obj->note_public;
2220 $this->user_creation_id = $obj->fk_user_author;
2221 $this->user_validation_id = $obj->fk_user_valid;
2222 $this->user_modification_id = $obj->fk_user_modif;
2223 $this->fk_user_author = $obj->fk_user_author;
2224 $this->fk_user_valid = $obj->fk_user_valid;
2225 $this->fk_user_modif = $obj->fk_user_modif;
2226 $this->model_pdf = $obj->model_pdf;
2227 $this->last_main_doc = $obj->last_main_doc;
2228 $this->situation_cycle_ref = $obj->situation_cycle_ref;
2229 $this->situation_counter = $obj->situation_counter;
2230 $this->situation_final = $obj->situation_final;
2231 $this->retained_warranty = $obj->retained_warranty;
2232 $this->retained_warranty_date_limit = $this->db->jdate($obj->retained_warranty_date_limit);
2233 $this->retained_warranty_fk_cond_reglement = $obj->retained_warranty_fk_cond_reglement;
2235 $this->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
2238 $this->fk_incoterms = $obj->fk_incoterms;
2239 $this->location_incoterms = $obj->location_incoterms;
2240 $this->label_incoterms = $obj->label_incoterms;
2242 $this->module_source = $obj->module_source;
2243 $this->pos_source = $obj->pos_source;
2246 $this->fk_multicurrency = $obj->fk_multicurrency;
2247 $this->multicurrency_code = $obj->multicurrency_code;
2248 $this->multicurrency_tx = $obj->multicurrency_tx;
2249 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
2250 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
2251 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
2253 if (($this->
type == self::TYPE_SITUATION || ($this->
type == self::TYPE_CREDIT_NOTE && $this->situation_cycle_ref > 0)) && $fetch_situation) {
2262 $this->lines = array();
2266 $this->error = $this->db->error();
2270 $this->db->free($resql);
2274 $this->error =
'Invoice with id='.$rowid.
' or ref='.$ref.
' or ref_ext='.$ref_ext.
' not found';
2276 dol_syslog(__METHOD__.$this->error, LOG_WARNING);
2280 $this->error = $this->db->lasterror();
2295 public function fetch_lines($only_product = 0, $loadalsotranslation = 0)
2298 $this->lines = array();
2300 $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,';
2301 $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,';
2302 $sql .=
' l.situation_percent, l.fk_prev_id,';
2303 $sql .=
' l.rang, l.special_code, l.batch, l.fk_warehouse,';
2304 $sql .=
' l.date_start as date_start, l.date_end as date_end,';
2305 $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,';
2306 $sql .=
' l.fk_unit,';
2307 $sql .=
' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
2308 $sql .=
' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc, p.barcode as product_barcode';
2309 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facturedet as l';
2310 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON l.fk_product = p.rowid';
2311 $sql .=
' WHERE l.fk_facture = '.((int) $this->
id);
2312 $sql .=
' ORDER BY l.rang, l.rowid';
2314 dol_syslog(get_class($this).
'::fetch_lines', LOG_DEBUG);
2315 $result = $this->db->query($sql);
2317 $num = $this->db->num_rows($result);
2320 $objp = $this->db->fetch_object($result);
2323 $line->id = $objp->rowid;
2324 $line->rowid = $objp->rowid;
2325 $line->fk_facture = $objp->fk_facture;
2326 $line->label = $objp->custom_label;
2327 $line->desc = $objp->description;
2328 $line->description = $objp->description;
2329 $line->product_type = $objp->product_type;
2330 $line->ref = $objp->product_ref;
2331 $line->product_ref = $objp->product_ref;
2332 $line->libelle = $objp->product_label;
2333 $line->product_label = $objp->product_label;
2334 $line->product_barcode = $objp->product_barcode;
2335 $line->product_desc = $objp->product_desc;
2336 $line->fk_product_type = $objp->fk_product_type;
2337 $line->qty = $objp->qty;
2338 $line->subprice = $objp->subprice;
2339 $line->ref_ext = $objp->ref_ext;
2341 $line->vat_src_code = $objp->vat_src_code;
2342 $line->tva_tx = $objp->tva_tx;
2343 $line->localtax1_tx = $objp->localtax1_tx;
2344 $line->localtax2_tx = $objp->localtax2_tx;
2345 $line->localtax1_type = $objp->localtax1_type;
2346 $line->localtax2_type = $objp->localtax2_type;
2347 $line->remise_percent = $objp->remise_percent;
2348 $line->fk_remise_except = $objp->fk_remise_except;
2349 $line->fk_product = $objp->fk_product;
2350 $line->date_start = $this->db->jdate($objp->date_start);
2351 $line->date_end = $this->db->jdate($objp->date_end);
2352 $line->info_bits = $objp->info_bits;
2353 $line->total_ht = $objp->total_ht;
2354 $line->total_tva = $objp->total_tva;
2355 $line->total_localtax1 = $objp->total_localtax1;
2356 $line->total_localtax2 = $objp->total_localtax2;
2357 $line->total_ttc = $objp->total_ttc;
2359 $line->code_ventilation = $objp->fk_code_ventilation;
2360 $line->fk_fournprice = $objp->fk_fournprice;
2361 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
2362 $line->pa_ht = $marginInfos[0];
2363 $line->marge_tx = $marginInfos[1];
2364 $line->marque_tx = $marginInfos[2];
2365 $line->rang = $objp->rang;
2366 $line->special_code = $objp->special_code;
2367 $line->fk_parent_line = $objp->fk_parent_line;
2368 $line->situation_percent = $objp->situation_percent;
2369 $line->fk_prev_id = $objp->fk_prev_id;
2370 $line->fk_unit = $objp->fk_unit;
2372 $line->batch = $objp->batch;
2373 $line->fk_warehouse = $objp->fk_warehouse;
2376 $line->fk_accounting_account = $objp->fk_code_ventilation;
2379 $line->fk_multicurrency = $objp->fk_multicurrency;
2380 $line->multicurrency_code = $objp->multicurrency_code;
2381 $line->multicurrency_subprice = $objp->multicurrency_subprice;
2382 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
2383 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
2384 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
2386 $line->fetch_optionals();
2389 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
2390 $tmpproduct =
new Product($this->db);
2391 $tmpproduct->fetch($objp->fk_product);
2392 $tmpproduct->getMultiLangs();
2394 $line->multilangs = $tmpproduct->multilangs;
2397 $this->lines[$i] = $line;
2401 $this->db->free($result);
2404 $this->error = $this->db->error();
2419 $this->tab_previous_situation_invoice = array();
2420 $this->tab_next_situation_invoice = array();
2422 $sql =
'SELECT rowid, type, situation_cycle_ref, situation_counter FROM '.MAIN_DB_PREFIX.
'facture';
2423 $sql .=
" WHERE rowid <> ".((int) $this->
id);
2424 $sql .=
' AND entity = '.((int) $this->entity);
2425 $sql .=
' AND situation_cycle_ref = '.(int) $this->situation_cycle_ref;
2426 $sql .=
' ORDER BY situation_counter ASC';
2428 dol_syslog(get_class($this).
'::fetchPreviousNextSituationInvoice ', LOG_DEBUG);
2429 $result = $this->db->query($sql);
2430 if ($result && $this->db->num_rows($result) > 0) {
2431 while ($objp = $this->db->fetch_object($result)) {
2432 $invoice =
new Facture($this->db);
2433 if ($invoice->fetch($objp->rowid) > 0) {
2434 if ($objp->situation_counter < $this->situation_counter
2435 || ($objp->situation_counter == $this->situation_counter && $objp->rowid < $this->id)
2437 $this->tab_previous_situation_invoice[] = $invoice;
2439 $this->tab_next_situation_invoice[] = $invoice;
2458 if (empty($this->
type)) {
2461 if (isset($this->
ref)) {
2462 $this->
ref = trim($this->
ref);
2464 if (isset($this->ref_ext)) {
2465 $this->ref_ext = trim($this->ref_ext);
2467 if (isset($this->ref_client)) {
2468 $this->ref_client = trim($this->ref_client);
2470 if (isset($this->increment)) {
2471 $this->increment = trim($this->increment);
2473 if (isset($this->close_code)) {
2474 $this->close_code = trim($this->close_code);
2476 if (isset($this->close_note)) {
2477 $this->close_note = trim($this->close_note);
2479 if (isset($this->note) || isset($this->note_private)) {
2480 $this->note = (isset($this->note) ? trim($this->note) : trim($this->note_private));
2482 if (isset($this->note) || isset($this->note_private)) {
2483 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note));
2485 if (isset($this->note_public)) {
2486 $this->note_public = trim($this->note_public);
2488 if (isset($this->model_pdf)) {
2489 $this->model_pdf = trim($this->model_pdf);
2491 if (isset($this->import_key)) {
2492 $this->import_key = trim($this->import_key);
2494 if (isset($this->retained_warranty)) {
2495 $this->retained_warranty = (float) $this->retained_warranty;
2497 if (!isset($this->fk_user_author) && isset($this->user_author) ) {
2498 $this->fk_user_author = $this->user_author;
2506 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facture SET";
2507 $sql .=
" ref=".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
2508 $sql .=
" ref_ext=".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
2509 $sql .=
" type=".(isset($this->
type) ? $this->db->escape($this->
type) :
"null").
",";
2510 $sql .=
" subtype=".(isset($this->subtype) ? $this->db->escape($this->subtype) :
"null").
",";
2511 $sql .=
" ref_client=".(isset($this->ref_client) ?
"'".$this->db->escape($this->ref_client).
"'" :
"null").
",";
2512 $sql .=
" increment=".(isset($this->increment) ?
"'".$this->db->escape($this->increment).
"'" :
"null").
",";
2513 $sql .=
" fk_soc=".(isset($this->socid) ? $this->db->escape($this->socid) :
"null").
",";
2514 $sql .=
" datec=".(strval($this->date_creation) !=
'' ?
"'".$this->db->idate($this->date_creation).
"'" :
'null').
",";
2515 $sql .=
" datef=".(strval($this->date) !=
'' ?
"'".$this->db->idate($this->date).
"'" :
'null').
",";
2516 $sql .=
" date_pointoftax=".(strval($this->date_pointoftax) !=
'' ?
"'".$this->db->idate($this->date_pointoftax).
"'" :
'null').
",";
2517 $sql .=
" date_valid=".(strval($this->date_validation) !=
'' ?
"'".$this->db->idate($this->date_validation).
"'" :
'null').
",";
2518 $sql .=
" paye=".(isset($this->paye) ? $this->db->escape($this->paye) : 0).
",";
2519 $sql .=
" close_code=".(isset($this->close_code) ?
"'".$this->db->escape($this->close_code).
"'" :
"null").
",";
2520 $sql .=
" close_note=".(isset($this->close_note) ?
"'".$this->db->escape($this->close_note).
"'" :
"null").
",";
2521 $sql .=
" total_tva=".(isset($this->total_tva) ? $this->total_tva :
"null").
",";
2522 $sql .=
" localtax1=".(isset($this->total_localtax1) ? $this->total_localtax1 :
"null").
",";
2523 $sql .=
" localtax2=".(isset($this->total_localtax2) ? $this->total_localtax2 :
"null").
",";
2524 $sql .=
" total_ht=".(isset($this->total_ht) ? $this->total_ht :
"null").
",";
2525 $sql .=
" total_ttc=".(isset($this->total_ttc) ? $this->total_ttc :
"null").
",";
2526 $sql .=
" revenuestamp=".((isset($this->revenuestamp) && $this->revenuestamp !=
'') ? $this->db->escape($this->revenuestamp) :
"null").
",";
2527 $sql .=
" fk_statut=".(isset($this->
status) ? ((int) $this->
status) :
"null").
",";
2528 $sql .=
" fk_user_author=".(isset($this->fk_user_author) ? ((int) $this->fk_user_author) :
"null").
",";
2529 $sql .=
" fk_user_valid=".(isset($this->fk_user_valid) ? $this->db->escape($this->fk_user_valid) :
"null").
",";
2530 $sql .=
" fk_facture_source=".(isset($this->fk_facture_source) ? $this->db->escape($this->fk_facture_source) :
"null").
",";
2531 $sql .=
" fk_projet=".(isset($this->fk_project) ? $this->db->escape($this->fk_project) :
"null").
",";
2532 $sql .=
" fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->db->escape($this->cond_reglement_id) :
"null").
",";
2533 $sql .=
" fk_mode_reglement=".(isset($this->mode_reglement_id) ? $this->db->escape($this->mode_reglement_id) :
"null").
",";
2534 $sql .=
" date_lim_reglement=".(strval($this->date_lim_reglement) !=
'' ?
"'".$this->db->idate($this->date_lim_reglement).
"'" :
'null').
",";
2535 $sql .=
" note_private=".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
2536 $sql .=
" note_public=".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
2537 $sql .=
" model_pdf=".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
2538 $sql .=
" import_key=".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null").
",";
2539 $sql .=
" situation_cycle_ref=".(empty($this->situation_cycle_ref) ?
"null" : $this->db->escape($this->situation_cycle_ref)).
",";
2540 $sql .=
" situation_counter=".(empty($this->situation_counter) ?
"null" : $this->db->escape($this->situation_counter)).
",";
2541 $sql .=
" situation_final=".(empty($this->situation_final) ?
"0" : $this->db->escape($this->situation_final)).
",";
2542 $sql .=
" retained_warranty=".(empty($this->retained_warranty) ?
"0" : $this->db->escape($this->retained_warranty)).
",";
2543 $sql .=
" retained_warranty_date_limit=".(strval($this->retained_warranty_date_limit) !=
'' ?
"'".$this->db->idate($this->retained_warranty_date_limit).
"'" :
'null').
",";
2544 $sql .=
" retained_warranty_fk_cond_reglement=".(isset($this->retained_warranty_fk_cond_reglement) ? intval($this->retained_warranty_fk_cond_reglement) :
"null");
2545 $sql .=
" WHERE rowid=".((int) $this->
id);
2549 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
2550 $resql = $this->db->query($sql);
2553 $this->errors[] =
"Error ".$this->db->lasterror();
2563 if (!$error && !$notrigger) {
2574 foreach ($this->errors as $errmsg) {
2575 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
2576 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2578 $this->db->rollback();
2581 $this->db->commit();
2597 global $conf, $langs;
2599 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
2600 include_once DOL_DOCUMENT_ROOT.
'/core/class/discount.class.php';
2605 $result = $remise->fetch($idremise);
2608 if ($remise->fk_facture) {
2609 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed");
2610 $this->db->rollback();
2615 $facligne->fk_facture = $this->id;
2616 $facligne->fk_remise_except = $remise->id;
2617 $facligne->desc = $remise->description;
2618 $facligne->vat_src_code = $remise->vat_src_code;
2619 $facligne->tva_tx = $remise->tva_tx;
2620 $facligne->subprice = -$remise->amount_ht;
2621 $facligne->fk_product = 0;
2623 $facligne->remise_percent = 0;
2624 $facligne->rang = -1;
2625 $facligne->info_bits = 2;
2628 $facligne->rang = 1;
2629 $linecount = count($this->lines);
2630 for ($ii = 1; $ii <= $linecount; $ii++) {
2636 if ($remise->fk_facture_source > 0) {
2637 $srcinvoice =
new Facture($this->db);
2638 $srcinvoice->fetch($remise->fk_facture_source);
2639 include_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmargin.class.php';
2641 $arraytmp = $formmargin->getMarginInfosArray($srcinvoice,
false);
2642 $facligne->pa_ht = $arraytmp[
'pa_total'];
2645 $facligne->total_ht = -$remise->amount_ht;
2646 $facligne->total_tva = -$remise->amount_tva;
2647 $facligne->total_ttc = -$remise->amount_ttc;
2649 $facligne->multicurrency_subprice = -$remise->multicurrency_subprice;
2650 $facligne->multicurrency_total_ht = -$remise->multicurrency_amount_ht;
2651 $facligne->multicurrency_total_tva = -$remise->multicurrency_amount_tva;
2652 $facligne->multicurrency_total_ttc = -$remise->multicurrency_amount_ttc;
2654 $lineid = $facligne->insert();
2659 $result = $remise->link_to_invoice($lineid, 0);
2661 $this->error = $remise->error;
2662 $this->db->rollback();
2666 $this->db->commit();
2669 $this->error = $facligne->error;
2670 $this->db->rollback();
2674 $this->error = $facligne->error;
2675 $this->db->rollback();
2679 $this->db->rollback();
2701 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
2702 if (empty($ref_client)) {
2703 $sql .=
' SET ref_client = NULL';
2705 $sql .=
' SET ref_client = \''.$this->db->escape($ref_client).
'\'';
2707 $sql .=
" WHERE rowid = ".((int) $this->
id);
2709 dol_syslog(__METHOD__.
' this->id='.$this->id.
', ref_client='.$ref_client, LOG_DEBUG);
2710 $resql = $this->db->query($sql);
2712 $this->errors[] = $this->db->error();
2717 $this->ref_client = $ref_client;
2720 if (!$notrigger && empty($error)) {
2730 $this->ref_client = $ref_client;
2732 $this->db->commit();
2735 foreach ($this->errors as $errmsg) {
2736 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2737 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2739 $this->db->rollback();
2752 public function delete($user, $notrigger = 0, $idwarehouse = -1)
2754 global $langs, $conf;
2755 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
2759 dol_syslog(get_class($this).
"::delete rowid=".$rowid.
", ref=".$this->ref.
", thirdparty=".(empty($this->thirdparty) ?
'' : $this->thirdparty->name), LOG_DEBUG);
2772 if (!$error && !$notrigger) {
2786 dol_syslog(get_class($this).
"::delete error deleteExtraFields ".$this->error, LOG_ERR);
2800 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'societe_remise_except';
2801 $sql .=
' WHERE fk_facture_source = '.((int) $rowid);
2802 $sql .=
' AND fk_facture_line IS NULL';
2803 $resql = $this->db->query($sql);
2807 $list_rowid_det = array();
2808 foreach ($this->lines as $key => $invoiceline) {
2809 $list_rowid_det[] = $invoiceline->id;
2813 if (count($list_rowid_det)) {
2814 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
2815 $sql .=
' SET fk_facture = NULL, fk_facture_line = NULL';
2816 $sql .=
' WHERE fk_facture_line IN ('.$this->db->sanitize(join(
',', $list_rowid_det)).
')';
2818 if (!$this->db->query($sql)) {
2819 $this->error = $this->db->error().
" sql=".$sql;
2820 $this->errors[] = $this->error;
2821 $this->db->rollback();
2828 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'eventorganization_conferenceorboothattendee';
2829 $sql .=
' SET fk_invoice = NULL';
2830 $sql .=
' WHERE fk_invoice = '.((int) $rowid);
2832 if (!$this->db->query($sql)) {
2833 $this->error = $this->db->error().
" sql=".$sql;
2834 $this->errors[] = $this->error;
2835 $this->db->rollback();
2839 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'element_time';
2840 $sql .=
' SET invoice_id = NULL, invoice_line_id = NULL';
2841 $sql .=
' WHERE invoice_id = '.((int) $rowid);
2843 if (!$this->db->query($sql)) {
2844 $this->error = $this->db->error().
" sql=".$sql;
2845 $this->errors[] = $this->error;
2846 $this->db->rollback();
2851 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL') && $idwarehouse != -1) {
2852 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
2853 $langs->load(
"agenda");
2855 $num = count($this->lines);
2856 for ($i = 0; $i < $num; $i++) {
2857 if ($this->lines[$i]->fk_product > 0) {
2859 $mouvP->origin = &$this;
2860 $mouvP->setOrigin($this->element, $this->
id);
2862 if ($this->
type == self::TYPE_CREDIT_NOTE) {
2863 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceDeleteDolibarr", $this->ref));
2865 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceDeleteDolibarr", $this->ref));
2872 $main = MAIN_DB_PREFIX.
'facturedet';
2873 $ef = $main.
"_extrafields";
2874 $sqlef =
"DELETE FROM ".$ef.
" WHERE fk_object IN (SELECT rowid FROM ".$main.
" WHERE fk_facture = ".((int) $rowid).
")";
2876 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'facturedet WHERE fk_facture = '.((int) $rowid);
2879 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'facture WHERE rowid = '.((int) $rowid);
2881 $resql = $this->db->query($sql);
2889 if ($conf->facture->dir_output && !empty($this->
ref)) {
2890 $dir = $conf->facture->dir_output.
"/".$ref;
2891 $file = $conf->facture->dir_output.
"/".$ref.
"/".$ref.
".pdf";
2892 if (file_exists($file)) {
2896 $langs->load(
"errors");
2897 $this->error = $langs->trans(
"ErrorFailToDeleteFile", $file);
2898 $this->errors[] = $this->error;
2899 $this->db->rollback();
2903 if (file_exists($dir)) {
2905 $langs->load(
"errors");
2906 $this->error = $langs->trans(
"ErrorFailToDeleteDir", $dir);
2907 $this->errors[] = $this->error;
2908 $this->db->rollback();
2914 $this->db->commit();
2917 $this->error = $this->db->lasterror().
" sql=".$sql;
2918 $this->errors[] = $this->error;
2919 $this->db->rollback();
2923 $this->error = $this->db->lasterror().
" sql=".$sql;
2924 $this->errors[] = $this->error;
2925 $this->db->rollback();
2929 $this->db->rollback();
2946 public function set_paid($user, $close_code =
'', $close_note =
'')
2949 dol_syslog(get_class($this).
"::set_paid is deprecated, use setPaid instead", LOG_NOTICE);
2950 return $this->
setPaid($user, $close_code, $close_note);
2963 public function setPaid($user, $close_code =
'', $close_note =
'')
2967 if ($this->paye != 1) {
2972 dol_syslog(get_class($this).
"::setPaid rowid=".((
int) $this->
id), LOG_DEBUG);
2974 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET';
2975 $sql .=
' fk_statut='.self::STATUS_CLOSED;
2980 $sql .=
", close_code='".$this->db->escape($close_code).
"'";
2983 $sql .=
", close_note='".$this->db->escape($close_note).
"'";
2985 $sql .=
', fk_user_closing = '.((int) $user->id);
2986 $sql .=
", date_closing = '".$this->db->idate($now).
"'";
2987 $sql .=
" WHERE rowid = ".((int) $this->
id);
2989 $resql = $this->db->query($sql);
2999 $this->error = $this->db->lasterror();
3003 $this->db->commit();
3006 $this->db->rollback();
3029 dol_syslog(get_class($this).
"::set_unpaid is deprecated, use setUnpaid instead", LOG_NOTICE);
3047 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
3048 $sql .=
' SET paye=0, fk_statut='.self::STATUS_VALIDATED.
', close_code=null, close_note=null,';
3049 $sql .=
' date_closing=null,';
3050 $sql .=
' fk_user_closing=null';
3051 $sql .=
" WHERE rowid = ".((int) $this->
id);
3053 dol_syslog(get_class($this).
"::setUnpaid", LOG_DEBUG);
3054 $resql = $this->db->query($sql);
3064 $this->error = $this->db->error();
3069 $this->db->commit();
3072 $this->db->rollback();
3094 dol_syslog(get_class($this).
"::set_canceled is deprecated, use setCanceled instead", LOG_NOTICE);
3095 return $this->
setCanceled($user, $close_code, $close_note);
3108 public function setCanceled($user, $close_code =
'', $close_note =
'')
3110 dol_syslog(get_class($this).
"::setCanceled rowid=".((
int) $this->
id), LOG_DEBUG);
3115 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET';
3116 $sql .=
' fk_statut='.self::STATUS_ABANDONED;
3118 $sql .=
", close_code='".$this->db->escape($close_code).
"'";
3121 $sql .=
", close_note='".$this->db->escape($close_note).
"'";
3123 $sql .=
', fk_user_closing = '.((int) $user->id);
3124 $sql .=
", date_closing = '".$this->db->idate($now).
"'";
3125 $sql .=
" WHERE rowid = ".((int) $this->
id);
3127 $resql = $this->db->query($sql);
3131 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
3132 $sql .=
' SET fk_facture = NULL';
3133 $sql .=
' WHERE fk_facture = '.((int) $this->
id);
3135 $resql = $this->db->query($sql);
3140 $this->db->rollback();
3145 $this->db->commit();
3148 $this->error = $this->db->error().
" sql=".$sql;
3149 $this->db->rollback();
3153 $this->error = $this->db->error().
" sql=".$sql;
3154 $this->db->rollback();
3170 public function validate($user, $force_number =
'', $idwarehouse = 0, $notrigger = 0, $batch_rule = 0)
3172 global $conf, $langs, $mysoc;
3173 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
3175 $productStatic =
null;
3176 $warehouseStatic =
null;
3177 if ($batch_rule > 0) {
3178 require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
3179 require_once DOL_DOCUMENT_ROOT.
'/product/class/productbatch.class.php';
3180 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
3181 $productStatic =
new Product($this->db);
3182 $warehouseStatic =
new Entrepot($this->db);
3189 dol_syslog(get_class($this).
'::validate user='.$user->id.
', force_number='.$force_number.
', idwarehouse='.$idwarehouse);
3196 if ($this->
status != self::STATUS_DRAFT) {
3197 dol_syslog(get_class($this).
"::validate Current status is not draft. operation canceled.", LOG_WARNING);
3200 if (count($this->lines) <= 0) {
3201 $langs->load(
"errors");
3202 $this->error = $langs->trans(
"ErrorObjectMustHaveLinesToBeValidated", $this->
ref);
3206 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && !$user->hasRight(
'facture',
'invoice_advance',
'validate'))) {
3207 $this->error =
'Permission denied';
3208 dol_syslog(get_class($this).
"::validate ".$this->error.
' MAIN_USE_ADVANCED_PERMS=' .
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS'), LOG_ERR);
3211 if ((preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) &&
3219 if (!$last_of_type[0]) {
3220 $this->error = $langs->transnoentities(
"ErrorInvoiceIsNotLastOfSameType", $this->
ref,
dol_print_date($this->date,
'day'),
dol_print_date($last_of_type[1],
'day'));
3226 if (!empty($this->thirdparty) && is_object($this->thirdparty)) {
3227 $array_to_check = array(
'IDPROF1',
'IDPROF2',
'IDPROF3',
'IDPROF4',
'IDPROF5',
'IDPROF6',
'EMAIL',
'ACCOUNTANCY_CODE_CUSTOMER');
3228 foreach ($array_to_check as $key) {
3229 $keymin = strtolower($key);
3230 if (!property_exists($this->thirdparty, $keymin)) {
3233 $vallabel = $this->thirdparty->$keymin;
3235 $i = (int) preg_replace(
'/[^0-9]/',
'', $key);
3237 if ($this->thirdparty->isACompany()) {
3239 if ($mysoc->country_id > 0 && $this->thirdparty->country_id == $mysoc->country_id) {
3240 $idprof_mandatory =
'SOCIETE_'.$key.
'_INVOICE_MANDATORY';
3241 if (!$vallabel && !empty($conf->global->$idprof_mandatory)) {
3242 $langs->load(
"errors");
3243 $this->error = $langs->trans(
'ErrorProdIdIsMandatory', $langs->transcountry(
'ProfId'.$i, $this->thirdparty->country_code)).
' ('.$langs->trans(
"ForbiddenBySetupRules").
') ['.$langs->trans(
'Company').
' : '.$this->thirdparty->name.
']';
3244 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3250 if ($key ==
'EMAIL') {
3252 if (
getDolGlobalString(
'SOCIETE_EMAIL_INVOICE_MANDATORY') && !isValidEMail($this->thirdparty->email)) {
3253 $langs->load(
"errors");
3254 $this->error = $langs->trans(
"ErrorBadEMail", $this->thirdparty->email).
' ('.$langs->trans(
"ForbiddenBySetupRules").
') ['.$langs->trans(
'Company').
' : '.$this->thirdparty->name.
']';
3255 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3259 if ($key ==
'ACCOUNTANCY_CODE_CUSTOMER') {
3261 if (
getDolGlobalString(
'SOCIETE_ACCOUNTANCY_CODE_CUSTOMER_INVOICE_MANDATORY') && empty($this->thirdparty->code_compta)) {
3262 $langs->load(
"errors");
3263 $this->error = $langs->trans(
"ErrorAccountancyCodeCustomerIsMandatory", $this->thirdparty->name).
' ('.$langs->trans(
"ForbiddenBySetupRules").
')';
3264 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3273 $array_to_check = array(
'REF_CLIENT'=>
'RefCustomer');
3274 foreach ($array_to_check as $key => $val) {
3275 $keymin = strtolower($key);
3276 $vallabel = $this->$keymin;
3279 $keymandatory =
'INVOICE_'.$key.
'_MANDATORY_FOR_VALIDATION';
3281 $langs->load(
"errors");
3283 setEventMessages($langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv($val)),
null,
'errors');
3290 if ($this->
type == self::TYPE_REPLACEMENT) {
3292 if ($this->fk_facture_source <= 0) {
3293 $this->error = $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"InvoiceReplacement"));
3294 $this->db->rollback();
3299 $facreplaced =
new Facture($this->db);
3300 $result = $facreplaced->fetch($this->fk_facture_source);
3302 $this->error = $langs->trans(
"ErrorBadInvoice");
3303 $this->db->rollback();
3308 $idreplacement = $facreplaced->getIdReplacingInvoice(
'validated');
3309 if ($idreplacement && $idreplacement != $this->
id) {
3310 $facreplacement =
new Facture($this->db);
3311 $facreplacement->fetch($idreplacement);
3312 $this->error = $langs->trans(
"ErrorInvoiceAlreadyReplaced", $facreplaced->ref, $facreplacement->ref);
3313 $this->db->rollback();
3317 $result = $facreplaced->setCanceled($user, self::CLOSECODE_REPLACED,
'');
3319 $this->error = $facreplaced->error;
3320 $this->db->rollback();
3326 if ($force_number) {
3327 $num = $force_number;
3328 } elseif (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
3344 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
3345 $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).
"'";
3347 $sql .=
", datef='".$this->db->idate($this->date).
"'";
3348 $sql .=
", date_lim_reglement='".$this->db->idate($this->date_lim_reglement).
"'";
3350 $sql .=
" WHERE rowid = ".((int) $this->
id);
3352 dol_syslog(get_class($this).
"::validate", LOG_DEBUG);
3353 $resql = $this->db->query($sql);
3360 if (!$error && (preg_match(
'/^[\(]?PROV/i', $this->
ref))) {
3366 $result = $this->thirdparty->setAsCustomer();
3369 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL') && $idwarehouse > 0) {
3370 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3371 $langs->load(
"agenda");
3374 $cpt = count($this->lines);
3375 for ($i = 0; $i < $cpt; $i++) {
3376 if ($this->lines[$i]->fk_product > 0) {
3378 $mouvP->origin = &$this;
3379 $mouvP->setOrigin($this->element, $this->
id);
3385 if ($this->
type == self::TYPE_CREDIT_NOTE) {
3386 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceValidatedInDolibarr", $num));
3389 $this->error = $mouvP->error;
3392 $is_batch_line =
false;
3393 if ($batch_rule > 0) {
3394 $productStatic->fetch($this->lines[$i]->fk_product);
3395 if ($productStatic->hasbatch()) {
3396 $is_batch_line =
true;
3397 $product_qty_remain = $this->lines[$i]->qty;
3403 $sortfield =
'pl.sellby,pl.eatby,pb.qty,pl.rowid';
3404 $sortorder =
'ASC,ASC,ASC,ASC';
3407 $resBatchList = $productbatch->findAllForProduct($productStatic->id, $idwarehouse, (
getDolGlobalInt(
'STOCK_ALLOW_NEGATIVE_TRANSFER') ?
null : 0), $sortfield, $sortorder);
3408 if (!is_array($resBatchList)) {
3410 $this->error = $this->db->lasterror();
3414 $batchList = $resBatchList;
3415 if (empty($batchList)) {
3417 $langs->load(
'errors');
3418 $warehouseStatic->fetch($idwarehouse);
3419 $this->error = $langs->trans(
'ErrorBatchNoFoundForProductInWarehouse', $productStatic->label, $warehouseStatic->ref);
3420 dol_syslog(__METHOD__.
' Error: '.$langs->transnoentitiesnoconv(
'ErrorBatchNoFoundForProductInWarehouse', $productStatic->label, $warehouseStatic->ref), LOG_ERR);
3423 foreach ($batchList as $batch) {
3424 if ($batch->qty <= 0) {
3429 if ($batch->qty >= $product_qty_remain) {
3430 $product_batch_qty = $product_qty_remain;
3433 $product_batch_qty = $batch->qty;
3435 $result = $mouvP->livraison($user, $productStatic->id, $idwarehouse, $product_batch_qty, $this->lines[$i]->subprice, $langs->trans(
'InvoiceValidatedInDolibarr', $num),
'',
'',
'', $batch->batch);
3438 $this->error = $mouvP->error;
3439 $this->errors = $mouvP->errors;
3443 $product_qty_remain -= $product_batch_qty;
3445 if ($product_qty_remain <= 0) {
3450 if (!$error && $product_qty_remain > 0) {
3453 $batch = $batchList[0];
3454 $result = $mouvP->livraison($user, $productStatic->id, $idwarehouse, $product_qty_remain, $this->lines[$i]->subprice, $langs->trans(
'InvoiceValidatedInDolibarr', $num),
'',
'',
'', $batch->batch);
3457 $this->error = $mouvP->error;
3458 $this->errors = $mouvP->errors;
3462 $langs->load(
'errors');
3463 $warehouseStatic->fetch($idwarehouse);
3464 $this->error = $langs->trans(
'ErrorBatchNoFoundEnoughQuantityForProductInWarehouse', $productStatic->label, $warehouseStatic->ref);
3465 dol_syslog(__METHOD__.
' Error: '.$langs->transnoentitiesnoconv(
'ErrorBatchNoFoundEnoughQuantityForProductInWarehouse', $productStatic->label, $warehouseStatic->ref), LOG_ERR);
3472 if (!$is_batch_line) {
3473 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceValidatedInDolibarr", $num));
3476 $this->error = $mouvP->error;
3477 $this->errors = $mouvP->errors;
3490 if (!$error && $this->
type == self::TYPE_CREDIT_NOTE && $this->fk_facture_source > 0) {
3491 $invoice_situation =
new Facture($this->db);
3492 $result = $invoice_situation->fetch($this->fk_facture_source);
3493 if ($result > 0 && $invoice_situation->type == self::TYPE_SITUATION && $invoice_situation->situation_final == 1) {
3494 $invoice_situation->situation_final = 0;
3496 $result = $invoice_situation->setFinal($user, 1);
3499 $this->error = $invoice_situation->error;
3500 $this->errors = $invoice_situation->errors;
3506 if (!$error && !$notrigger) {
3516 $this->oldref = $this->ref;
3519 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
3521 $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).
"'";
3522 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'facture/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
3523 $resql = $this->db->query($sql);
3526 $this->error = $this->db->lasterror();
3528 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'facture/".$this->db->escape($this->newref).
"'";
3529 $sql .=
" WHERE filepath = 'facture/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
3530 $resql = $this->db->query($sql);
3533 $this->error = $this->db->lasterror();
3539 $dirsource = $conf->facture->dir_output.
'/'.$oldref;
3540 $dirdest = $conf->facture->dir_output.
'/'.$newref;
3541 if (!$error && file_exists($dirsource)) {
3542 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
3544 if (@rename($dirsource, $dirdest)) {
3547 $listoffiles =
dol_dir_list($conf->facture->dir_output.
'/'.$newref,
'files', 1,
'^'.preg_quote($oldref,
'/'));
3548 foreach ($listoffiles as $fileentry) {
3549 $dirsource = $fileentry[
'name'];
3550 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
3551 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
3552 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
3553 @rename($dirsource, $dirdest);
3571 $this->date_validation = $now;
3576 $nboflines = count($this->lines);
3577 while (($i < $nboflines) && $final) {
3578 $final = ($this->lines[$i]->situation_percent == 100);
3582 if (empty($final)) {
3583 $this->situation_final = 0;
3585 $this->situation_final = 1;
3596 $this->db->commit();
3599 $this->db->rollback();
3612 foreach ($this->tab_next_situation_invoice as $next_invoice) {
3613 $is_last = $next_invoice->is_last_in_cycle();
3615 if ($next_invoice->status == self::STATUS_DRAFT && $is_last != 1) {
3616 $this->error = $langs->trans(
'updatePriceNextInvoiceErrorUpdateline', $next_invoice->ref);
3620 foreach ($next_invoice->lines as $line) {
3621 $result = $next_invoice->updateline(
3626 $line->remise_percent,
3630 $line->localtax1_tx,
3631 $line->localtax2_tx,
3634 $line->product_type,
3635 $line->fk_parent_line,
3637 $line->fk_fournprice,
3640 $line->special_code,
3641 $line->array_options,
3642 $line->situation_percent,
3647 $this->error = $langs->trans(
'updatePriceNextInvoiceErrorUpdateline', $next_invoice->ref);
3668 global $conf, $langs;
3672 if ($this->
status == self::STATUS_DRAFT) {
3673 dol_syslog(__METHOD__.
" already draft status", LOG_WARNING);
3681 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facture";
3682 $sql .=
" SET fk_statut = ".self::STATUS_DRAFT;
3683 $sql .=
" WHERE rowid = ".((int) $this->
id);
3685 $result = $this->db->query($sql);
3688 $this->oldcopy = clone $this;
3692 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL')) {
3693 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3694 $langs->load(
"agenda");
3696 $num = count($this->lines);
3697 for ($i = 0; $i < $num; $i++) {
3698 if ($this->lines[$i]->fk_product > 0) {
3700 $mouvP->origin = &$this;
3701 $mouvP->setOrigin($this->element, $this->
id);
3703 if ($this->
type == self::TYPE_CREDIT_NOTE) {
3704 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceBackToDraftInDolibarr", $this->ref));
3706 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceBackToDraftInDolibarr", $this->ref));
3713 $old_statut = $this->status;
3718 $result = $this->
call_trigger(
'BILL_UNVALIDATE', $user);
3721 $this->
statut = $old_statut;
3722 $this->
status = $old_statut;
3726 $this->db->rollback();
3731 $this->db->commit();
3734 $this->db->rollback();
3738 $this->error = $this->db->error();
3739 $this->db->rollback();
3794 $remise_percent = 0,
3799 $fk_remise_except = 0,
3800 $price_base_type =
'HT',
3807 $fk_parent_line = 0,
3808 $fk_fournprice =
null,
3811 $array_options = array(),
3812 $situation_percent = 100,
3817 $noupdateafterinsertline = 0
3821 dol_syslog(__METHOD__.
": using line label is deprecated", LOG_WARNING);
3825 global $mysoc, $conf, $langs;
3827 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);
3829 if ($this->
status == self::STATUS_DRAFT) {
3830 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
3833 if (empty($remise_percent)) {
3834 $remise_percent = 0;
3839 if (empty($info_bits)) {
3845 if (empty($ventil)) {
3848 if (empty($txtva)) {
3851 if (empty($txlocaltax1)) {
3854 if (empty($txlocaltax2)) {
3857 if (empty($fk_parent_line) || $fk_parent_line < 0) {
3858 $fk_parent_line = 0;
3860 if (empty($fk_prev_id)) {
3861 $fk_prev_id =
'null';
3863 if (!isset($situation_percent) || $situation_percent > 100 || (
string) $situation_percent ==
'') {
3864 $situation_percent = 100;
3866 if (empty($ref_ext)) {
3870 $remise_percent =
price2num($remise_percent);
3873 $pu_ht_devise =
price2num($pu_ht_devise);
3876 if (!preg_match(
'/\((.*)\)/', $txtva)) {
3882 if ($price_base_type ==
'HT') {
3893 if ($date_start && $date_end && $date_start > $date_end) {
3894 $langs->load(
"errors");
3895 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
3901 $product_type = $type;
3902 if (!empty($fk_product) && $fk_product > 0) {
3903 $product =
new Product($this->db);
3904 $result = $product->fetch($fk_product);
3905 $product_type = $product->type;
3907 if (
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_INVOICE') && $product_type == 0 && $product->stock_reel < $qty) {
3908 $langs->load(
"errors");
3909 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnInvoice', $product->ref);
3910 $this->db->rollback();
3920 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
3921 $vat_src_code = $reg[1];
3922 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
3930 $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);
3932 $total_ht = $tabprice[0];
3933 $total_tva = $tabprice[1];
3934 $total_ttc = $tabprice[2];
3935 $total_localtax1 = $tabprice[9];
3936 $total_localtax2 = $tabprice[10];
3937 $pu_ht = $tabprice[3];
3940 $multicurrency_total_ht = $tabprice[16];
3941 $multicurrency_total_tva = $tabprice[17];
3942 $multicurrency_total_ttc = $tabprice[18];
3943 $pu_ht_devise = $tabprice[19];
3947 if ($ranktouse == -1) {
3948 $rangmax = $this->
line_max($fk_parent_line);
3949 $ranktouse = $rangmax + 1;
3955 $this->line->context = $this->context;
3957 $this->line->fk_facture = $this->id;
3958 $this->line->label = $label;
3959 $this->line->desc = $desc;
3960 $this->line->ref_ext = $ref_ext;
3962 $this->line->qty = ($this->
type == self::TYPE_CREDIT_NOTE ? abs($qty) : $qty);
3963 $this->line->subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht) : $pu_ht);
3965 $this->line->vat_src_code = $vat_src_code;
3966 $this->line->tva_tx = $txtva;
3967 $this->line->localtax1_tx = ($total_localtax1 ? $localtaxes_type[1] : 0);
3968 $this->line->localtax2_tx = ($total_localtax2 ? $localtaxes_type[3] : 0);
3969 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
3970 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
3972 $this->line->total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ht) : $total_ht);
3973 $this->line->total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ttc) : $total_ttc);
3974 $this->line->total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_tva) : $total_tva);
3975 $this->line->total_localtax1 = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_localtax1) : $total_localtax1);
3976 $this->line->total_localtax2 = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_localtax2) : $total_localtax2);
3978 $this->line->fk_product = $fk_product;
3979 $this->line->product_type = $product_type;
3980 $this->line->remise_percent = $remise_percent;
3981 $this->line->date_start = $date_start;
3982 $this->line->date_end = $date_end;
3983 $this->line->ventil = $ventil;
3984 $this->line->rang = $ranktouse;
3985 $this->line->info_bits = $info_bits;
3986 $this->line->fk_remise_except = $fk_remise_except;
3988 $this->line->special_code = $special_code;
3989 $this->line->fk_parent_line = $fk_parent_line;
3990 $this->line->origin = $origin;
3991 $this->line->origin_id = $origin_id;
3992 $this->line->situation_percent = $situation_percent;
3993 $this->line->fk_prev_id = $fk_prev_id;
3994 $this->line->fk_unit = $fk_unit;
3997 $this->line->fk_fournprice = $fk_fournprice;
3998 $this->line->pa_ht = $pa_ht;
4001 $this->line->fk_multicurrency = $this->fk_multicurrency;
4002 $this->line->multicurrency_code = $this->multicurrency_code;
4003 $this->line->multicurrency_subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht_devise) : $pu_ht_devise);
4005 $this->line->multicurrency_total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ht) : $multicurrency_total_ht);
4006 $this->line->multicurrency_total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_tva) : $multicurrency_total_tva);
4007 $this->line->multicurrency_total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ttc) : $multicurrency_total_ttc);
4009 if (is_array($array_options) && count($array_options) > 0) {
4010 $this->line->array_options = $array_options;
4013 $result = $this->line->insert();
4016 if (!empty($fk_parent_line)) {
4018 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
4019 $linecount = count($this->lines);
4020 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
4026 if (empty($noupdateafterinsertline)) {
4031 $this->db->commit();
4032 return $this->line->id;
4034 $this->error = $this->db->lasterror();
4035 $this->db->rollback();
4039 $this->error = $this->line->error;
4040 $this->errors = $this->line->errors;
4041 $this->db->rollback();
4045 $this->errors[] =
'status of invoice must be Draft to allow use of ->addline()';
4046 dol_syslog(get_class($this).
"::addline status of invoice must be Draft to allow use of ->addline()", LOG_ERR);
4082 public function updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type =
'HT', $info_bits = 0, $type = self::TYPE_STANDARD, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice =
null, $pa_ht = 0, $label =
'', $special_code = 0, $array_options = array(), $situation_percent = 100, $fk_unit =
null, $pu_ht_devise = 0, $notrigger = 0, $ref_ext =
'', $rang = 0)
4084 global $conf, $user;
4087 dol_syslog(__METHOD__.
": using line label is deprecated", LOG_WARNING);
4090 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
4092 global $mysoc, $langs;
4094 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);
4096 if ($this->
status == self::STATUS_DRAFT) {
4099 if (!$this->error) {
4100 $this->error = $langs->trans(
'invoiceLineProgressError');
4106 if ($date_start && $date_end && $date_start > $date_end) {
4107 $langs->load(
"errors");
4108 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
4118 if (empty($fk_parent_line) || $fk_parent_line < 0) {
4119 $fk_parent_line = 0;
4121 if (empty($special_code) || $special_code == 3) {
4124 if (!isset($situation_percent) || $situation_percent > 100 || (
string) $situation_percent ==
'') {
4125 $situation_percent = 100;
4127 if (empty($ref_ext)) {
4131 $remise_percent =
price2num($remise_percent);
4134 $pu_ht_devise =
price2num($pu_ht_devise);
4136 if (!preg_match(
'/\((.*)\)/', $txtva)) {
4156 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
4157 $vat_src_code = $reg[1];
4158 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
4161 $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);
4163 $total_ht = $tabprice[0];
4164 $total_tva = $tabprice[1];
4165 $total_ttc = $tabprice[2];
4166 $total_localtax1 = $tabprice[9];
4167 $total_localtax2 = $tabprice[10];
4168 $pu_ht = $tabprice[3];
4169 $pu_tva = $tabprice[4];
4170 $pu_ttc = $tabprice[5];
4173 $multicurrency_total_ht = $tabprice[16];
4174 $multicurrency_total_tva = $tabprice[17];
4175 $multicurrency_total_ttc = $tabprice[18];
4176 $pu_ht_devise = $tabprice[19];
4181 if ($remise_percent > 0) {
4182 $remise = round(((
float) $pu * (
float) $remise_percent / 100), 2);
4183 $price = ((float) $pu - $remise);
4189 $line->fetch($rowid);
4190 $line->fetch_optionals();
4192 if (!empty($line->fk_product)) {
4193 $product =
new Product($this->db);
4194 $result = $product->fetch($line->fk_product);
4195 $product_type = $product->type;
4197 if (
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_INVOICE') && $product_type == 0 && $product->stock_reel < $qty) {
4198 $langs->load(
"errors");
4199 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnInvoice', $product->ref);
4200 $this->db->rollback();
4205 $staticline = clone $line;
4207 $line->oldline = $staticline;
4208 $this->line = $line;
4209 $this->line->context = $this->context;
4210 $this->line->rang = $rang;
4213 if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
4214 $rangmax = $this->
line_max($fk_parent_line);
4215 $this->line->rang = $rangmax + 1;
4217 $apply_abs_price_on_credit_note=
false;
4219 $apply_abs_price_on_credit_note =
true;
4223 $this->line->id = $rowid;
4224 $this->line->rowid = $rowid;
4225 $this->line->label = $label;
4226 $this->line->desc = $desc;
4227 $this->line->ref_ext = $ref_ext;
4228 $this->line->qty = ($this->
type == self::TYPE_CREDIT_NOTE ? abs($qty) : $qty);
4230 $this->line->vat_src_code = $vat_src_code;
4231 $this->line->tva_tx = $txtva;
4232 $this->line->localtax1_tx = $txlocaltax1;
4233 $this->line->localtax2_tx = $txlocaltax2;
4234 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
4235 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
4237 $this->line->remise_percent = $remise_percent;
4238 $this->line->subprice = ($apply_abs_price_on_credit_note ? -abs($pu_ht) : $pu_ht);
4239 $this->line->date_start = $date_start;
4240 $this->line->date_end = $date_end;
4241 $this->line->total_ht = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($total_ht) : $total_ht);
4242 $this->line->total_tva = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($total_tva) : $total_tva);
4243 $this->line->total_localtax1 = $total_localtax1;
4244 $this->line->total_localtax2 = $total_localtax2;
4245 $this->line->total_ttc = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($total_ttc) : $total_ttc);
4246 $this->line->info_bits = $info_bits;
4247 $this->line->special_code = $special_code;
4248 $this->line->product_type = $type;
4249 $this->line->fk_parent_line = $fk_parent_line;
4250 $this->line->skip_update_total = $skip_update_total;
4251 $this->line->situation_percent = $situation_percent;
4252 $this->line->fk_unit = $fk_unit;
4254 $this->line->fk_fournprice = $fk_fournprice;
4255 $this->line->pa_ht = $pa_ht;
4258 $this->line->multicurrency_subprice = ($apply_abs_price_on_credit_note ? -abs($pu_ht_devise) : $pu_ht_devise);
4259 $this->line->multicurrency_total_ht = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($multicurrency_total_ht) : $multicurrency_total_ht);
4260 $this->line->multicurrency_total_tva = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($multicurrency_total_tva) : $multicurrency_total_tva);
4261 $this->line->multicurrency_total_ttc = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($multicurrency_total_ttc) : $multicurrency_total_ttc);
4263 if (is_array($array_options) && count($array_options) > 0) {
4265 foreach ($array_options as $key => $value) {
4266 $this->line->array_options[$key] = $array_options[$key];
4270 $result = $this->line->update($user, $notrigger);
4273 if (!empty($fk_parent_line)) {
4279 $this->db->commit();
4282 $this->error = $this->line->error;
4283 $this->db->rollback();
4287 $this->error =
"Invoice statut makes operation forbidden";
4301 $sql =
'SELECT fd.situation_percent FROM '.MAIN_DB_PREFIX.
'facturedet fd
4302 INNER JOIN '.MAIN_DB_PREFIX.
'facture f ON (fd.fk_facture = f.rowid)
4303 WHERE fd.fk_prev_id = '.((int) $idline).
' AND f.fk_statut <> 0';
4305 $result = $this->db->query($sql);
4307 $this->error = $this->db->error();
4311 $obj = $this->db->fetch_object($result);
4313 if ($obj ===
null) {
4316 return ($situation_percent < $obj->situation_percent);
4332 global $mysoc, $user;
4335 if (($line->info_bits & 2) == 2) {
4339 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
4342 if ($percent > 100) {
4345 $line->situation_percent = $percent;
4346 $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);
4347 $line->total_ht = $tabprice[0];
4348 $line->total_tva = $tabprice[1];
4349 $line->total_ttc = $tabprice[2];
4350 $line->total_localtax1 = $tabprice[9];
4351 $line->total_localtax2 = $tabprice[10];
4352 $line->multicurrency_total_ht = $tabprice[16];
4353 $line->multicurrency_total_tva = $tabprice[17];
4354 $line->multicurrency_total_ttc = $tabprice[18];
4355 $line->update($user);
4358 if ($update_price) {
4374 dol_syslog(get_class($this).
"::deleteline rowid=".((
int) $rowid), LOG_DEBUG);
4376 if ($this->
status != self::STATUS_DRAFT) {
4377 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
4383 $line->context = $this->context;
4386 $result = $line->fetch($rowid);
4387 if (!($result > 0)) {
4392 if ($id > 0 && $line->fk_facture != $id) {
4393 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
4400 $staticline = clone $line;
4401 $line->oldline = $staticline;
4403 if ($line->delete($user) > 0) {
4407 $this->db->commit();
4410 $this->db->rollback();
4411 $this->error = $this->db->lasterror();
4415 $this->db->rollback();
4416 $this->error = $line->error;
4435 dol_syslog(get_class($this).
"::set_remise is deprecated, use setDiscount instead", LOG_NOTICE);
4436 return $this->
setDiscount($user, $remise, $notrigger);
4451 if (empty($remise)) {
4455 if ($user->hasRight(
'facture',
'creer')) {
4462 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
4463 $sql .=
' SET remise_percent = '.((float) $remise);
4464 $sql .=
" WHERE rowid = ".((int) $this->
id);
4465 $sql .=
' AND fk_statut = '.self::STATUS_DRAFT;
4468 $resql = $this->db->query($sql);
4470 $this->errors[] = $this->db->error();
4474 if (!$notrigger && empty($error)) {
4484 $this->remise_percent = $remise;
4487 $this->db->commit();
4490 foreach ($this->errors as $errmsg) {
4491 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
4492 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
4494 $this->db->rollback();
4581 global $conf, $langs;
4583 if ($this->module_source ==
'takepos') {
4584 $langs->load(
'cashdesk');
4586 $moduleName =
'takepos';
4587 $moduleSourceName =
'Takepos';
4588 $addonConstName =
'TAKEPOS_REF_ADDON';
4592 $conf->global->TAKEPOS_REF_ADDON =
'mod_takepos_ref_simple';
4595 $addon = $conf->global->TAKEPOS_REF_ADDON;
4597 $langs->load(
'bills');
4599 $moduleName =
'facture';
4600 $moduleSourceName =
'Invoice';
4601 $addonConstName =
'FACTURE_ADDON';
4605 $conf->global->FACTURE_ADDON =
'mod_facture_terre';
4607 $conf->global->FACTURE_ADDON =
'mod_facture_terre';
4609 $conf->global->FACTURE_ADDON =
'mod_facture_mercure';
4612 $addon = $conf->global->FACTURE_ADDON;
4615 if (!empty($addon)) {
4616 dol_syslog(
"Call getNextNumRef with ".$addonConstName.
" = " .
getDolGlobalString(
'FACTURE_ADDON').
", thirdparty=".$soc->name.
", type=".$soc->typent_code.
", mode=".$mode, LOG_DEBUG);
4620 $file = $addon.
'.php';
4621 $classname = $addon;
4625 $dirmodels = array_merge(array(
'/'), (array) $conf->modules_parts[
'models']);
4626 foreach ($dirmodels as $reldir) {
4627 $dir =
dol_buildpath($reldir.
'core/modules/'.$moduleName.
'/');
4630 if (is_file($dir.$file) && is_readable($dir.$file)) {
4631 $mybool |= include_once $dir.$file;
4637 $file = $addon.
'/'.$addon.
'.modules.php';
4638 $classname =
'mod_'.$moduleName.
'_'.$addon;
4639 $classname = preg_replace(
'/\-.*$/',
'', $classname);
4641 foreach ($conf->file->dol_document_root as $dirroot) {
4642 $dir = $dirroot.
'/core/modules/'.$moduleName.
'/';
4645 if (is_file($dir.$file) && is_readable($dir.$file)) {
4646 $mybool |= include_once $dir.$file;
4656 $obj =
new $classname();
4658 $numref = $obj->getNextValue($soc, $this, $mode);
4665 if ($mode !=
'last' && !$numref) {
4666 $this->error = $obj->error;
4672 $langs->load(
'errors');
4673 print $langs->trans(
'Error').
' '.$langs->trans(
'ErrorModuleSetupNotComplete', $langs->transnoentitiesnoconv($moduleSourceName));
4686 $sql =
'SELECT c.rowid, datec, date_valid as datev, tms as datem,';
4687 $sql .=
' date_closing as dateclosing,';
4688 $sql .=
' fk_user_author, fk_user_valid, fk_user_closing';
4689 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facture as c';
4690 $sql .=
' WHERE c.rowid = '.((int) $id);
4692 $result = $this->db->query($sql);
4694 if ($this->db->num_rows($result)) {
4695 $obj = $this->db->fetch_object($result);
4697 $this->
id = $obj->rowid;
4698 $this->user_creation_id = $obj->fk_user_author;
4699 $this->user_validation_id = $obj->fk_user_valid;
4700 $this->user_closing_id = $obj->fk_user_closing;
4702 $this->date_creation = $this->db->jdate($obj->datec);
4703 $this->date_modification = $this->db->jdate($obj->datem);
4704 $this->date_validation = $this->db->jdate($obj->datev);
4705 $this->date_closing = $this->db->jdate($obj->dateclosing);
4707 $this->db->free($result);
4728 public function liste_array($shortlist = 0, $draft = 0, $excluser =
null, $socid = 0, $limit = 0, $offset = 0, $sortfield =
'f.datef,f.rowid', $sortorder =
'DESC')
4731 global $conf, $user;
4735 $sql =
"SELECT s.rowid, s.nom as name, s.client,";
4736 $sql .=
" f.rowid as fid, f.ref as ref, f.datef as df";
4737 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4738 $sql .=
", sc.fk_soc, sc.fk_user";
4740 $sql .=
" FROM ".MAIN_DB_PREFIX.
"societe as s, ".MAIN_DB_PREFIX.
"facture as f";
4741 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4742 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
4744 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice').
")";
4745 $sql .=
" AND f.fk_soc = s.rowid";
4746 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4747 $sql .=
" AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4750 $sql .=
" AND s.rowid = ".((int) $socid);
4753 $sql .=
" AND f.fk_statut = ".self::STATUS_DRAFT;
4755 if (is_object($excluser)) {
4756 $sql .=
" AND f.fk_user_author <> ".((int) $excluser->id);
4758 $sql .= $this->db->order($sortfield, $sortorder);
4759 $sql .= $this->db->plimit($limit, $offset);
4761 $result = $this->db->query($sql);
4763 $numc = $this->db->num_rows($result);
4766 while ($i < $numc) {
4767 $obj = $this->db->fetch_object($result);
4769 if ($shortlist == 1) {
4770 $ga[$obj->fid] = $obj->ref;
4771 } elseif ($shortlist == 2) {
4772 $ga[$obj->fid] = $obj->ref.
' ('.$obj->name.
')';
4774 $ga[$i][
'id'] = $obj->fid;
4775 $ga[$i][
'ref'] = $obj->ref;
4776 $ga[$i][
'name'] = $obj->name;
4805 $sql =
"SELECT f.rowid as rowid, f.ref, f.fk_statut as status, f.paye as paid,";
4806 $sql .=
" ff.rowid as rowidnext";
4808 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4809 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"paiement_facture as pf ON f.rowid = pf.fk_facture";
4810 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facture as ff ON f.rowid = ff.fk_facture_source";
4811 $sql .=
" WHERE (f.fk_statut = ".self::STATUS_VALIDATED.
" OR (f.fk_statut = ".self::STATUS_ABANDONED.
" AND f.close_code = '".self::CLOSECODE_ABANDONED.
"'))";
4812 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4813 $sql .=
" AND f.paye = 0";
4814 $sql .=
" AND pf.fk_paiement IS NULL";
4815 $sql .=
" AND ff.fk_statut IS NULL";
4817 $sql .=
" AND f.fk_soc = ".((int) $socid);
4820 $sql .=
" ORDER BY f.ref";
4822 dol_syslog(get_class($this).
"::list_replacable_invoices", LOG_DEBUG);
4823 $resql = $this->db->query($sql);
4825 while ($obj = $this->db->fetch_object($resql)) {
4826 $return[$obj->rowid] = array(
4827 'id' => $obj->rowid,
4829 'status' => $obj->status,
4830 'paid' => $obj->paid,
4837 $this->error = $this->db->error();
4860 $sql =
"SELECT f.rowid as rowid, f.ref, f.fk_statut, f.type, f.subtype, f.paye, pf.fk_paiement";
4861 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4862 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"paiement_facture as pf ON f.rowid = pf.fk_facture";
4863 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facture as ff ON (f.rowid = ff.fk_facture_source AND ff.type=".self::TYPE_REPLACEMENT.
")";
4864 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice').
")";
4865 $sql .=
" AND f.fk_statut in (".self::STATUS_VALIDATED.
",".self::STATUS_CLOSED.
")";
4869 $sql .=
" AND ff.type IS NULL";
4870 $sql .=
" AND f.type <> ".self::TYPE_CREDIT_NOTE;
4874 $sql .=
" AND (f.type <> ".self::TYPE_SITUATION.
" OR f.rowid IN ";
4875 $sql .=
'(SELECT MAX(fs.rowid)';
4876 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as fs";
4877 $sql .=
" WHERE fs.entity IN (".getEntity(
'invoice').
")";
4878 $sql .=
" AND fs.type = ".self::TYPE_SITUATION;
4879 $sql .=
" AND fs.fk_statut IN (".self::STATUS_VALIDATED.
",".self::STATUS_CLOSED.
")";
4881 $sql .=
" AND fs.fk_soc = ".((int) $socid);
4883 $sql .=
" GROUP BY fs.situation_cycle_ref)";
4886 $sql .=
" AND f.type <> ".self::TYPE_SITUATION;
4890 $sql .=
" AND f.fk_soc = ".((int) $socid);
4892 $sql .=
" ORDER BY f.ref";
4894 dol_syslog(get_class($this).
"::list_qualified_avoir_invoices", LOG_DEBUG);
4895 $resql = $this->db->query($sql);
4897 while ($obj = $this->db->fetch_object($resql)) {
4899 if ($obj->fk_statut == self::STATUS_VALIDATED) {
4902 if ($obj->fk_statut == self::STATUS_CLOSED) {
4907 $paymentornot = ($obj->fk_paiement ? 1 : 0);
4908 $return[$obj->rowid] = array(
'ref'=>$obj->ref,
'status'=>$obj->fk_statut,
'type'=>$obj->type,
'paye'=>$obj->paye,
'paymentornot'=>$paymentornot);
4914 $this->error = $this->db->error();
4930 global $conf, $langs;
4934 $sql =
"SELECT f.rowid, f.date_lim_reglement as datefin, f.fk_statut as status, f.total_ht";
4935 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4936 if (!$user->hasRight(
'societe',
'client',
'voir') && !$user->socid) {
4937 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON f.fk_soc = sc.fk_soc";
4938 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
4941 $sql .= $clause.
" f.paye=0";
4942 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4943 $sql .=
" AND f.fk_statut = ".self::STATUS_VALIDATED;
4945 $sql .=
" AND f.fk_soc = ".((int) $user->socid);
4948 $resql = $this->db->query($sql);
4950 $langs->load(
"bills");
4954 $response->warning_delay = $conf->facture->client->warning_delay / 60 / 60 / 24;
4955 $response->label = $langs->trans(
"CustomerBillsUnpaid");
4956 $response->labelShort = $langs->trans(
"Unpaid");
4957 $response->url = DOL_URL_ROOT.
'/compta/facture/list.php?search_status=1&mainmenu=billing&leftmenu=customers_bills';
4960 $generic_facture =
new Facture($this->db);
4962 while ($obj = $this->db->fetch_object($resql)) {
4963 $generic_facture->date_lim_reglement = $this->db->jdate($obj->datefin);
4964 $generic_facture->statut = $obj->status;
4965 $generic_facture->status = $obj->status;
4967 $response->nbtodo++;
4968 $response->total += $obj->total_ht;
4970 if ($generic_facture->hasDelay()) {
4971 $response->nbtodolate++;
4972 $response->url_late = DOL_URL_ROOT.
'/compta/facture/list.php?search_option=late&mainmenu=billing&leftmenu=customers_bills';
4976 $this->db->free($resql);
4980 $this->error = $this->db->error();
5019 global $conf, $langs, $user;
5023 $nownotime =
dol_mktime(0, 0, 0, $arraynow[
'mon'], $arraynow[
'mday'], $arraynow[
'year']);
5028 $sql =
"SELECT rowid";
5029 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
5030 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
5031 $sql .= $this->db->plimit(100);
5033 $resql = $this->db->query($sql);
5035 $num_prods = $this->db->num_rows($resql);
5037 while ($i < $num_prods) {
5039 $row = $this->db->fetch_row($resql);
5040 $prodids[$i] = $row[0];
5044 if (empty($num_prods)) {
5051 $this->
ref =
'SPECIMEN';
5052 $this->specimen = 1;
5054 $this->date = $nownotime;
5055 $this->date_lim_reglement = $nownotime + 3600 * 24 * 30;
5056 $this->cond_reglement_id = 1;
5057 $this->cond_reglement_code =
'RECEP';
5059 $this->mode_reglement_id = 0;
5060 $this->mode_reglement_code =
'';
5062 $this->note_public =
'This is a comment (public)';
5063 $this->note_private =
'This is a comment (private)';
5064 $this->note =
'This is a comment (private)';
5066 $this->fk_user_author = $user->id;
5068 $this->multicurrency_tx = 1;
5069 $this->multicurrency_code = $conf->currency;
5071 $this->fk_incoterms = 0;
5072 $this->location_incoterms =
'';
5074 if (empty($option) || $option !=
'nolines') {
5078 while ($xnbp < $nbp) {
5080 $line->desc = $langs->trans(
"Description").
" ".$xnbp;
5082 $line->subprice = 100;
5083 $line->tva_tx = 19.6;
5084 $line->localtax1_tx = 0;
5085 $line->localtax2_tx = 0;
5086 $line->remise_percent = 0;
5088 $prodid = mt_rand(1, $num_prods);
5089 $line->fk_product = $prodids[$prodid];
5091 $line->total_ht = -100;
5092 $line->total_ttc = -119.6;
5093 $line->total_tva = -19.6;
5094 $line->multicurrency_total_ht = -200;
5095 $line->multicurrency_total_ttc = -239.2;
5096 $line->multicurrency_total_tva = -39.2;
5097 } elseif ($xnbp == 2) {
5098 $line->subprice = -100;
5099 $line->total_ht = -100;
5100 $line->total_ttc = -119.6;
5101 $line->total_tva = -19.6;
5102 $line->remise_percent = 0;
5103 $line->multicurrency_total_ht = -200;
5104 $line->multicurrency_total_ttc = -239.2;
5105 $line->multicurrency_total_tva = -39.2;
5106 } elseif ($xnbp == 3) {
5107 $prodid = mt_rand(1, $num_prods);
5108 $line->fk_product = $prodids[$prodid];
5109 $line->total_ht = 50;
5110 $line->total_ttc = 59.8;
5111 $line->total_tva = 9.8;
5112 $line->multicurrency_total_ht = 100;
5113 $line->multicurrency_total_ttc = 119.6;
5114 $line->multicurrency_total_tva = 19.6;
5115 $line->remise_percent = 50;
5117 $prodid = mt_rand(1, $num_prods);
5118 $line->fk_product = $prodids[$prodid];
5119 $line->total_ht = 100;
5120 $line->total_ttc = 119.6;
5121 $line->total_tva = 19.6;
5122 $line->multicurrency_total_ht = 200;
5123 $line->multicurrency_total_ttc = 239.2;
5124 $line->multicurrency_total_tva = 39.2;
5125 $line->remise_percent = 0;
5128 $this->lines[$xnbp] = $line;
5131 $this->total_ht += $line->total_ht;
5132 $this->total_tva += $line->total_tva;
5133 $this->total_ttc += $line->total_ttc;
5135 $this->multicurrency_total_ht += $line->multicurrency_total_ht;
5136 $this->multicurrency_total_tva += $line->multicurrency_total_tva;
5137 $this->multicurrency_total_ttc += $line->multicurrency_total_ttc;
5141 $this->revenuestamp = 0;
5145 $line->desc = $langs->trans(
"Description").
" (offered line)";
5147 $line->subprice = 100;
5148 $line->tva_tx = 19.6;
5149 $line->localtax1_tx = 0;
5150 $line->localtax2_tx = 0;
5151 $line->remise_percent = 100;
5152 $line->total_ht = 0;
5153 $line->total_ttc = 0;
5154 $line->total_tva = 0;
5155 $line->multicurrency_total_ht = 0;
5156 $line->multicurrency_total_ttc = 0;
5157 $line->multicurrency_total_tva = 0;
5158 $prodid = mt_rand(1, $num_prods);
5159 $line->fk_product = $prodids[$prodid];
5161 $this->lines[$xnbp] = $line;
5175 global $conf, $user;
5177 $this->nb = array();
5181 $sql =
"SELECT count(f.rowid) as nb";
5182 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
5183 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON f.fk_soc = s.rowid";
5184 if (!$user->hasRight(
'societe',
'client',
'voir') && !$user->socid) {
5185 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON s.rowid = sc.fk_soc";
5186 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
5189 $sql .=
" ".$clause.
" f.entity IN (".
getEntity(
'invoice').
")";
5191 $resql = $this->db->query($sql);
5193 while ($obj = $this->db->fetch_object($resql)) {
5194 $this->nb[
"invoices"] = $obj->nb;
5196 $this->db->free($resql);
5200 $this->error = $this->db->error();
5226 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
5228 global $conf, $langs;
5230 $outputlangs->loadLangs(array(
"bills",
"products"));
5234 $thisTypeConfName =
'FACTURE_ADDON_PDF_'.$this->type;
5236 if (!empty($this->model_pdf)) {
5237 $modele = $this->model_pdf;
5241 $modele = $conf->global->FACTURE_ADDON_PDF;
5245 $modelpath =
"core/modules/facture/doc/";
5247 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
5257 $sql =
'SELECT max(situation_cycle_ref) FROM '.MAIN_DB_PREFIX.
'facture as f';
5258 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice', 0).
")";
5259 $resql = $this->db->query($sql);
5261 if ($this->db->num_rows($resql) > 0) {
5262 $res = $this->db->fetch_array($resql);
5263 $ref = $res[
'max(situation_cycle_ref)'];
5268 $this->db->free($resql);
5271 $this->error = $this->db->lasterror();
5272 dol_syslog(
"Error sql=".$sql.
", error=".$this->error, LOG_ERR);
5286 return ($this->situation_counter == 1);
5300 $sql =
'SELECT rowid FROM '.MAIN_DB_PREFIX.
'facture';
5301 $sql .=
' WHERE situation_cycle_ref = '.((int) $this->situation_cycle_ref);
5302 $sql .=
' AND situation_counter < '.((int) $this->situation_counter);
5303 $sql .=
' AND entity = '.($this->entity > 0 ? $this->entity : $conf->entity);
5304 $resql = $this->db->query($sql);
5306 if ($resql && $this->db->num_rows($resql) > 0) {
5307 while ($row = $this->db->fetch_object($resql)) {
5309 $situation =
new Facture($this->db);
5310 $situation->fetch($id);
5311 $res[] = $situation;
5314 $this->error = $this->db->error();
5315 dol_syslog(
"Error sql=".$sql.
", error=".$this->error, LOG_ERR);
5335 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET situation_final = '.((int) $this->situation_final).
' WHERE rowid = '.((int) $this->
id);
5338 $resql = $this->db->query($sql);
5340 $this->errors[] = $this->db->error();
5344 if (!$notrigger && empty($error)) {
5354 $this->db->commit();
5357 foreach ($this->errors as $errmsg) {
5358 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
5359 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
5361 $this->db->rollback();
5377 if (!empty($this->situation_cycle_ref)) {
5379 $sql =
'SELECT max(situation_counter) FROM '.MAIN_DB_PREFIX.
'facture';
5380 $sql .=
' WHERE situation_cycle_ref = '.((int) $this->situation_cycle_ref);
5381 $sql .=
' AND entity = '.($this->entity > 0 ? $this->entity : $conf->entity);
5382 $resql = $this->db->query($sql);
5384 if ($resql && $this->db->num_rows($resql) > 0) {
5385 $res = $this->db->fetch_array($resql);
5386 $last = $res[
'max(situation_counter)'];
5387 return ($last == $this->situation_counter);
5389 $this->error = $this->db->lasterror();
5390 dol_syslog(get_class($this).
"::select Error ".$this->error, LOG_ERR);
5448 $hasDelay = $this->date_lim_reglement < ($now - $conf->facture->client->warning_delay);
5449 if ($hasDelay && !empty($this->retained_warranty) && !empty($this->retained_warranty_date_limit)) {
5451 $totalpaid = (float) $totalpaid;
5453 if ($totalpaid >= 0 && $RetainedWarrantyAmount >= 0) {
5454 if (($totalpaid < $this->total_ttc - $RetainedWarrantyAmount) && $this->date_lim_reglement < ($now - $conf->facture->client->warning_delay)) {
5456 } elseif ($totalpaid < $this->total_ttc && $this->retained_warranty_date_limit < ($now - $conf->facture->client->warning_delay)) {
5479 $displayWarranty =
false;
5480 if (!empty($this->retained_warranty)) {
5481 $displayWarranty =
true;
5485 $displayWarranty =
false;
5486 if (!empty($this->situation_final)) {
5487 $displayWarranty =
true;
5490 $displayWarranty =
true;
5492 foreach ($this->lines as $i => $line) {
5493 if ($line->product_type < 2 && $line->situation_percent < 100) {
5494 $displayWarranty =
false;
5502 return $displayWarranty;
5512 if (empty($this->retained_warranty)) {
5516 $retainedWarrantyAmount = 0;
5520 $displayWarranty =
true;
5522 if (!empty($this->lines)) {
5523 foreach ($this->lines as $i => $line) {
5524 if ($line->product_type < 2 && $line->situation_percent < 100) {
5525 $displayWarranty =
false;
5531 if ($displayWarranty && !empty($this->situation_final)) {
5533 $TPreviousIncoice = $this->tab_previous_situation_invoice;
5536 foreach ($TPreviousIncoice as &$fac) {
5537 $total2BillWT += $fac->total_ttc;
5539 $total2BillWT += $this->total_ttc;
5541 $retainedWarrantyAmount = $total2BillWT * $this->retained_warranty / 100;
5547 $retainedWarrantyAmount = $this->total_ttc * $this->retained_warranty / 100;
5550 if ($rounding < 0) {
5554 if ($rounding > 0) {
5555 return round($retainedWarrantyAmount, $rounding);
5558 return $retainedWarrantyAmount;
5569 dol_syslog(get_class($this).
'::setRetainedWarranty('.$value.
')');
5571 if ($this->
status >= 0) {
5572 $fieldname =
'retained_warranty';
5573 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
5574 $sql .=
" SET ".$fieldname.
" = ".((float) $value);
5575 $sql .=
' WHERE rowid='.((int) $this->
id);
5577 if ($this->db->query($sql)) {
5578 $this->retained_warranty = (float) $value;
5581 dol_syslog(get_class($this).
'::setRetainedWarranty Erreur '.$sql.
' - '.$this->db->error());
5582 $this->error = $this->db->error();
5586 dol_syslog(get_class($this).
'::setRetainedWarranty, status of the object is incompatible');
5587 $this->error =
'Status of the object is incompatible '.$this->status;
5602 if (!$timestamp && $dateYmd) {
5603 $timestamp = $this->db->jdate($dateYmd);
5607 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit('.$timestamp.
')');
5608 if ($this->
status >= 0) {
5609 $fieldname =
'retained_warranty_date_limit';
5610 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
5611 $sql .=
" SET ".$fieldname.
" = ".(strval($timestamp) !=
'' ?
"'".$this->db->idate($timestamp).
"'" :
'null');
5612 $sql .=
' WHERE rowid = '.((int) $this->
id);
5614 if ($this->db->query($sql)) {
5615 $this->retained_warranty_date_limit = $timestamp;
5618 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit Erreur '.$sql.
' - '.$this->db->error());
5619 $this->error = $this->db->error();
5623 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit, status of the object is incompatible');
5624 $this->error =
'Status of the object is incompatible '.$this->status;
5643 global $conf, $langs, $user;
5649 $errorsMsg = array();
5651 $langs->load(
"bills");
5653 if (!isModEnabled(
'facture')) {
5654 $this->output .= $langs->trans(
'ModuleNotEnabled', $langs->transnoentitiesnoconv(
"Facture"));
5657 if (!in_array($datetouse, array(
'duedate',
'invoicedate'))) {
5658 $this->output .=
'Bad value for parameter datetouse. Must be "duedate" or "invoicedate"';
5668 require_once DOL_DOCUMENT_ROOT.
'/core/lib/date.lib.php';
5669 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmail.class.php';
5670 require_once DOL_DOCUMENT_ROOT.
'/core/class/CMailFile.class.php';
5671 $formmail =
new FormMail($this->db);
5676 $tmpinvoice =
new Facture($this->db);
5681 $sql =
"SELECT rowid as id FROM ".MAIN_DB_PREFIX.
"facture as f";
5682 if (!empty($paymentmode) && $paymentmode !=
'all') {
5683 $sql .=
", ".MAIN_DB_PREFIX.
"c_paiement as cp";
5685 $sql .=
" WHERE f.paye = 0";
5686 $sql .=
" AND f.fk_statut = ".self::STATUS_VALIDATED;
5687 if ($datetouse ==
'invoicedate') {
5688 $sql .=
" AND f.datef = '".$this->db->idate($tmpidate,
'gmt').
"'";
5690 $sql .=
" AND f.date_lim_reglement = '".$this->db->idate($tmpidate,
'gmt').
"'";
5692 $sql .=
" AND f.entity IN (".getEntity(
'facture', 0).
")";
5693 if (!empty($paymentmode) && $paymentmode !=
'all') {
5694 $sql .=
" AND f.fk_mode_reglement = cp.id AND cp.code = '".$this->db->escape($paymentmode).
"'";
5697 if ($datetouse ==
'invoicedate') {
5698 $sql .= $this->db->order(
"datef",
"ASC");
5700 $sql .= $this->db->order(
"date_lim_reglement",
"ASC");
5703 $resql = $this->db->query($sql);
5706 if ($datetouse ==
'invoicedate') {
5707 $this->output .= $langs->transnoentitiesnoconv(
"SearchValidatedInvoicesWithDate", $stmpidate);
5709 $this->output .= $langs->transnoentitiesnoconv(
"SearchUnpaidInvoicesWithDueDate", $stmpidate);
5711 if (!empty($paymentmode) && $paymentmode !=
'all') {
5712 $this->output .=
' ('.$langs->transnoentitiesnoconv(
"PaymentMode").
' '.$paymentmode.
')';
5714 $this->output .=
'<br>';
5717 while ($obj = $this->db->fetch_object($resql)) {
5722 $res = $tmpinvoice->fetch($obj->id);
5724 $tmpinvoice->fetch_thirdparty();
5726 $outputlangs =
new Translate(
'', $conf);
5727 if ($tmpinvoice->thirdparty->default_lang) {
5728 $outputlangs->setDefaultLang($tmpinvoice->thirdparty->default_lang);
5729 $outputlangs->loadLangs(array(
"main",
"bills"));
5731 $outputlangs = $langs;
5735 $arraymessage = $formmail->getEMailTemplate($this->db,
'facture_send', $user, $outputlangs, (is_numeric($template) ? $template : 0), 1, (is_numeric($template) ?
'' : $template));
5736 if (is_numeric($arraymessage) && $arraymessage <= 0) {
5737 $langs->load(
"errors");
5738 $this->output .= $langs->trans(
'ErrorFailedToFindEmailTemplate', $template);
5751 $sendTopic =
make_substitutions(empty($arraymessage->topic) ? $outputlangs->transnoentitiesnoconv(
'InformationMessage') : $arraymessage->topic, $substitutionarray, $outputlangs, 1);
5754 $content = $outputlangs->transnoentitiesnoconv($arraymessage->content);
5760 if ($forcerecipient) {
5761 $to = array($forcerecipient);
5763 $res = $tmpinvoice->fetch_thirdparty();
5764 $recipient = $tmpinvoice->thirdparty;
5766 $tmparraycontact = $tmpinvoice->liste_contact(-1,
'external', 0,
'BILLING');
5767 if (is_array($tmparraycontact) && count($tmparraycontact) > 0) {
5768 foreach ($tmparraycontact as $data_email) {
5769 if (!empty($data_email[
'email'])) {
5770 $to[] = $tmpinvoice->thirdparty->contact_get_property($data_email[
'id'],
'email');
5774 if (empty($to) && !empty($recipient->email)) {
5775 $to[] = $recipient->email;
5778 $errormesg =
"Failed to send remind to thirdparty id=".$tmpinvoice->socid.
". No email defined for invoice or customer.";
5782 $errormesg =
"Failed to load recipient with thirdparty id=".$tmpinvoice->socid;
5789 if (!empty($arraymessage->email_from)) {
5790 $from = $arraymessage->email_from;
5793 $errormesg =
"Failed to get sender into global setup MAIN_MAIL_EMAIL_FROM";
5797 if (!$loopError && !empty($to)) {
5800 $to = implode(
',', $to);
5801 if (!empty($arraymessage->email_to)) {
5802 $to = $to.
','.$arraymessage->email_to;
5806 $errors_to = $conf->global->MAIN_MAIL_ERRORS_TO;
5808 $trackid =
'inv'.$tmpinvoice->id;
5809 $sendcontext =
'standard';
5812 if (!empty($arraymessage->email_tocc)) {
5813 $email_tocc = $arraymessage->email_tocc;
5817 if (!empty($arraymessage->email_tobcc)) {
5818 $email_tobcc = $arraymessage->email_tobcc;
5825 if ($arraymessage->joinfiles == 1 && !empty($tmpinvoice->last_main_doc)) {
5826 $joinFile[] = DOL_DATA_ROOT.
'/'.$tmpinvoice->last_main_doc;
5827 $joinFileName[] = basename($tmpinvoice->last_main_doc);
5828 $joinFileMime[] =
dol_mimetype(DOL_DATA_ROOT.
'/'.$tmpinvoice->last_main_doc);
5832 $cMailFile =
new CMailFile($sendTopic, $to, $from, $sendContent, $joinFile, $joinFileMime, $joinFileName, $email_tocc, $email_tobcc, 0, 1, $errors_to,
'', $trackid,
'', $sendcontext,
'');
5835 if ($cMailFile->sendfile()) {
5839 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
5844 $actioncomm->type_code =
'AC_OTH_AUTO';
5845 $actioncomm->socid = $tmpinvoice->thirdparty->id;
5846 $actioncomm->contact_id = 0;
5848 $actioncomm->code =
'AC_EMAIL';
5849 $actioncomm->label =
'sendEmailsRemindersOnInvoiceDueDateOK (nbdays='.$nbdays.
' paymentmode='.$paymentmode.
' template='.$template.
' datetouse='.$datetouse.
' forcerecipient='.$forcerecipient.
')';
5850 $actioncomm->note_private = $sendContent;
5851 $actioncomm->fk_project = $tmpinvoice->fk_project;
5852 $actioncomm->datep =
dol_now();
5853 $actioncomm->datef = $actioncomm->datep;
5854 $actioncomm->percentage = -1;
5855 $actioncomm->authorid = $user->id;
5856 $actioncomm->userownerid = $user->id;
5858 $actioncomm->email_msgid = $cMailFile->msgid;
5859 $actioncomm->email_subject = $sendTopic;
5860 $actioncomm->email_from = $from;
5861 $actioncomm->email_sender =
'';
5862 $actioncomm->email_to = $to;
5866 $actioncomm->errors_to = $errors_to;
5868 $actioncomm->elementtype =
'invoice';
5869 $actioncomm->fk_element = $tmpinvoice->id;
5873 $actioncomm->create($user);
5875 $errormesg = $cMailFile->error.
' : '.$to;
5879 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
5884 $actioncomm->type_code =
'AC_OTH_AUTO';
5885 $actioncomm->socid = $tmpinvoice->thirdparty->id;
5886 $actioncomm->contact_id = 0;
5888 $actioncomm->code =
'AC_EMAIL';
5889 $actioncomm->label =
'sendEmailsRemindersOnInvoiceDueDateKO';
5890 $actioncomm->note_private = $errormesg;
5891 $actioncomm->fk_project = $tmpinvoice->fk_project;
5892 $actioncomm->datep =
dol_now();
5893 $actioncomm->datef = $actioncomm->datep;
5894 $actioncomm->percentage = -1;
5895 $actioncomm->authorid = $user->id;
5896 $actioncomm->userownerid = $user->id;
5898 $actioncomm->email_msgid = $cMailFile->msgid;
5899 $actioncomm->email_from = $from;
5900 $actioncomm->email_sender =
'';
5901 $actioncomm->email_to = $to;
5905 $actioncomm->errors_to = $errors_to;
5909 $actioncomm->create($user);
5912 $this->db->commit();
5916 $errorsMsg[] = $errormesg;
5919 $errorsMsg[] =
'Failed to fetch record invoice with ID = '.$obj->id;
5923 $error += $loopError;
5930 $this->output .=
'Nb of emails sent : '.$nbMailSend;
5932 dol_syslog(__METHOD__.
" end - ".$this->output, LOG_INFO);
5936 $this->error =
'Nb of emails sent : '.$nbMailSend.
', '.(!empty($errorsMsg)) ? join(
', ', $errorsMsg) : $error;
5938 dol_syslog(__METHOD__.
" end - ".$this->error, LOG_INFO);
5953 $sql =
"SELECT datef";
5954 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture";
5955 $sql .=
" WHERE type = " . (int) $this->
type ;
5956 $sql .=
" AND date_valid IS NOT NULL";
5957 $sql .=
" AND entity IN (".getEntity(
'invoice').
")";
5958 $sql .=
" ORDER BY datef DESC LIMIT 1";
5960 $result = $this->db->query($sql);
5963 if ($this->db->num_rows($result)) {
5964 $obj = $this->db->fetch_object($result);
5965 $last_date = $this->db->jdate($obj->datef);
5966 $invoice_date = $this->date;
5968 $is_last_of_same_type = $invoice_date >= $last_date;
5969 if ($allow_validated_drafts) {
5973 return array($is_last_of_same_type, $last_date);
5996 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
5998 $return =
'<div class="box-flex-item box-flex-grow-zero">';
5999 $return .=
'<div class="info-box info-box-sm">';
6000 $return .=
'<span class="info-box-icon bg-infobox-action">';
6002 $return .=
'</span>';
6003 $return .=
'<div class="info-box-content">';
6004 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl(1) : $this->ref).
'</span>';
6005 if ($selected >= 0) {
6006 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
6008 if (!empty($arraydata[
'thirdparty'])) {
6009 $return .=
'<br><span class="info-box-label">'.$arraydata[
'thirdparty'].
'</span>';
6011 if (property_exists($this,
'date')) {
6012 $return .=
'<br><span class="info-box-label">'.dol_print_date($this->date,
'day').
'</span>';
6014 if (property_exists($this,
'total_ht')) {
6015 $return .=
' <span class="info-box-label amount" title="'.dol_escape_htmltag($langs->trans(
"AmountHT")).
'">'.
price($this->total_ht);
6016 $return .=
' '.$langs->trans(
"HT");
6017 $return .=
'</span>';
6019 if (method_exists($this,
'getLibStatut')) {
6020 $alreadypaid = (empty($arraydata[
'alreadypaid']) ? 0 : $arraydata[
'alreadypaid']);
6021 $return .=
'<br><div class="info-box-status">'.$this->getLibStatut(3, $alreadypaid).
'</div>';
6023 $return .=
'</div>';
6024 $return .=
'</div>';
6025 $return .=
'</div>';
6039 public $element =
'facturedet';
6044 public $table_element =
'facturedet';
6061 public $localtax1_type;
6062 public $localtax2_type;
6063 public $fk_remise_except;
6066 public $fk_fournprice;
6076 public $remise_percent;
6094 public $fk_warehouse;
6103 public $fk_code_ventilation = 0;
6109 public $skip_update_total;
6114 public $situation_percent;
6139 $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,';
6140 $sql .=
' fd.localtax1_tx, fd. localtax2_tx, fd.remise, fd.remise_percent, fd.fk_remise_except, fd.subprice, fd.ref_ext,';
6141 $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,';
6142 $sql .=
' fd.info_bits, fd.special_code, fd.total_ht, fd.total_tva, fd.total_ttc, fd.total_localtax1, fd.total_localtax2, fd.rang,';
6143 $sql .=
' fd.fk_code_ventilation,';
6144 $sql .=
' fd.fk_unit, fd.fk_user_author, fd.fk_user_modif,';
6145 $sql .=
' fd.situation_percent, fd.fk_prev_id,';
6146 $sql .=
' fd.multicurrency_subprice,';
6147 $sql .=
' fd.multicurrency_total_ht,';
6148 $sql .=
' fd.multicurrency_total_tva,';
6149 $sql .=
' fd.multicurrency_total_ttc,';
6150 $sql .=
' p.ref as product_ref, p.label as product_label, p.description as product_desc';
6151 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facturedet as fd';
6152 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON fd.fk_product = p.rowid';
6153 $sql .=
' WHERE fd.rowid = '.((int) $rowid);
6155 $result = $this->db->query($sql);
6157 $objp = $this->db->fetch_object($result);
6160 $this->error =
'InvoiceLine with id '. $rowid .
' not found sql='.$sql;
6164 $this->
rowid = $objp->rowid;
6165 $this->
id = $objp->rowid;
6166 $this->fk_facture = $objp->fk_facture;
6167 $this->fk_parent_line = $objp->fk_parent_line;
6168 $this->label = $objp->custom_label;
6169 $this->desc = $objp->description;
6170 $this->qty = $objp->qty;
6171 $this->subprice = $objp->subprice;
6172 $this->ref_ext = $objp->ref_ext;
6173 $this->vat_src_code = $objp->vat_src_code;
6174 $this->tva_tx = $objp->tva_tx;
6175 $this->localtax1_tx = $objp->localtax1_tx;
6176 $this->localtax2_tx = $objp->localtax2_tx;
6177 $this->remise_percent = $objp->remise_percent;
6178 $this->fk_remise_except = $objp->fk_remise_except;
6179 $this->fk_product = $objp->fk_product;
6180 $this->product_type = $objp->product_type;
6181 $this->date_start = $this->db->jdate($objp->date_start);
6182 $this->date_end = $this->db->jdate($objp->date_end);
6183 $this->info_bits = $objp->info_bits;
6184 $this->tva_npr = ($objp->info_bits & 1 == 1) ? 1 : 0;
6185 $this->special_code = $objp->special_code;
6186 $this->total_ht = $objp->total_ht;
6187 $this->total_tva = $objp->total_tva;
6188 $this->total_localtax1 = $objp->total_localtax1;
6189 $this->total_localtax2 = $objp->total_localtax2;
6190 $this->total_ttc = $objp->total_ttc;
6191 $this->fk_code_ventilation = $objp->fk_code_ventilation;
6192 $this->rang = $objp->rang;
6193 $this->fk_fournprice = $objp->fk_fournprice;
6194 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $this->fk_fournprice, $objp->pa_ht);
6195 $this->pa_ht = $marginInfos[0];
6196 $this->marge_tx = $marginInfos[1];
6197 $this->marque_tx = $marginInfos[2];
6199 $this->
ref = $objp->product_ref;
6201 $this->product_ref = $objp->product_ref;
6202 $this->product_label = $objp->product_label;
6203 $this->product_desc = $objp->product_desc;
6205 $this->fk_unit = $objp->fk_unit;
6206 $this->fk_user_modif = $objp->fk_user_modif;
6207 $this->fk_user_author = $objp->fk_user_author;
6209 $this->situation_percent = $objp->situation_percent;
6210 $this->fk_prev_id = $objp->fk_prev_id;
6212 $this->multicurrency_subprice = $objp->multicurrency_subprice;
6213 $this->multicurrency_total_ht = $objp->multicurrency_total_ht;
6214 $this->multicurrency_total_tva = $objp->multicurrency_total_tva;
6215 $this->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
6219 $this->db->free($result);
6223 $this->error = $this->db->lasterror();
6235 public function insert($notrigger = 0, $noerrorifdiscountalreadylinked = 0)
6237 global $langs, $user, $conf;
6241 $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht ==
'');
6243 dol_syslog(get_class($this).
"::insert rang=".$this->rang, LOG_DEBUG);
6246 $this->desc = trim($this->desc);
6247 if (empty($this->tva_tx)) {
6250 if (empty($this->localtax1_tx)) {
6251 $this->localtax1_tx = 0;
6253 if (empty($this->localtax2_tx)) {
6254 $this->localtax2_tx = 0;
6256 if (empty($this->localtax1_type)) {
6257 $this->localtax1_type = 0;
6259 if (empty($this->localtax2_type)) {
6260 $this->localtax2_type = 0;
6262 if (empty($this->total_localtax1)) {
6263 $this->total_localtax1 = 0;
6265 if (empty($this->total_localtax2)) {
6266 $this->total_localtax2 = 0;
6268 if (empty($this->rang)) {
6271 if (empty($this->remise_percent)) {
6272 $this->remise_percent = 0;
6274 if (empty($this->info_bits)) {
6275 $this->info_bits = 0;
6277 if (empty($this->subprice)) {
6278 $this->subprice = 0;
6280 if (empty($this->ref_ext)) {
6281 $this->ref_ext =
'';
6283 if (empty($this->special_code)) {
6284 $this->special_code = 0;
6286 if (empty($this->fk_parent_line)) {
6287 $this->fk_parent_line = 0;
6289 if (empty($this->fk_prev_id)) {
6290 $this->fk_prev_id = 0;
6292 if (!isset($this->situation_percent) || $this->situation_percent > 100 || (
string) $this->situation_percent ==
'') {
6293 $this->situation_percent = 100;
6296 if (empty($this->pa_ht)) {
6299 if (empty($this->multicurrency_subprice)) {
6300 $this->multicurrency_subprice = 0;
6302 if (empty($this->multicurrency_total_ht)) {
6303 $this->multicurrency_total_ht = 0;
6305 if (empty($this->multicurrency_total_tva)) {
6306 $this->multicurrency_total_tva = 0;
6308 if (empty($this->multicurrency_total_ttc)) {
6309 $this->multicurrency_total_ttc = 0;
6313 if ($this->pa_ht == 0 && $pa_ht_isemptystring) {
6314 if (($result = $this->
defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0) {
6317 $this->pa_ht = $result;
6322 if ($this->product_type < 0) {
6323 $this->error =
'ErrorProductTypeMustBe0orMore';
6326 if (!empty($this->fk_product) && $this->fk_product > 0) {
6330 $this->error =
'ErrorProductIdDoesNotExists';
6331 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6339 $sql =
'INSERT INTO '.MAIN_DB_PREFIX.
'facturedet';
6340 $sql .=
' (fk_facture, fk_parent_line, label, description, qty,';
6341 $sql .=
' vat_src_code, tva_tx, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type,';
6342 $sql .=
' fk_product, product_type, remise_percent, subprice, ref_ext, fk_remise_except,';
6343 $sql .=
' date_start, date_end, fk_code_ventilation, ';
6344 $sql .=
' rang, special_code, fk_product_fournisseur_price, buy_price_ht,';
6345 $sql .=
' info_bits, total_ht, total_tva, total_ttc, total_localtax1, total_localtax2,';
6346 $sql .=
' situation_percent, fk_prev_id,';
6347 $sql .=
' fk_unit, fk_user_author, fk_user_modif,';
6348 $sql .=
' fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc';
6350 $sql .=
" VALUES (".$this->fk_facture.
",";
6351 $sql .=
" ".($this->fk_parent_line > 0 ? $this->fk_parent_line :
"null").
",";
6352 $sql .=
" ".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null").
",";
6353 $sql .=
" '".$this->db->escape($this->desc).
"',";
6354 $sql .=
" ".price2num($this->qty).
",";
6355 $sql .=
" ".(empty($this->vat_src_code) ?
"''" :
"'".$this->db->escape($this->vat_src_code).
"'").
",";
6356 $sql .=
" ".price2num($this->tva_tx).
",";
6357 $sql .=
" ".price2num($this->localtax1_tx).
",";
6358 $sql .=
" ".price2num($this->localtax2_tx).
",";
6359 $sql .=
" '".$this->db->escape($this->localtax1_type).
"',";
6360 $sql .=
" '".$this->db->escape($this->localtax2_type).
"',";
6361 $sql .=
' '.((!empty($this->fk_product) && $this->fk_product > 0) ? $this->fk_product :
"null").
',';
6362 $sql .=
" ".((int) $this->product_type).
",";
6363 $sql .=
" ".price2num($this->remise_percent).
",";
6364 $sql .=
" ".price2num($this->subprice).
",";
6365 $sql .=
" '".$this->db->escape($this->ref_ext).
"',";
6366 $sql .=
' '.(!empty($this->fk_remise_except) ? $this->fk_remise_except :
"null").
',';
6367 $sql .=
" ".(!empty($this->date_start) ?
"'".$this->db->idate($this->date_start).
"'" :
"null").
",";
6368 $sql .=
" ".(!empty($this->date_end) ?
"'".$this->db->idate($this->date_end).
"'" :
"null").
",";
6369 $sql .=
' '.((int) $this->fk_code_ventilation).
',';
6370 $sql .=
' '.((int) $this->rang).
',';
6371 $sql .=
' '.((int) $this->special_code).
',';
6372 $sql .=
' '.(!empty($this->fk_fournprice) ? $this->fk_fournprice :
"null").
',';
6373 $sql .=
' '.price2num($this->pa_ht).
',';
6374 $sql .=
" '".$this->db->escape($this->info_bits).
"',";
6375 $sql .=
" ".price2num($this->total_ht).
",";
6376 $sql .=
" ".price2num($this->total_tva).
",";
6377 $sql .=
" ".price2num($this->total_ttc).
",";
6378 $sql .=
" ".price2num($this->total_localtax1).
",";
6379 $sql .=
" ".price2num($this->total_localtax2);
6380 $sql .=
", ".((float) $this->situation_percent);
6381 $sql .=
", ".(!empty($this->fk_prev_id) ? $this->fk_prev_id :
"null");
6382 $sql .=
", ".(!$this->fk_unit ?
'NULL' : $this->fk_unit);
6383 $sql .=
", ".((int) $user->id);
6384 $sql .=
", ".((int) $user->id);
6385 $sql .=
", ".(int) $this->fk_multicurrency;
6386 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
6387 $sql .=
", ".price2num($this->multicurrency_subprice);
6388 $sql .=
", ".price2num($this->multicurrency_total_ht);
6389 $sql .=
", ".price2num($this->multicurrency_total_tva);
6390 $sql .=
", ".price2num($this->multicurrency_total_ttc);
6393 dol_syslog(get_class($this).
"::insert", LOG_DEBUG);
6394 $resql = $this->db->query($sql);
6396 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
'facturedet');
6397 $this->
rowid = $this->id;
6408 if ($this->fk_remise_except && empty($error)) {
6410 $result = $discount->fetch($this->fk_remise_except);
6415 if ($discount->fk_facture_line > 0) {
6416 if (empty($noerrorifdiscountalreadylinked)) {
6417 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed", $discount->id);
6418 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6419 $this->db->rollback();
6423 $result = $discount->link_to_invoice($this->
rowid, 0);
6425 $this->error = $discount->error;
6426 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6427 $this->db->rollback();
6432 $this->error = $langs->trans(
"ErrorADiscountThatHasBeenRemovedIsIncluded");
6433 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6434 $this->db->rollback();
6438 $this->error = $discount->error;
6439 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6440 $this->db->rollback();
6445 if (!$notrigger && empty($error)) {
6447 $result = $this->
call_trigger(
'LINEBILL_INSERT', $user);
6449 $this->db->rollback();
6456 $this->db->commit();
6460 foreach ($this->errors as $errmsg) {
6461 dol_syslog(get_class($this).
"::insert ".$errmsg, LOG_ERR);
6462 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
6464 $this->db->rollback();
6467 $this->error = $this->db->lasterror();
6468 $this->db->rollback();
6480 public function update($user =
null, $notrigger = 0)
6482 global $user, $conf;
6486 $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht ==
'');
6489 $this->desc = trim($this->desc);
6490 if (empty($this->ref_ext)) {
6491 $this->ref_ext =
'';
6493 if (empty($this->tva_tx)) {
6496 if (empty($this->localtax1_tx)) {
6497 $this->localtax1_tx = 0;
6499 if (empty($this->localtax2_tx)) {
6500 $this->localtax2_tx = 0;
6502 if (empty($this->localtax1_type)) {
6503 $this->localtax1_type = 0;
6505 if (empty($this->localtax2_type)) {
6506 $this->localtax2_type = 0;
6508 if (empty($this->total_localtax1)) {
6509 $this->total_localtax1 = 0;
6511 if (empty($this->total_localtax2)) {
6512 $this->total_localtax2 = 0;
6514 if (empty($this->remise_percent)) {
6515 $this->remise_percent = 0;
6517 if (empty($this->info_bits)) {
6518 $this->info_bits = 0;
6520 if (empty($this->special_code)) {
6521 $this->special_code = 0;
6523 if (empty($this->product_type)) {
6524 $this->product_type = 0;
6526 if (empty($this->fk_parent_line)) {
6527 $this->fk_parent_line = 0;
6529 if (!isset($this->situation_percent) || $this->situation_percent > 100 || (
string) $this->situation_percent ==
'') {
6530 $this->situation_percent = 100;
6532 if (empty($this->pa_ht)) {
6536 if (empty($this->multicurrency_subprice)) {
6537 $this->multicurrency_subprice = 0;
6539 if (empty($this->multicurrency_total_ht)) {
6540 $this->multicurrency_total_ht = 0;
6542 if (empty($this->multicurrency_total_tva)) {
6543 $this->multicurrency_total_tva = 0;
6545 if (empty($this->multicurrency_total_ttc)) {
6546 $this->multicurrency_total_ttc = 0;
6550 if ($this->product_type < 0) {
6555 if ($this->pa_ht == 0 && $pa_ht_isemptystring) {
6557 $result = $this->
defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product);
6561 $this->pa_ht = $result;
6568 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facturedet SET";
6569 $sql .=
" description='".$this->db->escape($this->desc).
"'";
6570 $sql .=
", ref_ext='".$this->db->escape($this->ref_ext).
"'";
6571 $sql .=
", label=".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null");
6572 $sql .=
", subprice=".price2num($this->subprice);
6573 $sql .=
", remise_percent=".price2num($this->remise_percent);
6574 if ($this->fk_remise_except) {
6575 $sql .=
", fk_remise_except=".$this->fk_remise_except;
6577 $sql .=
", fk_remise_except=null";
6579 $sql .=
", vat_src_code = '".(empty($this->vat_src_code) ?
'' : $this->db->escape($this->vat_src_code)).
"'";
6580 $sql .=
", tva_tx=".price2num($this->tva_tx);
6581 $sql .=
", localtax1_tx=".price2num($this->localtax1_tx);
6582 $sql .=
", localtax2_tx=".price2num($this->localtax2_tx);
6583 $sql .=
", localtax1_type='".$this->db->escape($this->localtax1_type).
"'";
6584 $sql .=
", localtax2_type='".$this->db->escape($this->localtax2_type).
"'";
6585 $sql .=
", qty=".price2num($this->qty);
6586 $sql .=
", date_start=".(!empty($this->date_start) ?
"'".$this->db->idate($this->date_start).
"'" :
"null");
6587 $sql .=
", date_end=".(!empty($this->date_end) ?
"'".$this->db->idate($this->date_end).
"'" :
"null");
6588 $sql .=
", product_type=".$this->product_type;
6589 $sql .=
", info_bits='".$this->db->escape($this->info_bits).
"'";
6590 $sql .=
", special_code='".$this->db->escape($this->special_code).
"'";
6591 if (empty($this->skip_update_total)) {
6592 $sql .=
", total_ht=".price2num($this->total_ht);
6593 $sql .=
", total_tva=".price2num($this->total_tva);
6594 $sql .=
", total_ttc=".price2num($this->total_ttc);
6595 $sql .=
", total_localtax1=".price2num($this->total_localtax1);
6596 $sql .=
", total_localtax2=".price2num($this->total_localtax2);
6598 $sql .=
", fk_product_fournisseur_price=".(!empty($this->fk_fournprice) ?
"'".$this->db->escape($this->fk_fournprice).
"'" :
"null");
6599 $sql .=
", buy_price_ht=".(($this->pa_ht || (string) $this->pa_ht ===
'0') ?
price2num($this->pa_ht) :
"null");
6600 $sql .=
", fk_parent_line=".($this->fk_parent_line > 0 ? $this->fk_parent_line :
"null");
6601 if (!empty($this->rang)) {
6602 $sql .=
", rang=".((int) $this->rang);
6604 $sql .=
", situation_percent = ".((float) $this->situation_percent);
6605 $sql .=
", fk_unit = ".(!$this->fk_unit ?
'NULL' : $this->fk_unit);
6606 $sql .=
", fk_user_modif = ".((int) $user->id);
6609 $sql .=
", multicurrency_subprice=".price2num($this->multicurrency_subprice);
6610 $sql .=
", multicurrency_total_ht=".price2num($this->multicurrency_total_ht);
6611 $sql .=
", multicurrency_total_tva=".price2num($this->multicurrency_total_tva);
6612 $sql .=
", multicurrency_total_ttc=".price2num($this->multicurrency_total_ttc);
6614 $sql .=
" WHERE rowid = ".((int) $this->
rowid);
6616 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
6617 $resql = $this->db->query($sql);
6620 $this->
id = $this->rowid;
6627 if (!$error && !$notrigger) {
6629 $result = $this->
call_trigger(
'LINEBILL_MODIFY', $user);
6631 $this->db->rollback();
6638 $this->db->commit();
6642 foreach ($this->errors as $errmsg) {
6643 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
6644 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
6646 $this->db->rollback();
6649 $this->error = $this->db->error();
6650 $this->db->rollback();
6662 public function delete($tmpuser =
null, $notrigger =
false)
6669 if (empty($notrigger)) {
6670 $result = $this->
call_trigger(
'LINEBILL_DELETE', $user);
6672 $this->db->rollback();
6681 $this->db->rollback();
6686 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
6687 $sql .=
' SET fk_facture_line = NULL';
6688 $sql .=
' WHERE fk_facture_line = '.((int) $this->
id);
6690 dol_syslog(get_class($this).
"::deleteline", LOG_DEBUG);
6691 $result = $this->db->query($sql);
6693 $this->error = $this->db->error();
6694 $this->errors[] = $this->error;
6695 $this->db->rollback();
6699 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'element_time';
6700 $sql .=
' SET invoice_id = NULL, invoice_line_id = NULL';
6701 $sql .=
' WHERE invoice_line_id = '.((int) $this->
id);
6702 if (!$this->db->query($sql)) {
6703 $this->error = $this->db->error().
" sql=".$sql;
6704 $this->errors[] = $this->error;
6705 $this->db->rollback();
6709 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"facturedet WHERE rowid = ".((int) $this->
id);
6711 if ($this->db->query($sql)) {
6712 $this->db->commit();
6715 $this->error = $this->db->error().
" sql=".$sql;
6716 $this->errors[] = $this->error;
6717 $this->db->rollback();
6733 dol_syslog(get_class($this).
"::update_total", LOG_DEBUG);
6736 if (empty($this->total_localtax1)) {
6737 $this->total_localtax1 = 0;
6739 if (empty($this->total_localtax2)) {
6740 $this->total_localtax2 = 0;
6744 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facturedet SET";
6745 $sql .=
" total_ht=".price2num($this->total_ht);
6746 $sql .=
",total_tva=".price2num($this->total_tva);
6747 $sql .=
",total_localtax1=".price2num($this->total_localtax1);
6748 $sql .=
",total_localtax2=".price2num($this->total_localtax2);
6749 $sql .=
",total_ttc=".price2num($this->total_ttc);
6750 $sql .=
" WHERE rowid = ".((int) $this->
rowid);
6752 dol_syslog(get_class($this).
"::update_total", LOG_DEBUG);
6754 $resql = $this->db->query($sql);
6756 $this->db->commit();
6759 $this->error = $this->db->error();
6760 $this->db->rollback();
6777 global $invoicecache;
6779 if (is_null($this->fk_prev_id) || empty($this->fk_prev_id) || $this->fk_prev_id ==
"") {
6783 if (!isset($invoicecache[$invoiceid])) {
6784 $invoicecache[$invoiceid] =
new Facture($this->db);
6785 $invoicecache[$invoiceid]->fetch($invoiceid);
6791 $sql =
"SELECT situation_percent FROM ".MAIN_DB_PREFIX.
"facturedet WHERE rowid = ".((int) $this->fk_prev_id);
6792 $resql = $this->db->query($sql);
6793 if ($resql && $this->db->num_rows($resql) > 0) {
6794 $res = $this->db->fetch_array($resql);
6796 $returnPercent = (float) $res[
'situation_percent'];
6798 if ($include_credit_note) {
6799 $sql =
'SELECT fd.situation_percent FROM '.MAIN_DB_PREFIX.
'facturedet fd';
6800 $sql .=
' JOIN '.MAIN_DB_PREFIX.
'facture f ON (f.rowid = fd.fk_facture) ';
6801 $sql .=
" WHERE fd.fk_prev_id = ".((int) $this->fk_prev_id);
6802 $sql .=
" AND f.situation_cycle_ref = ".((int) $invoicecache[$invoiceid]->situation_cycle_ref);
6803 $sql .=
" AND f.type = ".Facture::TYPE_CREDIT_NOTE;
6805 $res = $this->db->query($sql);
6807 while ($obj = $this->db->fetch_object($res)) {
6808 $returnPercent = $returnPercent + (float) $obj->situation_percent;
6815 return $returnPercent;
6817 $this->error = $this->db->error();
6818 dol_syslog(get_class($this).
"::select Error ".$this->error, LOG_ERR);
6819 $this->db->rollback();
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Class to manage agenda events (actions)
Class to send emails (with attachments or not) Usage: $mailfile = new CMailFile($subject,...
Superclass for invoices classes.
getSommePaiement($multicurrency=0)
Return amount of payments already done.
calculate_date_lim_reglement($cond_reglement=0)
Returns an invoice payment deadline based on the invoice settlement conditions and billing date.
is_erasable()
Return if an invoice can be deleted Rule is: If invoice is draft and has a temporary ref -> yes (1) I...
Parent class of all other business classes for details of elements (invoices, contracts,...
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
line_order($renum=false, $rowidorder='ASC', $fk_parent_line=true)
Save a new position (field rang) for details lines.
deleteEcmFiles($mode=0)
Delete related files of object in database.
add_object_linked($origin=null, $origin_id=null, $f_user=null, $notrigger=0)
Add an object link into llx_element_element.
defineBuyPrice($unitPrice=0.0, $discountPercent=0.0, $fk_product=0)
Get buy price to use for margin calculation.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty.
getIdContact($source, $code, $status=0)
Return id of contacts for a source and a contact code.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid=0, $f_user=null, $notrigger=0)
Delete all links between an object $this.
setErrorsFromObject($object)
setErrorsFromObject
static isExistingObject($element, $id, $ref='', $ref_ext='')
Check an object id/ref exists If you don't need/want to instantiate object and just need to know if o...
updateRangOfLine($rowid, $rang)
Update position of line (rang)
update_price($exclspec=0, $roundingadjust='none', $nodatabaseupdate=0, $seller=null)
Update total_ht, total_ttc, total_vat, total_localtax1, total_localtax2 for an object (sum of lines).
deleteExtraFields()
Delete all extra fields values for the current object.
fetchObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $clause='OR', $alsosametype=1, $orderby='sourcetype', $loadalsoobjects=1)
Fetch array of objects linked to current object (object of enabled modules only).
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
static commonReplaceProduct(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a product id with another one.
line_max($fk_parent_line=0)
Get max value used for position of line (rang)
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
delete_linked_contact($source='', $code='')
Delete all links between an object $this and all its contacts in llx_element_contact.
call_trigger($triggerName, $user)
Call trigger based on this instance.
add_contact($fk_socpeople, $type_contact, $source='external', $notrigger=0)
Add a link between element $this->element and a contact.
Class to manage absolute discounts.
Class to manage Dolibarr database access.
Class to manage warehouses.
Class to manage shipments.
Class to manage invoices.
createFromClone(User $user, $fromid=0)
Load an object from its id and create a new one in database.
setDraft($user, $idwarehouse=-1)
Set draft status.
$fk_facture_source
id of source invoice if replacement invoice or credit note
getIdShippingContact()
Retourne id des contacts clients de livraison.
setFinal(User $user, $notrigger=0)
Sets the invoice as a final situation.
setCanceled($user, $close_code='', $close_note='')
Tag invoice as canceled, with no payment on it (example for replacement invoice or payment never rece...
static createDepositFromOrigin(CommonObject $origin, $date, $payment_terms_id, User $user, $notrigger=0, $autoValidateDeposit=false, $overrideFields=array())
Creates a deposit from a proposal or an order by grouping lines by VAT rates.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
list_replacable_invoices($socid=0)
Return list of invoices qualified to be replaced by another invoice.
insert_discount($idremise)
Add a discount line into an invoice (as an invoice line) using an existing absolute discount (Consume...
createFromOrder($object, User $user)
Load an object from an order and create a new invoice into database.
load_state_board()
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
willBeLastOfSameType($allow_validated_drafts=false)
See if current invoice date is posterior to the last invoice date among validated invoices of same ty...
update_percent($line, $percent, $update_price=true)
Update invoice line with percentage.
const TYPE_REPLACEMENT
Replacement invoice.
validate($user, $force_number='', $idwarehouse=0, $notrigger=0, $batch_rule=0)
Tag invoice as validated + call trigger BILL_VALIDATE Object must have lines loaded with fetch_lines.
deleteline($rowid, $id=0)
Delete line in database.
update(User $user, $notrigger=0)
Update database.
fetch_lines($only_product=0, $loadalsotranslation=0)
Load all detailed lines into this->lines.
$fk_fac_rec_source
id of template invoice when generated from a template invoice
liste_array($shortlist=0, $draft=0, $excluser=null, $socid=0, $limit=0, $offset=0, $sortfield='f.datef, f.rowid', $sortorder='DESC')
Return list of invoices (eventually filtered on a user) into an array.
getIdBillingContact()
Retourne id des contacts clients de facturation.
__construct(DoliDB $db)
Constructor.
const STATUS_DRAFT
Draft status.
updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $txtva, $txlocaltax1=0, $txlocaltax2=0, $price_base_type='HT', $info_bits=0, $type=self::TYPE_STANDARD, $fk_parent_line=0, $skip_update_total=0, $fk_fournprice=null, $pa_ht=0, $label='', $special_code=0, $array_options=array(), $situation_percent=100, $fk_unit=null, $pu_ht_devise=0, $notrigger=0, $ref_ext='', $rang=0)
Update a detail line.
getNomUrl($withpicto=0, $option='', $max=0, $short=0, $moretitle='', $notooltip=0, $addlinktonotes=0, $save_lastsearch_value=-1, $target='')
Return clicable link of object (with eventually picto)
load_board($user)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
fetchPreviousNextSituationInvoice()
Fetch previous and next situations invoices.
fetch($rowid, $ref='', $ref_ext='', $notused=0, $fetch_situation=false)
Get object from database.
const TYPE_STANDARD
Standard invoice.
const TYPE_SITUATION
Situation invoice.
$paye
1 if invoice paid COMPLETELY, 0 otherwise (do not use it anymore, use statut and close_code)
updatePriceNextInvoice(&$langs)
Update price of next invoice.
static replaceProduct(DoliDB $db, $origin_id, $dest_id)
Function used to replace a product id with another one.
setRetainedWarrantyDateLimit($timestamp, $dateYmd='')
Change the retained_warranty_date_limit.
$pos_source
key of pos source ('0', '1', ...)
sendEmailsRemindersOnInvoiceDueDate($nbdays=0, $paymentmode='all', $template='', $datetouse='duedate', $forcerecipient='')
Send reminders by emails for invoices validated that are due.
info($id)
Load miscellaneous information for tab "Info".
const TYPE_PROFORMA
Proforma invoice (should not be used.
addline( $desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $date_start='', $date_end='', $ventil=0, $info_bits=0, $fk_remise_except=0, $price_base_type='HT', $pu_ttc=0, $type=0, $rang=-1, $special_code=0, $origin='', $origin_id=0, $fk_parent_line=0, $fk_fournprice=null, $pa_ht=0, $label='', $array_options=array(), $situation_percent=100, $fk_prev_id=0, $fk_unit=null, $pu_ht_devise=0, $ref_ext='', $noupdateafterinsertline=0)
Add an invoice line into database (linked to product/service or not).
getKanbanView($option='', $arraydata=null)
Return clicable link of object (with eventually picto)
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
setRetainedWarranty($value)
Change the retained warranty.
get_prev_sits()
Returns an array containing the previous situations as Facture objects.
list_qualified_avoir_invoices($socid=0)
Return list of invoices qualified to be corrected by a credit note.
set_canceled($user, $close_code='', $close_note='')
Tag invoice as canceled, with no payment on it (example for replacement invoice or payment never rece...
newCycle()
Gets the smallest reference available for a new cycle.
setDiscount($user, $remise, $notrigger=0)
Set percent discount.
set_ref_client($ref_client, $notrigger=0)
Set customer ref.
is_first()
Checks if the invoice is the first of a cycle.
set_remise($user, $remise, $notrigger=0)
Set percent discount.
getTooltipContentArray($params)
getTooltipContentArray
getNextNumRef($soc, $mode='next')
Set absolute discount.
checkProgressLine($idline, $situation_percent)
Check if the percent edited is lower of next invoice line.
const STATUS_VALIDATED
Validated (need to be paid)
hasDelay()
Is the customer invoice delayed?
getLinesArray()
Create an array of invoice lines.
set_unpaid($user)
Tag la facture comme non payee completement + appel trigger BILL_UNPAYED Fonction utilisee quand un p...
const TYPE_DEPOSIT
Deposit invoice.
set_paid($user, $close_code='', $close_note='')
Tag the invoice as paid completely (if close_code is filled) => this->fk_statut=2,...
const STATUS_ABANDONED
Classified abandoned and no payment done.
createFromCurrent(User $user, $invertdetail=0)
Create a new invoice in database from current invoice.
setPaid($user, $close_code='', $close_note='')
Tag the invoice as :
displayRetainedWarranty()
Currently used for documents generation : to know if retained warranty need to be displayed.
const TYPE_CREDIT_NOTE
Credit note invoice.
is_last_in_cycle()
Checks if the invoice is the last in its cycle.
initAsSpecimen($option='')
Initialise an instance with random values.
getRetainedWarrantyAmount($rounding=-1)
create(User $user, $notrigger=0, $forceduedate=0)
Create invoice in database.
$module_source
key of module source when invoice generated from a dedicated module ('cashdesk', 'takepos',...
setUnpaid($user)
Tag la facture comme non payee completement + appel trigger BILL_UNPAYED Fonction utilisee quand un p...
const STATUS_CLOSED
Classified paid.
createFromContract($object, User $user, $lines=array())
Load an object from an order and create a new invoice into database.
Class to manage invoice lines.
$fk_parent_line
Id parent line.
$special_code
List of special options to define line: 1: shipment cost lines 2: ecotaxe 3: ?? idofmodule: a meaning...
insert($notrigger=0, $noerrorifdiscountalreadylinked=0)
Insert line into database.
get_prev_progress($invoiceid, $include_credit_note=true)
Returns situation_percent of the previous line.
fetch($rowid)
Load invoice line from database.
update($user=null, $notrigger=0)
Update line into database.
$fk_facture
From llx_facturedet Id facture.
__construct($db)
Constructor.
update_total()
Update DB line fields total_xxx Used by migration.
Class to manage invoice templates.
Class to manage stock movements.
static getIdFromCode($dbs, $code)
Get id of currency from code.
static getIdAndTxFromCode($dbs, $code, $date_document='')
Get id and rate of currency from code.
Class to manage predefined suppliers products.
Class to manage products or services.
Manage record for batch number management.
const BATCH_RULE_SELLBY_EATBY_DATES_FIRST
Batches rules.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
hasRight($module, $permlevel1, $permlevel2='')
Return if a user has a permission.
dol_get_first_hour($date, $gm='tzserver')
Return GMT time for first hour of a given GMT date (it removes hours, min and second part)
dol_get_last_hour($date, $gm='tzserver')
Return GMT time for last hour of a given GMT date (it replaces hours, min and second part to 23:59:59...
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
dol_get_next_month($month, $year)
Return next month.
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
dol_delete_preview($object)
Delete all preview files linked to object instance.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
dol_mimetype($file, $default='application/octet-stream', $mode=0)
Return MIME type of a file from its name with extension.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null, $include=null)
Return array of possible common substitutions.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
getDictionaryValue($tablename, $field, $id, $checkentity=false, $rowidfield='rowid')
Return the value of a filed into a dictionary for the record $id.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall right right takeposterminal SELECT e rowid
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall right right takeposterminal SELECT e e e e e statut
getMarginInfos($pvht, $remise_percent, $tva_tx, $localtax1_tx, $localtax2_tx, $fk_pa, $paht)
Return an array with margins information of a line.
calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller='', $localtaxes_array='', $progress=100, $multicurrency_tx=1, $pu_devise=0, $multicurrency_code='')
Calculate totals (net, vat, ...) of a line.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type