44require_once DOL_DOCUMENT_ROOT.
'/core/class/commoninvoice.class.php';
45require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobjectline.class.php';
46require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
47require_once DOL_DOCUMENT_ROOT.
'/societe/class/client.class.php';
48require_once DOL_DOCUMENT_ROOT.
'/margin/lib/margins.lib.php';
49require_once DOL_DOCUMENT_ROOT.
'/multicurrency/class/multicurrency.class.php';
51if (isModEnabled(
'accounting')) {
52 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formaccounting.class.php';
54if (isModEnabled(
'accounting')) {
55 require_once DOL_DOCUMENT_ROOT.
'/accountancy/class/accountingaccount.class.php';
66 public $element =
'facture';
71 public $table_element =
'facture';
76 public $table_element_line =
'facturedet';
81 public $class_element_line =
'FactureLigne';
86 public $fk_element =
'fk_facture';
91 public $picto =
'bill';
97 public $ismultientitymanaged = 1;
102 public $isextrafieldmanaged = 1;
108 public $restrictiononfksoc = 1;
127 public $fk_user_author;
139 public $fk_user_valid;
144 public $fk_user_modif;
151 public $delivery_date;
163 public $ref_customer;
167 public $total_localtax1;
168 public $total_localtax2;
170 public $revenuestamp;
187 public $linked_objects = array();
197 public $lines = array();
203 public $extraparams = array();
210 public $date_pointoftax;
216 public $situation_cycle_ref;
221 public $situation_counter;
226 public $situation_final;
231 public $tab_previous_situation_invoice = array();
236 public $tab_next_situation_invoice = array();
246 public $retained_warranty;
251 public $retained_warranty_date_limit;
256 public $retained_warranty_fk_cond_reglement;
261 public $availability_id;
263 public $date_closing;
273 public $remise_percent;
304 public $fields = array(
305 'rowid' =>array(
'type'=>
'integer',
'label'=>
'TechnicalID',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>1),
306 'ref' =>array(
'type'=>
'varchar(30)',
'label'=>
'Ref',
'enabled'=>1,
'visible'=>1,
'notnull'=>1,
'showoncombobox'=>1,
'position'=>5),
307 'entity' =>array(
'type'=>
'integer',
'label'=>
'Entity',
'default'=>1,
'enabled'=>1,
'visible'=>-2,
'notnull'=>1,
'position'=>20,
'index'=>1),
308 'ref_client' =>array(
'type'=>
'varchar(255)',
'label'=>
'RefCustomer',
'enabled'=>1,
'visible'=>-1,
'position'=>10),
309 'ref_ext' =>array(
'type'=>
'varchar(255)',
'label'=>
'Ref ext',
'enabled'=>1,
'visible'=>0,
'position'=>12),
310 'type' =>array(
'type'=>
'smallint(6)',
'label'=>
'Type',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>15),
311 'subtype' =>array(
'type'=>
'smallint(6)',
'label'=>
'InvoiceSubtype',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>15),
313 'fk_soc' =>array(
'type'=>
'integer:Societe:societe/class/societe.class.php',
'label'=>
'ThirdParty',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>50),
314 'datef' =>array(
'type'=>
'date',
'label'=>
'DateInvoice',
'enabled'=>1,
'visible'=>1,
'position'=>20),
315 'date_valid' =>array(
'type'=>
'date',
'label'=>
'DateValidation',
'enabled'=>1,
'visible'=>-1,
'position'=>22),
316 'date_lim_reglement' =>array(
'type'=>
'date',
'label'=>
'DateDue',
'enabled'=>1,
'visible'=>1,
'position'=>25),
317 'date_closing' =>array(
'type'=>
'datetime',
'label'=>
'Date closing',
'enabled'=>1,
'visible'=>-1,
'position'=>30),
318 'paye' =>array(
'type'=>
'smallint(6)',
'label'=>
'InvoicePaidCompletely',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>80),
323 'close_code' =>array(
'type'=>
'varchar(16)',
'label'=>
'EarlyClosingReason',
'enabled'=>1,
'visible'=>-1,
'position'=>92),
324 'close_note' =>array(
'type'=>
'varchar(128)',
'label'=>
'EarlyClosingComment',
'enabled'=>1,
'visible'=>-1,
'position'=>93),
325 'total_ht' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountHT',
'enabled'=>1,
'visible'=>1,
'position'=>95,
'isameasure'=>1),
326 'total_tva' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountVAT',
'enabled'=>1,
'visible'=>-1,
'position'=>100,
'isameasure'=>1),
327 'localtax1' =>array(
'type'=>
'double(24,8)',
'label'=>
'LT1',
'enabled'=>1,
'visible'=>-1,
'position'=>110,
'isameasure'=>1),
328 'localtax2' =>array(
'type'=>
'double(24,8)',
'label'=>
'LT2',
'enabled'=>1,
'visible'=>-1,
'position'=>120,
'isameasure'=>1),
329 'revenuestamp' =>array(
'type'=>
'double(24,8)',
'label'=>
'RevenueStamp',
'enabled'=>1,
'visible'=>-1,
'position'=>115,
'isameasure'=>1),
330 'total_ttc' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountTTC',
'enabled'=>1,
'visible'=>1,
'position'=>130,
'isameasure'=>1),
331 'fk_facture_source' =>array(
'type'=>
'integer',
'label'=>
'SourceInvoice',
'enabled'=>1,
'visible'=>-1,
'position'=>170),
332 'fk_projet' =>array(
'type'=>
'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)',
'label'=>
'Project',
'enabled'=>1,
'visible'=>-1,
'position'=>175),
333 'fk_account' =>array(
'type'=>
'integer',
'label'=>
'Fk account',
'enabled'=>1,
'visible'=>-1,
'position'=>180),
334 'fk_currency' =>array(
'type'=>
'varchar(3)',
'label'=>
'CurrencyCode',
'enabled'=>1,
'visible'=>-1,
'position'=>185),
335 'fk_cond_reglement' =>array(
'type'=>
'integer',
'label'=>
'PaymentTerm',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>190),
336 'fk_mode_reglement' =>array(
'type'=>
'integer',
'label'=>
'PaymentMode',
'enabled'=>1,
'visible'=>-1,
'position'=>195),
337 'note_private' =>array(
'type'=>
'html',
'label'=>
'NotePrivate',
'enabled'=>1,
'visible'=>0,
'position'=>205),
338 'note_public' =>array(
'type'=>
'html',
'label'=>
'NotePublic',
'enabled'=>1,
'visible'=>0,
'position'=>210),
339 'model_pdf' =>array(
'type'=>
'varchar(255)',
'label'=>
'Model pdf',
'enabled'=>1,
'visible'=>0,
'position'=>215),
340 'extraparams' =>array(
'type'=>
'varchar(255)',
'label'=>
'Extraparams',
'enabled'=>1,
'visible'=>-1,
'position'=>225),
341 'situation_cycle_ref' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation cycle ref',
'enabled'=>
'$conf->global->INVOICE_USE_SITUATION',
'visible'=>-1,
'position'=>230),
342 'situation_counter' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation counter',
'enabled'=>
'$conf->global->INVOICE_USE_SITUATION',
'visible'=>-1,
'position'=>235),
343 'situation_final' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation final',
'enabled'=>
'empty($conf->global->INVOICE_USE_SITUATION) ? 0 : 1',
'visible'=>-1,
'position'=>240),
344 'retained_warranty' =>array(
'type'=>
'double',
'label'=>
'Retained warranty',
'enabled'=>
'$conf->global->INVOICE_USE_RETAINED_WARRANTY',
'visible'=>-1,
'position'=>245),
345 'retained_warranty_date_limit' =>array(
'type'=>
'date',
'label'=>
'Retained warranty date limit',
'enabled'=>
'$conf->global->INVOICE_USE_RETAINED_WARRANTY',
'visible'=>-1,
'position'=>250),
346 'retained_warranty_fk_cond_reglement' =>array(
'type'=>
'integer',
'label'=>
'Retained warranty fk cond reglement',
'enabled'=>
'$conf->global->INVOICE_USE_RETAINED_WARRANTY',
'visible'=>-1,
'position'=>255),
347 'fk_incoterms' =>array(
'type'=>
'integer',
'label'=>
'IncotermCode',
'enabled'=>
'$conf->incoterm->enabled',
'visible'=>-1,
'position'=>260),
348 'location_incoterms' =>array(
'type'=>
'varchar(255)',
'label'=>
'IncotermLabel',
'enabled'=>
'$conf->incoterm->enabled',
'visible'=>-1,
'position'=>265),
349 'date_pointoftax' =>array(
'type'=>
'date',
'label'=>
'DatePointOfTax',
'enabled'=>
'$conf->global->INVOICE_POINTOFTAX_DATE',
'visible'=>-1,
'position'=>270),
350 'fk_multicurrency' =>array(
'type'=>
'integer',
'label'=>
'MulticurrencyID',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>275),
351 'multicurrency_code' =>array(
'type'=>
'varchar(255)',
'label'=>
'Currency',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>280),
352 'multicurrency_tx' =>array(
'type'=>
'double(24,8)',
'label'=>
'CurrencyRate',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>285,
'isameasure'=>1),
353 'multicurrency_total_ht' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountHT',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>290,
'isameasure'=>1),
354 'multicurrency_total_tva' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountVAT',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>291,
'isameasure'=>1),
355 'multicurrency_total_ttc' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountTTC',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>292,
'isameasure'=>1),
356 'fk_fac_rec_source' =>array(
'type'=>
'integer',
'label'=>
'RecurringInvoiceSource',
'enabled'=>1,
'visible'=>-1,
'position'=>305),
357 'last_main_doc' =>array(
'type'=>
'varchar(255)',
'label'=>
'LastMainDoc',
'enabled'=>1,
'visible'=>-1,
'position'=>310),
358 'module_source' =>array(
'type'=>
'varchar(32)',
'label'=>
'POSModule',
'enabled'=>
"(isModEnabled('cashdesk') || isModEnabled('takepos') || getDolGlobalInt('INVOICE_SHOW_POS'))",
'visible'=>-1,
'position'=>315),
359 'pos_source' =>array(
'type'=>
'varchar(32)',
'label'=>
'POSTerminal',
'enabled'=>
"(isModEnabled('cashdesk') || isModEnabled('takepos') || getDolGlobalInt('INVOICE_SHOW_POS'))",
'visible'=>-1,
'position'=>320),
360 'datec' =>array(
'type'=>
'datetime',
'label'=>
'DateCreation',
'enabled'=>1,
'visible'=>-1,
'position'=>500),
361 'tms' =>array(
'type'=>
'timestamp',
'label'=>
'DateModificationShort',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>502),
362 'fk_user_author' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserAuthor',
'enabled'=>1,
'visible'=>-1,
'position'=>506),
363 'fk_user_modif' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserModif',
'enabled'=>1,
'visible'=>-1,
'notnull'=>-1,
'position'=>508),
364 'fk_user_valid' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserValidation',
'enabled'=>1,
'visible'=>-1,
'position'=>510),
365 'fk_user_closing' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserClosing',
'enabled'=>1,
'visible'=>-1,
'position'=>512),
366 'import_key' =>array(
'type'=>
'varchar(14)',
'label'=>
'ImportId',
'enabled'=>1,
'visible'=>-2,
'position'=>900),
367 'fk_statut' =>array(
'type'=>
'smallint(6)',
'label'=>
'Status',
'enabled'=>1,
'visible'=>1,
'notnull'=>1,
'position'=>1000,
'arrayofkeyval'=>array(0=>
'Draft', 1=>
'Validated', 2=>
'Paid', 3=>
'Abandonned')),
429 const CLOSECODE_DISCOUNTVAT =
'discount_vat';
430 const CLOSECODE_BADDEBT =
'badcustomer';
431 const CLOSECODE_BANKCHARGE =
'bankcharge';
432 const CLOSECODE_OTHER =
'other';
434 const CLOSECODE_ABANDONED =
'abandon';
435 const CLOSECODE_REPLACED =
'replaced';
458 public function create(
User $user, $notrigger = 0, $forceduedate = 0)
460 global $langs, $conf, $mysoc, $hookmanager;
464 if (empty($this->
type)) {
468 $this->ref_client = trim($this->ref_client);
470 $this->note = (isset($this->note) ? trim($this->note) : trim($this->note_private));
471 $this->note_private = (isset($this->note_private) ? trim($this->note_private) :
'');
472 $this->note_public = (isset($this->note_public) ? trim($this->note_public) :
'');
473 if (!$this->cond_reglement_id) {
474 $this->cond_reglement_id = 0;
476 if (!$this->mode_reglement_id) {
477 $this->mode_reglement_id = 0;
482 if (!empty($this->multicurrency_code)) {
484 if (empty($this->multicurrency_tx)) {
492 $this->fk_multicurrency = 0;
494 if (empty($this->fk_multicurrency)) {
495 $this->multicurrency_code = $conf->currency;
496 $this->fk_multicurrency = 0;
497 $this->multicurrency_tx = 1;
500 dol_syslog(get_class($this).
"::create user=".$user->id.
" date=".$this->date);
503 if (empty($this->date)) {
504 $this->error =
"Try to create an invoice with an empty parameter (date)";
505 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
509 $result = $soc->fetch($this->socid);
511 $this->error =
"Failed to fetch company: ".$soc->error;
512 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
517 $this->date_creation = $now;
521 $originaldatewhen =
null;
522 $nextdatewhen =
null;
523 $previousdaynextdatewhen =
null;
526 if ($this->fac_rec > 0) {
527 $this->fk_fac_rec_source = $this->fac_rec;
529 require_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture-rec.class.php';
531 $result = $_facrec->fetch($this->fac_rec);
532 $result = $_facrec->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 0);
535 $originaldatewhen = $_facrec->date_when;
536 $nextdatewhen =
null;
537 $previousdaynextdatewhen =
null;
538 if ($originaldatewhen) {
539 $nextdatewhen =
dol_time_plus_duree($originaldatewhen, $_facrec->frequency, $_facrec->unit_frequency);
543 if (!empty($_facrec->frequency)) {
544 $this->socid = $_facrec->socid;
546 $this->entity = $_facrec->entity;
549 $this->fk_project =
GETPOST(
'projectid',
'int') > 0 ? ((int)
GETPOST(
'projectid',
'int')) : $_facrec->fk_project;
550 $this->note_public = GETPOSTISSET(
'note_public') ?
GETPOST(
'note_public',
'restricthtml') : $_facrec->note_public;
551 $this->note_private = GETPOSTISSET(
'note_private') ?
GETPOST(
'note_private',
'restricthtml') : $_facrec->note_private;
552 $this->model_pdf = GETPOSTISSET(
'model') ?
GETPOST(
'model',
'alpha') : $_facrec->model_pdf;
553 $this->cond_reglement_id =
GETPOST(
'cond_reglement_id',
'int') > 0 ? ((int)
GETPOST(
'cond_reglement_id',
'int')) : $_facrec->cond_reglement_id;
554 $this->mode_reglement_id =
GETPOST(
'mode_reglement_id',
'int') > 0 ? ((int)
GETPOST(
'mode_reglement_id',
'int')) : $_facrec->mode_reglement_id;
555 $this->fk_account =
GETPOST(
'fk_account') > 0 ? ((int)
GETPOST(
'fk_account')) : $_facrec->fk_account;
558 $this->total_ht = $_facrec->total_ht;
559 $this->total_ttc = $_facrec->total_ttc;
564 $this->fk_incoterms = $_facrec->fk_incoterms;
565 $this->location_incoterms = $_facrec->location_incoterms;
571 $this->ref_client = trim($this->ref_client);
572 $this->ref_customer = trim($this->ref_customer);
573 $this->note_public = trim($this->note_public);
574 $this->note_private = trim($this->note_private);
575 $this->note_private =
dol_concatdesc($this->note_private, $langs->trans(
"GeneratedFromRecurringInvoice", $_facrec->ref));
577 $this->array_options = $_facrec->array_options;
579 if (!$this->mode_reglement_id) {
580 $this->mode_reglement_id = 0;
585 $this->linked_objects = $_facrec->linkedObjectsIds;
590 if ($_facrec->frequency > 0) {
591 dol_syslog(
"This is a recurring invoice so we set date_last_gen and next date_when");
592 if (empty($_facrec->date_when)) {
593 $_facrec->date_when = $now;
595 $next_date = $_facrec->getNextDate();
596 $result = $_facrec->setValueFrom(
'date_last_gen', $now,
'',
null,
'date',
'', $user,
'');
598 $result = $_facrec->setNextDate($next_date, 1);
602 $outputlangs = $langs;
605 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && empty($newlang) && isset($this->thirdparty->default_lang)) {
606 $newlang = $this->thirdparty->default_lang;
608 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && empty($newlang) && isset($this->default_lang)) {
609 $newlang = $this->default_lang;
611 if (!empty($newlang)) {
613 $outputlangs->setDefaultLang($newlang);
619 $substitutionarray[
'__INVOICE_MONTH__'] =
dol_print_date($this->date,
'%m');
622 $substitutionarray[
'__INVOICE_MONTH_TEXT__'] =
dol_print_date($this->date,
'%B');
625 $substitutionarray[
'__INVOICE_YEAR__'] =
dol_print_date($this->date,
'%Y');
628 $substitutionarray[
'__INVOICE_DATE_NEXT_INVOICE_BEFORE_GEN__'] = (isset($originaldatewhen) ?
dol_print_date($originaldatewhen,
'dayhour') :
'');
629 $substitutionarray[
'__INVOICE_DATE_NEXT_INVOICE_AFTER_GEN__'] = (isset($nextdatewhen) ?
dol_print_date($nextdatewhen,
'dayhour') :
'');
630 $substitutionarray[
'__INVOICE_PREVIOUS_DATE_NEXT_INVOICE_AFTER_GEN__'] = (isset($previousdaynextdatewhen) ?
dol_print_date($previousdaynextdatewhen,
'dayhour') :
'');
631 $substitutionarray[
'__INVOICE_COUNTER_CURRENT__'] = $_facrec->nb_gen_done;
632 $substitutionarray[
'__INVOICE_COUNTER_MAX__'] = $_facrec->nb_gen_max;
643 if (empty($forceduedate)) {
649 $this->date_lim_reglement = $duedate;
651 $this->date_lim_reglement = $forceduedate;
655 $socid = $this->socid;
657 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"facture (";
666 $sql .=
", date_pointoftax";
667 $sql .=
", note_private";
668 $sql .=
", note_public";
669 $sql .=
", ref_client";
670 $sql .=
", fk_account";
671 $sql .=
", module_source, pos_source, fk_fac_rec_source, fk_facture_source, fk_user_author, fk_projet";
672 $sql .=
", fk_cond_reglement, fk_mode_reglement, date_lim_reglement, model_pdf";
673 $sql .=
", situation_cycle_ref, situation_counter, situation_final";
674 $sql .=
", fk_incoterms, location_incoterms";
675 $sql .=
", fk_multicurrency";
676 $sql .=
", multicurrency_code";
677 $sql .=
", multicurrency_tx";
678 $sql .=
", retained_warranty";
679 $sql .=
", retained_warranty_date_limit";
680 $sql .=
", retained_warranty_fk_cond_reglement";
684 $sql .=
", ".setEntity($this);
685 $sql .=
", ".($this->ref_ext ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
686 $sql .=
", '".$this->db->escape($this->
type).
"'";
687 $sql .=
", ".($this->subtype ?
"'".$this->db->escape($this->subtype).
"'" :
"null");
688 $sql .=
", ".((int) $socid);
689 $sql .=
", '".$this->db->idate($this->date_creation).
"'";
690 $sql .=
", '".$this->db->idate($this->date).
"'";
691 $sql .=
", ".(empty($this->date_pointoftax) ?
"null" :
"'".$this->db->idate($this->date_pointoftax).
"'");
692 $sql .=
", ".($this->note_private ?
"'".$this->db->escape($this->note_private).
"'" :
"null");
693 $sql .=
", ".($this->note_public ?
"'".$this->db->escape($this->note_public).
"'" :
"null");
694 $sql .=
", ".($this->ref_customer ?
"'".$this->db->escape($this->ref_customer).
"'" : ($this->ref_client ?
"'".$this->db->escape($this->ref_client).
"'" :
"null"));
695 $sql .=
", ".($this->fk_account > 0 ? $this->fk_account :
'NULL');
696 $sql .=
", ".($this->module_source ?
"'".$this->db->escape($this->module_source).
"'" :
"null");
697 $sql .=
", ".($this->pos_source !=
'' ?
"'".$this->db->escape($this->pos_source).
"'" :
"null");
698 $sql .=
", ".($this->fk_fac_rec_source ?
"'".$this->db->escape($this->fk_fac_rec_source).
"'" :
"null");
699 $sql .=
", ".($this->fk_facture_source ?
"'".$this->db->escape($this->fk_facture_source).
"'" :
"null");
700 $sql .=
", ".($user->id > 0 ? (int) $user->id :
"null");
701 $sql .=
", ".($this->fk_project ? $this->fk_project :
"null");
702 $sql .=
", ".((int) $this->cond_reglement_id);
703 $sql .=
", ".((int) $this->mode_reglement_id);
704 $sql .=
", '".$this->db->idate($this->date_lim_reglement).
"'";
705 $sql .=
", ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null");
706 $sql .=
", ".($this->situation_cycle_ref ?
"'".$this->db->escape($this->situation_cycle_ref).
"'" :
"null");
707 $sql .=
", ".($this->situation_counter ?
"'".$this->db->escape($this->situation_counter).
"'" :
"null");
708 $sql .=
", ".($this->situation_final ? $this->situation_final : 0);
709 $sql .=
", ".(int) $this->fk_incoterms;
710 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
711 $sql .=
", ".(int) $this->fk_multicurrency;
712 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
713 $sql .=
", ".(float) $this->multicurrency_tx;
714 $sql .=
", ".(empty($this->retained_warranty) ?
"0" : $this->db->escape($this->retained_warranty));
715 $sql .=
", ".(!empty($this->retained_warranty_date_limit) ?
"'".$this->db->idate($this->retained_warranty_date_limit).
"'" :
'NULL');
716 $sql .=
", ".(int) $this->retained_warranty_fk_cond_reglement;
719 $resql = $this->db->query($sql);
721 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
'facture');
724 $this->
ref =
'(PROV'.$this->id.
')';
725 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"facture SET ref='".$this->db->escape($this->
ref).
"' WHERE rowid=".((int) $this->
id);
727 $resql = $this->db->query($sql);
732 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {
733 $this->linked_objects = $this->linkedObjectsIds;
737 if (!$error && $this->
id && !empty($this->linked_objects) && is_array($this->linked_objects)) {
738 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
739 if (is_array($tmp_origin_id)) {
740 foreach ($tmp_origin_id as $origin_id) {
743 $this->error = $this->db->lasterror();
748 $origin_id = $tmp_origin_id;
751 $this->error = $this->db->lasterror();
759 if (!$error && $this->
id &&
getDolGlobalString(
'MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN') && !empty($this->origin) && !empty($this->origin_id)) {
760 $originforcontact = $this->origin;
761 $originidforcontact = $this->origin_id;
762 if ($originforcontact ==
'shipping') {
763 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expedition.class.php';
765 $exp->fetch($this->origin_id);
766 $exp->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 0);
767 if (count($exp->linkedObjectsIds[
'commande']) > 0) {
768 foreach ($exp->linkedObjectsIds[
'commande'] as $key => $value) {
769 $originforcontact =
'commande';
770 if (is_object($value)) {
771 $originidforcontact = $value->id;
773 $originidforcontact = $value;
780 $sqlcontact =
"SELECT ctc.code, ctc.source, ec.fk_socpeople FROM ".MAIN_DB_PREFIX.
"element_contact as ec, ".MAIN_DB_PREFIX.
"c_type_contact as ctc";
781 $sqlcontact .=
" WHERE element_id = ".((int) $originidforcontact).
" AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$this->db->escape($originforcontact).
"'";
783 $resqlcontact = $this->db->query($sqlcontact);
785 while ($objcontact = $this->db->fetch_object($resqlcontact)) {
787 $this->
add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source);
797 if (!$error && empty($this->fac_rec) && count($this->lines) && is_object($this->lines[0])) {
800 dol_syslog(
"There is ".count($this->lines).
" lines into ->lines that are InvoiceLines");
801 foreach ($this->lines as $i => $val) {
802 $newinvoiceline = $this->lines[$i];
804 $newinvoiceline->context = $this->context;
806 $newinvoiceline->fk_facture = $this->id;
808 $newinvoiceline->origin = $this->lines[$i]->element;
809 $newinvoiceline->origin_id = $this->lines[$i]->id;
812 if ($this->lines[$i]->date_start_fill == 1 && $originaldatewhen) {
813 $newinvoiceline->date_start = $originaldatewhen;
815 if ($this->lines[$i]->date_end_fill == 1 && $previousdaynextdatewhen) {
816 $newinvoiceline->date_end = $previousdaynextdatewhen;
821 if (($newinvoiceline->product_type != 9 && empty($newinvoiceline->fk_parent_line)) || $newinvoiceline->product_type == 9) {
826 $vatrate = $newinvoiceline->tva_tx;
827 if ($newinvoiceline->vat_src_code && ! preg_match(
'/\(.*\)/', $vatrate)) {
828 $vatrate.=
' ('.$newinvoiceline->vat_src_code.
')';
831 $newinvoiceline->fk_parent_line = $fk_parent_line;
835 $discount->fetch($newinvoiceline->fk_remise_except);
837 $discountId = $soc->set_remise_except($discount->amount_ht, $user, $discount->description, $discount->tva_tx);
838 $newinvoiceline->fk_remise_except = $discountId;
842 $newinvoiceline->desc,
843 $newinvoiceline->subprice,
844 $newinvoiceline->qty,
846 $newinvoiceline->localtax1_tx,
847 $newinvoiceline->localtax2_tx,
848 $newinvoiceline->fk_product,
849 $newinvoiceline->remise_percent,
850 $newinvoiceline->date_start,
851 $newinvoiceline->date_end,
852 $newinvoiceline->fk_code_ventilation,
853 $newinvoiceline->info_bits,
854 $newinvoiceline->fk_remise_except,
857 $newinvoiceline->product_type,
858 $newinvoiceline->rang,
859 $newinvoiceline->special_code,
860 $newinvoiceline->element,
863 $newinvoiceline->fk_fournprice,
864 $newinvoiceline->pa_ht,
865 $newinvoiceline->label,
866 $newinvoiceline->array_options,
867 $newinvoiceline->situation_percent,
868 $newinvoiceline->fk_prev_id,
869 $newinvoiceline->fk_unit,
870 $newinvoiceline->multicurrency_subprice,
871 $newinvoiceline->ref_ext,
876 if ($result > 0 && $newinvoiceline->product_type == 9) {
877 $fk_parent_line = $result;
881 $this->error = $newinvoiceline->error;
882 $this->errors = $newinvoiceline->errors;
887 } elseif (!$error && empty($this->fac_rec)) {
890 dol_syslog(
"There is ".count($this->lines).
" lines into ->lines as a simple array");
892 foreach ($this->lines as $i => $val) {
893 $line = $this->lines[$i];
897 if (!is_object($line)) {
898 $line = (object) $line;
903 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
908 $vatrate = $line->tva_tx;
909 if ($line->vat_src_code && !preg_match(
'/\(.*\)/', $vatrate)) {
910 $vatrate .=
' ('.$line->vat_src_code.
')';
914 $originid = $line->origin_id;
915 $origintype = $line->origin;
917 $originid = $line->id;
918 $origintype = $this->element;
922 if (empty($line->ref_ext)) {
934 $line->remise_percent,
937 $line->fk_code_ventilation,
939 $line->fk_remise_except,
948 $line->fk_fournprice,
951 $line->array_options,
952 $line->situation_percent,
955 $line->multicurrency_subprice,
960 $this->error = $this->db->lasterror();
962 $this->db->rollback();
967 if ($result > 0 && $line->product_type == 9) {
968 $fk_parent_line = $result;
977 if (!$error && $this->fac_rec > 0) {
978 dol_syslog(
"There is ".count($_facrec->lines).
" lines from recurring invoice");
981 foreach ($_facrec->lines as $i => $val) {
983 if (($_facrec->lines[$i]->product_type != 9 && empty($_facrec->lines[$i]->fk_parent_line)) || $_facrec->lines[$i]->product_type == 9) {
1000 $tva_tx = $_facrec->lines[$i]->tva_tx.($_facrec->lines[$i]->vat_src_code ?
'('.$_facrec->lines[$i]->vat_src_code.
')' :
'');
1001 $tva_npr = $_facrec->lines[$i]->info_bits;
1002 if (empty($tva_tx)) {
1005 $localtax1_tx = $_facrec->lines[$i]->localtax1_tx;
1006 $localtax2_tx = $_facrec->lines[$i]->localtax2_tx;
1008 $fk_product_fournisseur_price = empty($_facrec->lines[$i]->fk_product_fournisseur_price) ? null : $_facrec->lines[$i]->fk_product_fournisseur_price;
1009 $buyprice = empty($_facrec->lines[$i]->buyprice) ? 0 : $_facrec->lines[$i]->buyprice;
1012 if (!$buyprice && $_facrec->lines[$i]->fk_product > 0) {
1013 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
1015 $producttmp->fetch($_facrec->lines[$i]->fk_product);
1020 if (
getDolGlobalString(
'MARGIN_TYPE') ==
'costprice' && !empty($producttmp->cost_price)) {
1021 $buyprice = $producttmp->cost_price;
1023 $buyprice = $producttmp->pmp;
1025 if ($producttmp->find_min_price_product_fournisseur($_facrec->lines[$i]->fk_product) > 0) {
1026 if ($producttmp->product_fourn_price_id > 0) {
1027 $buyprice =
price2num($producttmp->fourn_unitprice * (1 - $producttmp->fourn_remise_percent / 100) + $producttmp->fourn_remise,
'MU');
1033 $result_insert = $this->
addline(
1034 $_facrec->lines[$i]->desc,
1035 $_facrec->lines[$i]->subprice,
1036 $_facrec->lines[$i]->qty,
1040 $_facrec->lines[$i]->fk_product,
1041 $_facrec->lines[$i]->remise_percent,
1042 ($_facrec->lines[$i]->date_start_fill == 1 && $originaldatewhen) ? $originaldatewhen :
'',
1043 ($_facrec->lines[$i]->date_end_fill == 1 && $previousdaynextdatewhen) ? $previousdaynextdatewhen :
'',
1049 $_facrec->lines[$i]->product_type,
1050 $_facrec->lines[$i]->rang,
1051 $_facrec->lines[$i]->special_code,
1055 $fk_product_fournisseur_price,
1057 $_facrec->lines[$i]->label,
1058 empty($_facrec->lines[$i]->array_options) ? null : $_facrec->lines[$i]->array_options,
1061 $_facrec->lines[$i]->fk_unit,
1062 $_facrec->lines[$i]->multicurrency_subprice,
1063 $_facrec->lines[$i]->ref_ext,
1068 if ($result_insert > 0 && $_facrec->lines[$i]->product_type == 9) {
1069 $fk_parent_line = $result_insert;
1072 if ($result_insert < 0) {
1074 $this->error = $this->db->error();
1093 if (!$error && !$notrigger) {
1103 $this->db->commit();
1106 $this->db->rollback();
1110 $this->error = $langs->trans(
'FailedToUpdatePrice');
1111 $this->db->rollback();
1115 dol_syslog(get_class($this).
"::create error ".$this->error, LOG_ERR);
1116 $this->db->rollback();
1120 $this->error = $this->db->error();
1121 $this->db->rollback();
1139 $facture =
new Facture($this->db);
1145 if (!empty($this->array_options)) {
1146 $facture->array_options = $this->array_options;
1149 foreach ($this->lines as &$line) {
1150 $line->fetch_optionals();
1154 $facture->type = $this->type;
1155 $facture->subtype = $this->subtype;
1156 $facture->socid = $this->socid;
1157 $facture->date = $this->date;
1158 $facture->date_pointoftax = $this->date_pointoftax;
1159 $facture->note_public = $this->note_public;
1160 $facture->note_private = $this->note_private;
1161 $facture->ref_client = $this->ref_client;
1162 $facture->model_pdf = $this->model_pdf;
1163 $facture->fk_project = $this->fk_project;
1164 $facture->cond_reglement_id = $this->cond_reglement_id;
1165 $facture->mode_reglement_id = $this->mode_reglement_id;
1169 $facture->origin = $this->origin;
1170 $facture->origin_id = $this->origin_id;
1171 $facture->fk_account = $this->fk_account;
1173 $facture->lines = $this->lines;
1174 $facture->situation_counter = $this->situation_counter;
1175 $facture->situation_cycle_ref = $this->situation_cycle_ref;
1176 $facture->situation_final = $this->situation_final;
1178 $facture->retained_warranty = $this->retained_warranty;
1179 $facture->retained_warranty_fk_cond_reglement = $this->retained_warranty_fk_cond_reglement;
1180 $facture->retained_warranty_date_limit = $this->retained_warranty_date_limit;
1182 $facture->fk_user_author = $user->id;
1186 foreach ($facture->lines as $i => $tmpline) {
1187 $facture->lines[$i]->fk_prev_id = $this->lines[$i]->rowid;
1188 if ($invertdetail) {
1189 $facture->lines[$i]->subprice = -$facture->lines[$i]->subprice;
1190 $facture->lines[$i]->total_ht = -$facture->lines[$i]->total_ht;
1191 $facture->lines[$i]->total_tva = -$facture->lines[$i]->total_tva;
1192 $facture->lines[$i]->total_localtax1 = -$facture->lines[$i]->total_localtax1;
1193 $facture->lines[$i]->total_localtax2 = -$facture->lines[$i]->total_localtax2;
1194 $facture->lines[$i]->total_ttc = -$facture->lines[$i]->total_ttc;
1195 $facture->lines[$i]->ref_ext =
'';
1199 dol_syslog(get_class($this).
"::createFromCurrent invertdetail=".$invertdetail.
" socid=".$this->socid.
" nboflines=".count($facture->lines));
1201 $facid = $facture->create($user);
1203 $this->error = $facture->error;
1204 $this->errors = $facture->errors;
1208 foreach ($this->linkedObjectsIds as $typeObject => $Tfk_object) {
1209 foreach ($Tfk_object as $fk_object) {
1210 $facture->add_object_linked($typeObject, $fk_object);
1214 $facture->add_object_linked(
'facture', $this->fk_facture_source);
1230 global $conf, $hookmanager;
1234 $object =
new Facture($this->db);
1238 $object->fetch($fromid);
1241 $objFrom = clone $object;
1244 if (!empty($this->socid) && $this->socid != $object->socid) {
1245 $objsoc =
new Societe($this->db);
1247 if ($objsoc->fetch($this->socid) > 0) {
1248 $object->socid = $objsoc->id;
1249 $object->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1250 $object->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1251 $object->fk_project =
'';
1252 $object->fk_delivery_address =
'';
1263 $object->date = (empty($this->date) ?
dol_now() : $this->date);
1264 $object->user_creation_id = $user->id;
1265 $object->user_validation_id =
null;
1266 $object->fk_user_author = $user->id;
1267 $object->fk_user_valid =
null;
1268 $object->fk_facture_source = 0;
1269 $object->date_creation =
'';
1270 $object->date_modification =
'';
1271 $object->date_validation =
'';
1272 $object->ref_client =
'';
1273 $object->ref_customer =
'';
1274 $object->close_code =
'';
1275 $object->close_note =
'';
1277 $object->note_private =
'';
1278 $object->note_public =
'';
1282 foreach ($object->lines as $i => $line) {
1283 if (($object->lines[$i]->info_bits & 0x02) == 0x02) {
1284 unset($object->lines[$i]);
1290 if (
getDolGlobalString(
'INVOICE_AUTO_NEXT_MONTH_ON_LINES') && !empty($line->date_start) && !empty($line->date_end)) {
1302 if (
dol_mktime(0, 0, 0, $start[
'mon'], $start[
'mday'], $start[
'year'],
'gmt') == $first
1303 &&
dol_mktime(23, 59, 59, $end[
'mon'], $end[
'mday'], $end[
'year'],
'gmt') == $last) {
1307 $object->lines[$i]->date_start = $newFirst;
1308 $object->lines[$i]->date_end = $newLast;
1312 $object->lines[$i]->ref_ext =
'';
1316 $object->context[
'createfromclone'] =
'createfromclone';
1317 $result = $object->create($user);
1320 $this->error = $object->error;
1321 $this->errors = $object->errors;
1324 if ($object->copy_linked_contact($objFrom,
'internal') < 0) {
1326 $this->error = $object->error;
1327 $this->errors = $object->errors;
1328 } elseif ($object->socid == $objFrom->socid) {
1330 if ($object->copy_linked_contact($objFrom,
'external') < 0) {
1332 $this->error = $object->error;
1333 $this->errors = $object->errors;
1340 if (is_object($hookmanager)) {
1341 $parameters = array(
'objFrom'=>$objFrom);
1343 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $object, $action);
1351 unset($object->context[
'createfromclone']);
1355 $this->db->commit();
1358 $this->db->rollback();
1372 global $conf, $hookmanager;
1380 $num = count($object->lines);
1381 for ($i = 0; $i < $num; $i++) {
1384 $line->libelle = $object->lines[$i]->libelle;
1385 $line->label = $object->lines[$i]->label;
1386 $line->desc = $object->lines[$i]->desc;
1387 $line->subprice = $object->lines[$i]->subprice;
1388 $line->total_ht = $object->lines[$i]->total_ht;
1389 $line->total_tva = $object->lines[$i]->total_tva;
1390 $line->total_localtax1 = $object->lines[$i]->total_localtax1;
1391 $line->total_localtax2 = $object->lines[$i]->total_localtax2;
1392 $line->total_ttc = $object->lines[$i]->total_ttc;
1393 $line->vat_src_code = $object->lines[$i]->vat_src_code;
1394 $line->tva_tx = $object->lines[$i]->tva_tx;
1395 $line->localtax1_tx = $object->lines[$i]->localtax1_tx;
1396 $line->localtax2_tx = $object->lines[$i]->localtax2_tx;
1397 $line->qty = $object->lines[$i]->qty;
1398 $line->fk_remise_except = $object->lines[$i]->fk_remise_except;
1399 $line->remise_percent = $object->lines[$i]->remise_percent;
1400 $line->fk_product = $object->lines[$i]->fk_product;
1401 $line->info_bits = $object->lines[$i]->info_bits;
1402 $line->product_type = $object->lines[$i]->product_type;
1403 $line->rang = $object->lines[$i]->rang;
1404 $line->special_code = $object->lines[$i]->special_code;
1405 $line->fk_parent_line = $object->lines[$i]->fk_parent_line;
1406 $line->fk_unit = $object->lines[$i]->fk_unit;
1407 $line->date_start = $object->lines[$i]->date_start;
1408 $line->date_end = $object->lines[$i]->date_end;
1411 $line->fk_multicurrency = $object->lines[$i]->fk_multicurrency;
1412 $line->multicurrency_code = $object->lines[$i]->multicurrency_code;
1413 $line->multicurrency_subprice = $object->lines[$i]->multicurrency_subprice;
1414 $line->multicurrency_total_ht = $object->lines[$i]->multicurrency_total_ht;
1415 $line->multicurrency_total_tva = $object->lines[$i]->multicurrency_total_tva;
1416 $line->multicurrency_total_ttc = $object->lines[$i]->multicurrency_total_ttc;
1418 $line->fk_fournprice = $object->lines[$i]->fk_fournprice;
1419 $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);
1420 $line->pa_ht = $marginInfos[0];
1423 $object->lines[$i]->fetch_optionals();
1424 foreach ($object->lines[$i]->array_options as $options_key => $value) {
1425 $line->array_options[$options_key] = $value;
1428 $this->lines[$i] = $line;
1431 $this->socid = $object->socid;
1432 $this->fk_project = $object->fk_project;
1433 $this->fk_account = $object->fk_account;
1434 $this->cond_reglement_id = $object->cond_reglement_id;
1435 $this->mode_reglement_id = $object->mode_reglement_id;
1436 $this->availability_id = $object->availability_id;
1437 $this->demand_reason_id = $object->demand_reason_id;
1438 $this->delivery_date = $object->delivery_date;
1439 $this->fk_delivery_address = $object->fk_delivery_address;
1440 $this->contact_id = $object->contact_id;
1441 $this->ref_client = $object->ref_client;
1444 $this->note_private = $object->note_private;
1445 $this->note_public = $object->note_public;
1448 $this->module_source = $object->module_source;
1449 $this->pos_source = $object->pos_source;
1451 $this->origin = $object->element;
1452 $this->origin_id = $object->id;
1454 $this->fk_user_author = $user->id;
1457 $object->fetch_optionals();
1458 foreach ($object->array_options as $options_key => $value) {
1459 $this->array_options[$options_key] = $value;
1463 $this->linked_objects[$this->origin] = $this->origin_id;
1464 if (!empty($object->other_linked_objects) && is_array($object->other_linked_objects)) {
1465 $this->linked_objects = array_merge($this->linked_objects, $object->other_linked_objects);
1468 $ret = $this->
create($user);
1472 $hookmanager->initHooks(array(
'invoicedao'));
1474 $parameters = array(
'objFrom'=>$object);
1476 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $this, $action);
1502 global $conf, $hookmanager;
1510 $use_all_lines = empty($lines);
1511 $num = count($object->lines);
1512 for ($i = 0; $i < $num; $i++) {
1513 if (!$use_all_lines && !in_array($object->lines[$i]->id, $lines)) {
1519 $line->libelle = $object->lines[$i]->libelle;
1520 $line->label = $object->lines[$i]->label;
1521 $line->desc = $object->lines[$i]->desc;
1522 $line->subprice = $object->lines[$i]->subprice;
1523 $line->total_ht = $object->lines[$i]->total_ht;
1524 $line->total_tva = $object->lines[$i]->total_tva;
1525 $line->total_localtax1 = $object->lines[$i]->total_localtax1;
1526 $line->total_localtax2 = $object->lines[$i]->total_localtax2;
1527 $line->total_ttc = $object->lines[$i]->total_ttc;
1528 $line->vat_src_code = $object->lines[$i]->vat_src_code;
1529 $line->tva_tx = $object->lines[$i]->tva_tx;
1530 $line->localtax1_tx = $object->lines[$i]->localtax1_tx;
1531 $line->localtax2_tx = $object->lines[$i]->localtax2_tx;
1532 $line->qty = $object->lines[$i]->qty;
1533 $line->fk_remise_except = $object->lines[$i]->fk_remise_except;
1534 $line->remise_percent = $object->lines[$i]->remise_percent;
1535 $line->fk_product = $object->lines[$i]->fk_product;
1536 $line->info_bits = $object->lines[$i]->info_bits;
1537 $line->product_type = $object->lines[$i]->product_type;
1538 $line->rang = $object->lines[$i]->rang;
1539 $line->special_code = $object->lines[$i]->special_code;
1540 $line->fk_parent_line = $object->lines[$i]->fk_parent_line;
1541 $line->fk_unit = $object->lines[$i]->fk_unit;
1542 $line->date_start = $object->lines[$i]->date_start;
1543 $line->date_end = $object->lines[$i]->date_end;
1546 $line->fk_multicurrency = $object->lines[$i]->fk_multicurrency;
1547 $line->multicurrency_code = $object->lines[$i]->multicurrency_code;
1548 $line->multicurrency_subprice = $object->lines[$i]->multicurrency_subprice;
1549 $line->multicurrency_total_ht = $object->lines[$i]->multicurrency_total_ht;
1550 $line->multicurrency_total_tva = $object->lines[$i]->multicurrency_total_tva;
1551 $line->multicurrency_total_ttc = $object->lines[$i]->multicurrency_total_ttc;
1553 $line->fk_fournprice = $object->lines[$i]->fk_fournprice;
1554 $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);
1555 $line->pa_ht = $marginInfos[0];
1558 $object->lines[$i]->fetch_optionals();
1559 foreach ($object->lines[$i]->array_options as $options_key => $value) {
1560 $line->array_options[$options_key] = $value;
1563 $this->lines[$i] = $line;
1566 $this->socid = $object->socid;
1567 $this->fk_project = $object->fk_project;
1568 $this->fk_account = $object->fk_account;
1569 $this->cond_reglement_id = $object->cond_reglement_id;
1570 $this->mode_reglement_id = $object->mode_reglement_id;
1571 $this->availability_id = $object->availability_id;
1572 $this->demand_reason_id = $object->demand_reason_id;
1573 $this->delivery_date = $object->delivery_date;
1574 $this->fk_delivery_address = $object->fk_delivery_address;
1575 $this->contact_id = $object->contact_id;
1576 $this->ref_client = $object->ref_client;
1579 $this->note_private = $object->note_private;
1580 $this->note_public = $object->note_public;
1583 $this->module_source = $object->module_source;
1584 $this->pos_source = $object->pos_source;
1586 $this->origin = $object->element;
1587 $this->origin_id = $object->id;
1589 $this->fk_user_author = $user->id;
1592 $object->fetch_optionals();
1593 foreach ($object->array_options as $options_key => $value) {
1594 $this->array_options[$options_key] = $value;
1598 $this->linked_objects[$this->origin] = $this->origin_id;
1599 if (!empty($object->other_linked_objects) && is_array($object->other_linked_objects)) {
1600 $this->linked_objects = array_merge($this->linked_objects, $object->other_linked_objects);
1603 $ret = $this->
create($user);
1607 $hookmanager->initHooks(array(
'invoicedao'));
1609 $parameters = array(
'objFrom'=>$object);
1611 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $this, $action);
1641 global $conf, $langs, $hookmanager, $action;
1643 if (! in_array($origin->element, array(
'propal',
'commande'))) {
1644 $origin->error =
'ErrorCanOnlyAutomaticallyGenerateADepositFromProposalOrOrder';
1649 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'DateInvoice'));
1653 require_once DOL_DOCUMENT_ROOT .
'/core/lib/date.lib.php';
1656 $origin->error =
'ErrorDateIsInFuture';
1660 if ($payment_terms_id <= 0) {
1661 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'PaymentConditionsShort'));
1665 $payment_conditions_deposit_percent =
getDictionaryValue(
'c_payment_term',
'deposit_percent', $origin->cond_reglement_id);
1667 if (empty($payment_conditions_deposit_percent)) {
1668 $origin->error =
'ErrorPaymentConditionsNotEligibleToDepositCreation';
1672 if (empty($origin->deposit_percent)) {
1673 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'DepositPercent'));
1677 $deposit =
new self($origin->db);
1678 $deposit->socid = $origin->socid;
1680 $deposit->fk_project = $origin->fk_project;
1681 $deposit->ref_client = $origin->ref_client;
1682 $deposit->date = $date;
1683 $deposit->mode_reglement_id = $origin->mode_reglement_id;
1684 $deposit->cond_reglement_id = $payment_terms_id;
1685 $deposit->availability_id = $origin->availability_id;
1686 $deposit->demand_reason_id = $origin->demand_reason_id;
1687 $deposit->fk_account = $origin->fk_account;
1688 $deposit->fk_incoterms = $origin->fk_incoterms;
1689 $deposit->location_incoterms = $origin->location_incoterms;
1690 $deposit->fk_multicurrency = $origin->fk_multicurrency;
1691 $deposit->multicurrency_code = $origin->multicurrency_code;
1692 $deposit->multicurrency_tx = $origin->multicurrency_tx;
1693 $deposit->module_source = $origin->module_source;
1694 $deposit->pos_source = $origin->pos_source;
1695 $deposit->model_pdf =
'crabe';
1697 $modelByTypeConfName =
'FACTURE_ADDON_PDF_' . $deposit->type;
1706 $deposit->note_private = $origin->note_private;
1707 $deposit->note_public = $origin->note_public;
1710 $deposit->origin = $origin->element;
1711 $deposit->origin_id = $origin->id;
1713 $origin->fetch_optionals();
1715 foreach ($origin->array_options as $extrakey => $value) {
1716 $deposit->array_options[$extrakey] = $value;
1719 $deposit->linked_objects[$deposit->origin] = $deposit->origin_id;
1721 foreach ($overrideFields as $key => $value) {
1722 $deposit->$key = $value;
1725 $deposit->context[
'createdepositfromorigin'] =
'createdepositfromorigin';
1727 $origin->db->begin();
1730 $createReturn = $deposit->create($user, $notrigger);
1732 if ($createReturn <= 0) {
1733 $origin->db->rollback();
1734 $origin->error = $deposit->error;
1735 $origin->errors = $deposit->errors;
1739 $amount_ttc_diff = 0;
1740 $amountdeposit = array();
1741 $descriptions = array();
1744 $amount = $origin->total_ttc * ($origin->deposit_percent / 100);
1746 $TTotalByTva = array();
1747 foreach ($origin->lines as &$line) {
1748 if (!empty($line->special_code)) {
1751 $TTotalByTva[$line->tva_tx] += $line->total_ttc;
1752 $descriptions[$line->tva_tx] .=
'<li>' . (!empty($line->product_ref) ? $line->product_ref .
' - ' :
'');
1753 $descriptions[$line->tva_tx] .= (!empty($line->product_label) ? $line->product_label .
' - ' :
'');
1754 $descriptions[$line->tva_tx] .= $langs->trans(
'Qty') .
' : ' . $line->qty;
1755 $descriptions[$line->tva_tx] .=
' - ' . $langs->trans(
'TotalHT') .
' : ' .
price($line->total_ht) .
'</li>';
1758 foreach ($TTotalByTva as $tva => &$total) {
1759 $coef = $total / $origin->total_ttc;
1760 $am = $amount * $coef;
1761 $amount_ttc_diff += $am;
1762 $amountdeposit[$tva] += $am / (1 + $tva / 100);
1766 $lines = $origin->lines;
1767 $numlines = count($lines);
1768 for ($i = 0; $i < $numlines; $i++) {
1769 if (empty($lines[$i]->qty)) {
1772 if (!empty($lines[$i]->special_code)) {
1776 $totalamount += $lines[$i]->total_ht;
1777 $tva_tx = $lines[$i]->tva_tx;
1778 $amountdeposit[$tva_tx] += ($lines[$i]->total_ht * $origin->deposit_percent) / 100;
1779 $descriptions[$tva_tx] .=
'<li>' . (!empty($lines[$i]->product_ref) ? $lines[$i]->product_ref .
' - ' :
'');
1780 $descriptions[$tva_tx] .= (!empty($lines[$i]->product_label) ? $lines[$i]->product_label .
' - ' :
'');
1781 $descriptions[$tva_tx] .= $langs->trans(
'Qty') .
' : ' . $lines[$i]->qty;
1782 $descriptions[$tva_tx] .=
' - ' . $langs->trans(
'TotalHT') .
' : ' .
price($lines[$i]->total_ht) .
'</li>';
1785 if ($totalamount == 0) {
1786 $amountdeposit[0] = 0;
1789 $amount_ttc_diff = $amountdeposit[0];
1792 foreach ($amountdeposit as $tva => $amount) {
1793 if (empty($amount)) {
1797 $descline =
'(DEPOSIT) ('. $origin->deposit_percent .
'%) - '.$origin->ref;
1800 if (
getDolGlobalString(
'INVOICE_DEPOSIT_VARIABLE_MODE_DETAIL_LINES_IN_DESCRIPTION') && !empty($descriptions[$tva])) {
1801 $descline .=
'<ul>' . $descriptions[$tva] .
'</ul>';
1804 $addlineResult = $deposit->addline(
1811 (!
getDolGlobalString(
'INVOICE_PRODUCTID_DEPOSIT') ? 0 : $conf->global->INVOICE_PRODUCTID_DEPOSIT),
1831 if ($addlineResult < 0) {
1832 $origin->db->rollback();
1833 $origin->error = $deposit->error;
1834 $origin->errors = $deposit->errors;
1839 $diff = $deposit->total_ttc - $amount_ttc_diff;
1842 $deposit->fetch_lines();
1843 $subprice_diff = $deposit->lines[0]->subprice - $diff / (1 + $deposit->lines[0]->tva_tx / 100);
1845 $updatelineResult = $deposit->updateline(
1846 $deposit->lines[0]->id,
1847 $deposit->lines[0]->desc,
1849 $deposit->lines[0]->qty,
1850 $deposit->lines[0]->remise_percent,
1851 $deposit->lines[0]->date_start,
1852 $deposit->lines[0]->date_end,
1853 $deposit->lines[0]->tva_tx,
1857 $deposit->lines[0]->info_bits,
1858 $deposit->lines[0]->product_type,
1862 $deposit->lines[0]->pa_ht,
1863 $deposit->lines[0]->label,
1869 if ($updatelineResult < 0) {
1870 $origin->db->rollback();
1871 $origin->error = $deposit->error;
1872 $origin->errors = $deposit->errors;
1877 $hookmanager->initHooks(array(
'invoicedao'));
1879 $parameters = array(
'objFrom' => $origin);
1880 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $deposit, $action);
1883 $origin->db->rollback();
1884 $origin->error = $hookmanager->error;
1885 $origin->errors = $hookmanager->errors;
1889 if (!empty($autoValidateDeposit)) {
1890 $validateReturn = $deposit->validate($user,
'', 0, $notrigger);
1892 if ($validateReturn < 0) {
1893 $origin->db->rollback();
1894 $origin->error = $deposit->error;
1895 $origin->errors = $deposit->errors;
1900 unset($deposit->context[
'createdepositfromorigin']);
1902 $origin->db->commit();
1916 global $conf, $langs, $mysoc, $user;
1918 $langs->load(
'bills');
1921 $moretitle = $params[
'moretitle'] ??
'';
1922 $picto = $this->picto;
1923 if ($this->
type == self::TYPE_REPLACEMENT) {
1926 if ($this->
type == self::TYPE_CREDIT_NOTE) {
1929 if ($this->
type == self::TYPE_DEPOSIT) {
1933 if ($user->hasRight(
"facture",
"read")) {
1934 $datas[
'picto'] =
img_picto(
'', $picto).
' <u class="paddingrightonly">'.$langs->trans(
"Invoice").
'</u>';
1936 $datas[
'picto'] .=
' '.$this->getLibType(1);
1939 if (!empty($params[
'fromajaxtooltip']) && !isset($this->alreadypaid)) {
1943 if (isset($this->
status) && isset($this->alreadypaid)) {
1944 $datas[
'picto'] .=
' '.$this->getLibStatut(5, $this->alreadypaid);
1947 $datas[
'picto'] .=
' - '.$moretitle;
1949 if (!empty($this->
ref)) {
1950 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
1952 if (!empty($this->ref_customer)) {
1953 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.$this->ref_customer;
1955 if (!empty($this->date)) {
1956 $datas[
'date'] =
'<br><b>'.$langs->trans(
'Date').
':</b> '.
dol_print_date($this->date,
'day');
1958 if (!empty($this->total_ht)) {
1959 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
1961 if (!empty($this->total_tva)) {
1962 $datas[
'amountvat'] =
'<br><b>'.$langs->trans(
'AmountVAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
1964 if (!empty($this->revenuestamp) && $this->revenuestamp != 0) {
1965 $datas[
'amountrevenustamp'] =
'<br><b>'.$langs->trans(
'RevenueStamp').
':</b> '.
price($this->revenuestamp, 0, $langs, 0, -1, -1, $conf->currency);
1967 if (!empty($this->total_localtax1) && $this->total_localtax1 != 0) {
1969 $datas[
'amountlt1'] =
'<br><b>'.$langs->transcountry(
'AmountLT1', $mysoc->country_code).
':</b> '.
price($this->total_localtax1, 0, $langs, 0, -1, -1, $conf->currency);
1971 if (!empty($this->total_localtax2) && $this->total_localtax2 != 0) {
1972 $datas[
'amountlt2'] =
'<br><b>'.$langs->transcountry(
'AmountLT2', $mysoc->country_code).
':</b> '.
price($this->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency);
1974 if (!empty($this->total_ttc)) {
1975 $datas[
'amountttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
1996 public function getNomUrl($withpicto = 0, $option =
'', $max = 0, $short = 0, $moretitle =
'', $notooltip = 0, $addlinktonotes = 0, $save_lastsearch_value = -1, $target =
'')
1998 global $langs, $conf, $user, $mysoc;
2000 if (!empty($conf->dol_no_mouse_hover)) {
2006 if ($option ==
'withdraw') {
2007 $url = DOL_URL_ROOT.
'/compta/facture/prelevement.php?facid='.$this->id;
2009 $url = DOL_URL_ROOT.
'/compta/facture/card.php?facid='.$this->id;
2012 if (!$user->hasRight(
"facture",
"read")) {
2016 if ($option !==
'nolink') {
2018 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2019 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
2020 $add_save_lastsearch_values = 1;
2022 if ($add_save_lastsearch_values) {
2023 $url .=
'&save_lastsearch_values=1';
2031 $picto = $this->picto;
2032 if ($this->
type == self::TYPE_REPLACEMENT) {
2035 if ($this->
type == self::TYPE_CREDIT_NOTE) {
2038 if ($this->
type == self::TYPE_DEPOSIT) {
2043 'objecttype' => $this->element,
2044 'moretitle' => $moretitle,
2045 'option' => $option,
2047 $classfortooltip =
'classfortooltip';
2050 $classfortooltip =
'classforajaxtooltip';
2051 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
2057 $linkclose = ($target ?
' target="'.$target.
'"' :
'');
2058 if (empty($notooltip) && $user->hasRight(
"facture",
"read")) {
2060 $label = $langs->trans(
"Invoice");
2061 $linkclose .=
' alt="'.dol_escape_htmltag($label, 1).
'"';
2063 $linkclose .= ($label ?
' title="'.dol_escape_htmltag($label, 1).
'"' :
' title="tocomplete"');
2064 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
2067 $linkstart =
'<a href="'.$url.
'"';
2068 $linkstart .= $linkclose.
'>';
2071 if ($option ==
'nolink') {
2076 $result .= $linkstart;
2078 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), ($notooltip ? (($withpicto != 2) ?
'class="paddingright"' :
'') :
'class="'.(($withpicto != 2) ?
'paddingright ' :
'').
'"'), 0, 0, $notooltip ? 0 : 1);
2080 if ($withpicto != 2) {
2081 $result .= ($max ?
dol_trunc($this->
ref, $max) : $this->ref);
2083 $result .= $linkend;
2085 if ($addlinktonotes) {
2086 $txttoshow = ($user->socid > 0 ? $this->note_public : $this->note_private);
2089 $notetoshow = $langs->trans(
"ViewPrivateNote").
':<br>'.$txttoshow;
2090 $result .=
' <span class="note inline-block">';
2091 $result .=
'<a href="'.DOL_URL_ROOT.
'/compta/facture/note.php?id='.$this->
id.
'" class="classfortooltip" title="'.
dol_escape_htmltag($notetoshow, 1, 1).
'">';
2096 $result .=
'</span>';
2100 global $action, $hookmanager;
2101 $hookmanager->initHooks(array(
'invoicedao'));
2102 $parameters = array(
'id'=>$this->
id,
'getnomurl' => &$result,
'notooltip' => $notooltip,
'addlinktonotes' => $addlinktonotes,
'save_lastsearch_value'=> $save_lastsearch_value,
'target' => $target);
2103 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
2105 $result = $hookmanager->resPrint;
2107 $result .= $hookmanager->resPrint;
2123 public function fetch($rowid, $ref =
'', $ref_ext =
'', $notused = 0, $fetch_situation =
false)
2125 if (empty($rowid) && empty($ref) && empty($ref_ext)) {
2129 $sql =
'SELECT f.rowid, f.entity, f.ref, f.ref_client, f.ref_ext, f.type, f.subtype, f.fk_soc';
2130 $sql .=
', f.total_tva, f.localtax1, f.localtax2, f.total_ht, f.total_ttc, f.revenuestamp';
2131 $sql .=
', f.datef as df, f.date_pointoftax';
2132 $sql .=
', f.date_lim_reglement as dlr';
2133 $sql .=
', f.datec as datec';
2134 $sql .=
', f.date_valid as datev';
2135 $sql .=
', f.tms as datem';
2136 $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';
2137 $sql .=
', f.fk_facture_source, f.fk_fac_rec_source';
2138 $sql .=
', f.fk_mode_reglement, f.fk_cond_reglement, f.fk_projet as fk_project, f.extraparams';
2139 $sql .=
', f.situation_cycle_ref, f.situation_counter, f.situation_final';
2140 $sql .=
', f.fk_account';
2141 $sql .=
", f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc";
2142 $sql .=
', p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
2143 $sql .=
', c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_doc';
2144 $sql .=
', f.fk_incoterms, f.location_incoterms';
2145 $sql .=
', f.module_source, f.pos_source';
2146 $sql .=
", i.libelle as label_incoterms";
2147 $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";
2148 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facture as f';
2149 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_payment_term as c ON f.fk_cond_reglement = c.rowid';
2150 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_paiement as p ON f.fk_mode_reglement = p.id';
2151 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON f.fk_incoterms = i.rowid';
2154 $sql .=
" WHERE f.rowid = ".((int) $rowid);
2156 $sql .=
' WHERE f.entity IN ('.getEntity(
'invoice').
')';
2158 $sql .=
" AND f.ref = '".$this->db->escape($ref).
"'";
2161 $sql .=
" AND f.ref_ext = '".$this->db->escape($ref_ext).
"'";
2165 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
2166 $resql = $this->db->query($sql);
2168 if ($this->db->num_rows($resql)) {
2169 $obj = $this->db->fetch_object($resql);
2171 $this->
id = $obj->rowid;
2172 $this->entity = $obj->entity;
2174 $this->
ref = $obj->ref;
2175 $this->ref_client = $obj->ref_client;
2176 $this->ref_customer = $obj->ref_client;
2177 $this->ref_ext = $obj->ref_ext;
2178 $this->
type = $obj->type;
2179 $this->subtype = $obj->subtype;
2180 $this->date = $this->db->jdate($obj->df);
2181 $this->date_pointoftax = $this->db->jdate($obj->date_pointoftax);
2182 $this->date_creation = $this->db->jdate($obj->datec);
2183 $this->date_validation = $this->db->jdate($obj->datev);
2184 $this->date_modification = $this->db->jdate($obj->datem);
2185 $this->datem = $this->db->jdate($obj->datem);
2186 $this->total_ht = $obj->total_ht;
2187 $this->total_tva = $obj->total_tva;
2188 $this->total_localtax1 = $obj->localtax1;
2189 $this->total_localtax2 = $obj->localtax2;
2190 $this->total_ttc = $obj->total_ttc;
2191 $this->revenuestamp = $obj->revenuestamp;
2192 $this->paye = $obj->paye;
2193 $this->close_code = $obj->close_code;
2194 $this->close_note = $obj->close_note;
2196 $this->socid = $obj->fk_soc;
2197 $this->thirdparty =
null;
2199 $this->fk_project = $obj->fk_project;
2200 $this->project =
null;
2202 $this->
statut = $obj->status;
2203 $this->
status = $obj->status;
2205 $this->date_lim_reglement = $this->db->jdate($obj->dlr);
2206 $this->mode_reglement_id = $obj->fk_mode_reglement;
2207 $this->mode_reglement_code = $obj->mode_reglement_code;
2208 $this->mode_reglement = $obj->mode_reglement_libelle;
2209 $this->cond_reglement_id = $obj->fk_cond_reglement;
2210 $this->cond_reglement_code = $obj->cond_reglement_code;
2211 $this->cond_reglement = $obj->cond_reglement_libelle;
2212 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
2213 $this->fk_account = ($obj->fk_account > 0) ? $obj->fk_account :
null;
2214 $this->fk_facture_source = $obj->fk_facture_source;
2215 $this->fk_fac_rec_source = $obj->fk_fac_rec_source;
2216 $this->note = $obj->note_private;
2217 $this->note_private = $obj->note_private;
2218 $this->note_public = $obj->note_public;
2219 $this->user_creation_id = $obj->fk_user_author;
2220 $this->user_validation_id = $obj->fk_user_valid;
2221 $this->user_modification_id = $obj->fk_user_modif;
2222 $this->fk_user_author = $obj->fk_user_author;
2223 $this->fk_user_valid = $obj->fk_user_valid;
2224 $this->fk_user_modif = $obj->fk_user_modif;
2225 $this->model_pdf = $obj->model_pdf;
2226 $this->last_main_doc = $obj->last_main_doc;
2227 $this->situation_cycle_ref = $obj->situation_cycle_ref;
2228 $this->situation_counter = $obj->situation_counter;
2229 $this->situation_final = $obj->situation_final;
2230 $this->retained_warranty = $obj->retained_warranty;
2231 $this->retained_warranty_date_limit = $this->db->jdate($obj->retained_warranty_date_limit);
2232 $this->retained_warranty_fk_cond_reglement = $obj->retained_warranty_fk_cond_reglement;
2234 $this->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
2237 $this->fk_incoterms = $obj->fk_incoterms;
2238 $this->location_incoterms = $obj->location_incoterms;
2239 $this->label_incoterms = $obj->label_incoterms;
2241 $this->module_source = $obj->module_source;
2242 $this->pos_source = $obj->pos_source;
2245 $this->fk_multicurrency = $obj->fk_multicurrency;
2246 $this->multicurrency_code = $obj->multicurrency_code;
2247 $this->multicurrency_tx = $obj->multicurrency_tx;
2248 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
2249 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
2250 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
2252 if (($this->
type == self::TYPE_SITUATION || ($this->
type == self::TYPE_CREDIT_NOTE && $this->situation_cycle_ref > 0)) && $fetch_situation) {
2261 $this->lines = array();
2265 $this->error = $this->db->error();
2269 $this->db->free($resql);
2273 $this->error =
'Invoice with id='.$rowid.
' or ref='.$ref.
' or ref_ext='.$ref_ext.
' not found';
2275 dol_syslog(__METHOD__.$this->error, LOG_WARNING);
2279 $this->error = $this->db->lasterror();
2294 public function fetch_lines($only_product = 0, $loadalsotranslation = 0)
2297 $this->lines = array();
2299 $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,';
2300 $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,';
2301 $sql .=
' l.situation_percent, l.fk_prev_id,';
2302 $sql .=
' l.rang, l.special_code, l.batch, l.fk_warehouse,';
2303 $sql .=
' l.date_start as date_start, l.date_end as date_end,';
2304 $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,';
2305 $sql .=
' l.fk_unit,';
2306 $sql .=
' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
2307 $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';
2308 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facturedet as l';
2309 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON l.fk_product = p.rowid';
2310 $sql .=
' WHERE l.fk_facture = '.((int) $this->
id);
2311 $sql .=
' ORDER BY l.rang, l.rowid';
2313 dol_syslog(get_class($this).
'::fetch_lines', LOG_DEBUG);
2314 $result = $this->db->query($sql);
2316 $num = $this->db->num_rows($result);
2319 $objp = $this->db->fetch_object($result);
2322 $line->id = $objp->rowid;
2323 $line->rowid = $objp->rowid;
2324 $line->fk_facture = $objp->fk_facture;
2325 $line->label = $objp->custom_label;
2326 $line->desc = $objp->description;
2327 $line->description = $objp->description;
2328 $line->product_type = $objp->product_type;
2329 $line->ref = $objp->product_ref;
2330 $line->product_ref = $objp->product_ref;
2331 $line->libelle = $objp->product_label;
2332 $line->product_label = $objp->product_label;
2333 $line->product_barcode = $objp->product_barcode;
2334 $line->product_desc = $objp->product_desc;
2335 $line->fk_product_type = $objp->fk_product_type;
2336 $line->qty = $objp->qty;
2337 $line->subprice = $objp->subprice;
2338 $line->ref_ext = $objp->ref_ext;
2340 $line->vat_src_code = $objp->vat_src_code;
2341 $line->tva_tx = $objp->tva_tx;
2342 $line->localtax1_tx = $objp->localtax1_tx;
2343 $line->localtax2_tx = $objp->localtax2_tx;
2344 $line->localtax1_type = $objp->localtax1_type;
2345 $line->localtax2_type = $objp->localtax2_type;
2346 $line->remise_percent = $objp->remise_percent;
2347 $line->fk_remise_except = $objp->fk_remise_except;
2348 $line->fk_product = $objp->fk_product;
2349 $line->date_start = $this->db->jdate($objp->date_start);
2350 $line->date_end = $this->db->jdate($objp->date_end);
2351 $line->info_bits = $objp->info_bits;
2352 $line->total_ht = $objp->total_ht;
2353 $line->total_tva = $objp->total_tva;
2354 $line->total_localtax1 = $objp->total_localtax1;
2355 $line->total_localtax2 = $objp->total_localtax2;
2356 $line->total_ttc = $objp->total_ttc;
2358 $line->code_ventilation = $objp->fk_code_ventilation;
2359 $line->fk_fournprice = $objp->fk_fournprice;
2360 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
2361 $line->pa_ht = $marginInfos[0];
2362 $line->marge_tx = $marginInfos[1];
2363 $line->marque_tx = $marginInfos[2];
2364 $line->rang = $objp->rang;
2365 $line->special_code = $objp->special_code;
2366 $line->fk_parent_line = $objp->fk_parent_line;
2367 $line->situation_percent = $objp->situation_percent;
2368 $line->fk_prev_id = $objp->fk_prev_id;
2369 $line->fk_unit = $objp->fk_unit;
2371 $line->batch = $objp->batch;
2372 $line->fk_warehouse = $objp->fk_warehouse;
2375 $line->fk_accounting_account = $objp->fk_code_ventilation;
2378 $line->fk_multicurrency = $objp->fk_multicurrency;
2379 $line->multicurrency_code = $objp->multicurrency_code;
2380 $line->multicurrency_subprice = $objp->multicurrency_subprice;
2381 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
2382 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
2383 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
2385 $line->fetch_optionals();
2388 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
2389 $tmpproduct =
new Product($this->db);
2390 $tmpproduct->fetch($objp->fk_product);
2391 $tmpproduct->getMultiLangs();
2393 $line->multilangs = $tmpproduct->multilangs;
2396 $this->lines[$i] = $line;
2400 $this->db->free($result);
2403 $this->error = $this->db->error();
2418 $this->tab_previous_situation_invoice = array();
2419 $this->tab_next_situation_invoice = array();
2421 $sql =
'SELECT rowid, type, situation_cycle_ref, situation_counter FROM '.MAIN_DB_PREFIX.
'facture';
2422 $sql .=
" WHERE rowid <> ".((int) $this->
id);
2423 $sql .=
' AND entity = '.((int) $this->entity);
2424 $sql .=
' AND situation_cycle_ref = '.(int) $this->situation_cycle_ref;
2425 $sql .=
' ORDER BY situation_counter ASC';
2427 dol_syslog(get_class($this).
'::fetchPreviousNextSituationInvoice ', LOG_DEBUG);
2428 $result = $this->db->query($sql);
2429 if ($result && $this->db->num_rows($result) > 0) {
2430 while ($objp = $this->db->fetch_object($result)) {
2431 $invoice =
new Facture($this->db);
2432 if ($invoice->fetch($objp->rowid) > 0) {
2433 if ($objp->situation_counter < $this->situation_counter
2434 || ($objp->situation_counter == $this->situation_counter && $objp->rowid < $this->id)
2436 $this->tab_previous_situation_invoice[] = $invoice;
2438 $this->tab_next_situation_invoice[] = $invoice;
2457 if (empty($this->
type)) {
2460 if (isset($this->
ref)) {
2461 $this->
ref = trim($this->
ref);
2463 if (isset($this->ref_ext)) {
2464 $this->ref_ext = trim($this->ref_ext);
2466 if (isset($this->ref_client)) {
2467 $this->ref_client = trim($this->ref_client);
2469 if (isset($this->increment)) {
2470 $this->increment = trim($this->increment);
2472 if (isset($this->close_code)) {
2473 $this->close_code = trim($this->close_code);
2475 if (isset($this->close_note)) {
2476 $this->close_note = trim($this->close_note);
2478 if (isset($this->note) || isset($this->note_private)) {
2479 $this->note = (isset($this->note) ? trim($this->note) : trim($this->note_private));
2481 if (isset($this->note) || isset($this->note_private)) {
2482 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note));
2484 if (isset($this->note_public)) {
2485 $this->note_public = trim($this->note_public);
2487 if (isset($this->model_pdf)) {
2488 $this->model_pdf = trim($this->model_pdf);
2490 if (isset($this->import_key)) {
2491 $this->import_key = trim($this->import_key);
2493 if (isset($this->retained_warranty)) {
2494 $this->retained_warranty = (float) $this->retained_warranty;
2496 if (!isset($this->fk_user_author) && isset($this->user_author) ) {
2497 $this->fk_user_author = $this->user_author;
2505 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facture SET";
2506 $sql .=
" ref=".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
2507 $sql .=
" ref_ext=".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
2508 $sql .=
" type=".(isset($this->
type) ? $this->db->escape($this->
type) :
"null").
",";
2509 $sql .=
" subtype=".(isset($this->subtype) ? $this->db->escape($this->subtype) :
"null").
",";
2510 $sql .=
" ref_client=".(isset($this->ref_client) ?
"'".$this->db->escape($this->ref_client).
"'" :
"null").
",";
2511 $sql .=
" increment=".(isset($this->increment) ?
"'".$this->db->escape($this->increment).
"'" :
"null").
",";
2512 $sql .=
" fk_soc=".(isset($this->socid) ? $this->db->escape($this->socid) :
"null").
",";
2513 $sql .=
" datec=".(strval($this->date_creation) !=
'' ?
"'".$this->db->idate($this->date_creation).
"'" :
'null').
",";
2514 $sql .=
" datef=".(strval($this->date) !=
'' ?
"'".$this->db->idate($this->date).
"'" :
'null').
",";
2515 $sql .=
" date_pointoftax=".(strval($this->date_pointoftax) !=
'' ?
"'".$this->db->idate($this->date_pointoftax).
"'" :
'null').
",";
2516 $sql .=
" date_valid=".(strval($this->date_validation) !=
'' ?
"'".$this->db->idate($this->date_validation).
"'" :
'null').
",";
2517 $sql .=
" paye=".(isset($this->paye) ? $this->db->escape($this->paye) : 0).
",";
2518 $sql .=
" close_code=".(isset($this->close_code) ?
"'".$this->db->escape($this->close_code).
"'" :
"null").
",";
2519 $sql .=
" close_note=".(isset($this->close_note) ?
"'".$this->db->escape($this->close_note).
"'" :
"null").
",";
2520 $sql .=
" total_tva=".(isset($this->total_tva) ? $this->total_tva :
"null").
",";
2521 $sql .=
" localtax1=".(isset($this->total_localtax1) ? $this->total_localtax1 :
"null").
",";
2522 $sql .=
" localtax2=".(isset($this->total_localtax2) ? $this->total_localtax2 :
"null").
",";
2523 $sql .=
" total_ht=".(isset($this->total_ht) ? $this->total_ht :
"null").
",";
2524 $sql .=
" total_ttc=".(isset($this->total_ttc) ? $this->total_ttc :
"null").
",";
2525 $sql .=
" revenuestamp=".((isset($this->revenuestamp) && $this->revenuestamp !=
'') ? $this->db->escape($this->revenuestamp) :
"null").
",";
2526 $sql .=
" fk_statut=".(isset($this->
status) ? ((int) $this->
status) :
"null").
",";
2527 $sql .=
" fk_user_author=".(isset($this->fk_user_author) ? ((int) $this->fk_user_author) :
"null").
",";
2528 $sql .=
" fk_user_valid=".(isset($this->fk_user_valid) ? $this->db->escape($this->fk_user_valid) :
"null").
",";
2529 $sql .=
" fk_facture_source=".(isset($this->fk_facture_source) ? $this->db->escape($this->fk_facture_source) :
"null").
",";
2530 $sql .=
" fk_projet=".(isset($this->fk_project) ? $this->db->escape($this->fk_project) :
"null").
",";
2531 $sql .=
" fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->db->escape($this->cond_reglement_id) :
"null").
",";
2532 $sql .=
" fk_mode_reglement=".(isset($this->mode_reglement_id) ? $this->db->escape($this->mode_reglement_id) :
"null").
",";
2533 $sql .=
" date_lim_reglement=".(strval($this->date_lim_reglement) !=
'' ?
"'".$this->db->idate($this->date_lim_reglement).
"'" :
'null').
",";
2534 $sql .=
" note_private=".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
2535 $sql .=
" note_public=".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
2536 $sql .=
" model_pdf=".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
2537 $sql .=
" import_key=".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null").
",";
2538 $sql .=
" situation_cycle_ref=".(empty($this->situation_cycle_ref) ?
"null" : $this->db->escape($this->situation_cycle_ref)).
",";
2539 $sql .=
" situation_counter=".(empty($this->situation_counter) ?
"null" : $this->db->escape($this->situation_counter)).
",";
2540 $sql .=
" situation_final=".(empty($this->situation_final) ?
"0" : $this->db->escape($this->situation_final)).
",";
2541 $sql .=
" retained_warranty=".(empty($this->retained_warranty) ?
"0" : $this->db->escape($this->retained_warranty)).
",";
2542 $sql .=
" retained_warranty_date_limit=".(strval($this->retained_warranty_date_limit) !=
'' ?
"'".$this->db->idate($this->retained_warranty_date_limit).
"'" :
'null').
",";
2543 $sql .=
" retained_warranty_fk_cond_reglement=".(isset($this->retained_warranty_fk_cond_reglement) ? intval($this->retained_warranty_fk_cond_reglement) :
"null");
2544 $sql .=
" WHERE rowid=".((int) $this->
id);
2548 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
2549 $resql = $this->db->query($sql);
2552 $this->errors[] =
"Error ".$this->db->lasterror();
2562 if (!$error && !$notrigger) {
2573 foreach ($this->errors as $errmsg) {
2574 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
2575 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2577 $this->db->rollback();
2580 $this->db->commit();
2596 global $conf, $langs;
2598 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
2599 include_once DOL_DOCUMENT_ROOT.
'/core/class/discount.class.php';
2604 $result = $remise->fetch($idremise);
2607 if ($remise->fk_facture) {
2608 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed");
2609 $this->db->rollback();
2614 $facligne->fk_facture = $this->id;
2615 $facligne->fk_remise_except = $remise->id;
2616 $facligne->desc = $remise->description;
2617 $facligne->vat_src_code = $remise->vat_src_code;
2618 $facligne->tva_tx = $remise->tva_tx;
2619 $facligne->subprice = -$remise->amount_ht;
2620 $facligne->fk_product = 0;
2622 $facligne->remise_percent = 0;
2623 $facligne->rang = -1;
2624 $facligne->info_bits = 2;
2627 $facligne->rang = 1;
2628 $linecount = count($this->lines);
2629 for ($ii = 1; $ii <= $linecount; $ii++) {
2635 if ($remise->fk_facture_source > 0) {
2636 $srcinvoice =
new Facture($this->db);
2637 $srcinvoice->fetch($remise->fk_facture_source);
2638 include_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmargin.class.php';
2640 $arraytmp = $formmargin->getMarginInfosArray($srcinvoice,
false);
2641 $facligne->pa_ht = $arraytmp[
'pa_total'];
2644 $facligne->total_ht = -$remise->amount_ht;
2645 $facligne->total_tva = -$remise->amount_tva;
2646 $facligne->total_ttc = -$remise->amount_ttc;
2648 $facligne->multicurrency_subprice = -$remise->multicurrency_subprice;
2649 $facligne->multicurrency_total_ht = -$remise->multicurrency_amount_ht;
2650 $facligne->multicurrency_total_tva = -$remise->multicurrency_amount_tva;
2651 $facligne->multicurrency_total_ttc = -$remise->multicurrency_amount_ttc;
2653 $lineid = $facligne->insert();
2658 $result = $remise->link_to_invoice($lineid, 0);
2660 $this->error = $remise->error;
2661 $this->db->rollback();
2665 $this->db->commit();
2668 $this->error = $facligne->error;
2669 $this->db->rollback();
2673 $this->error = $facligne->error;
2674 $this->db->rollback();
2678 $this->db->rollback();
2700 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
2701 if (empty($ref_client)) {
2702 $sql .=
' SET ref_client = NULL';
2704 $sql .=
' SET ref_client = \''.$this->db->escape($ref_client).
'\'';
2706 $sql .=
" WHERE rowid = ".((int) $this->
id);
2708 dol_syslog(__METHOD__.
' this->id='.$this->id.
', ref_client='.$ref_client, LOG_DEBUG);
2709 $resql = $this->db->query($sql);
2711 $this->errors[] = $this->db->error();
2716 $this->ref_client = $ref_client;
2719 if (!$notrigger && empty($error)) {
2729 $this->ref_client = $ref_client;
2731 $this->db->commit();
2734 foreach ($this->errors as $errmsg) {
2735 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2736 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2738 $this->db->rollback();
2751 public function delete($user, $notrigger = 0, $idwarehouse = -1)
2753 global $langs, $conf;
2754 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
2758 dol_syslog(get_class($this).
"::delete rowid=".$rowid.
", ref=".$this->ref.
", thirdparty=".(empty($this->thirdparty) ?
'' : $this->thirdparty->name), LOG_DEBUG);
2771 if (!$error && !$notrigger) {
2785 dol_syslog(get_class($this).
"::delete error deleteExtraFields ".$this->error, LOG_ERR);
2799 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'societe_remise_except';
2800 $sql .=
' WHERE fk_facture_source = '.((int) $rowid);
2801 $sql .=
' AND fk_facture_line IS NULL';
2802 $resql = $this->db->query($sql);
2806 $list_rowid_det = array();
2807 foreach ($this->lines as $key => $invoiceline) {
2808 $list_rowid_det[] = $invoiceline->id;
2812 if (count($list_rowid_det)) {
2813 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
2814 $sql .=
' SET fk_facture = NULL, fk_facture_line = NULL';
2815 $sql .=
' WHERE fk_facture_line IN ('.$this->db->sanitize(join(
',', $list_rowid_det)).
')';
2817 if (!$this->db->query($sql)) {
2818 $this->error = $this->db->error().
" sql=".$sql;
2819 $this->errors[] = $this->error;
2820 $this->db->rollback();
2827 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'eventorganization_conferenceorboothattendee';
2828 $sql .=
' SET fk_invoice = NULL';
2829 $sql .=
' WHERE fk_invoice = '.((int) $rowid);
2831 if (!$this->db->query($sql)) {
2832 $this->error = $this->db->error().
" sql=".$sql;
2833 $this->errors[] = $this->error;
2834 $this->db->rollback();
2838 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'element_time';
2839 $sql .=
' SET invoice_id = NULL, invoice_line_id = NULL';
2840 $sql .=
' WHERE invoice_id = '.((int) $rowid);
2842 if (!$this->db->query($sql)) {
2843 $this->error = $this->db->error().
" sql=".$sql;
2844 $this->errors[] = $this->error;
2845 $this->db->rollback();
2850 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL') && $idwarehouse != -1) {
2851 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
2852 $langs->load(
"agenda");
2854 $num = count($this->lines);
2855 for ($i = 0; $i < $num; $i++) {
2856 if ($this->lines[$i]->fk_product > 0) {
2858 $mouvP->origin = &$this;
2859 $mouvP->setOrigin($this->element, $this->
id);
2861 if ($this->
type == self::TYPE_CREDIT_NOTE) {
2862 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceDeleteDolibarr", $this->ref));
2864 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceDeleteDolibarr", $this->ref));
2871 $main = MAIN_DB_PREFIX.
'facturedet';
2872 $ef = $main.
"_extrafields";
2873 $sqlef =
"DELETE FROM ".$ef.
" WHERE fk_object IN (SELECT rowid FROM ".$main.
" WHERE fk_facture = ".((int) $rowid).
")";
2875 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'facturedet WHERE fk_facture = '.((int) $rowid);
2878 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'facture WHERE rowid = '.((int) $rowid);
2880 $resql = $this->db->query($sql);
2888 if ($conf->facture->dir_output && !empty($this->
ref)) {
2889 $dir = $conf->facture->dir_output.
"/".$ref;
2890 $file = $conf->facture->dir_output.
"/".$ref.
"/".$ref.
".pdf";
2891 if (file_exists($file)) {
2895 $langs->load(
"errors");
2896 $this->error = $langs->trans(
"ErrorFailToDeleteFile", $file);
2897 $this->errors[] = $this->error;
2898 $this->db->rollback();
2902 if (file_exists($dir)) {
2904 $langs->load(
"errors");
2905 $this->error = $langs->trans(
"ErrorFailToDeleteDir", $dir);
2906 $this->errors[] = $this->error;
2907 $this->db->rollback();
2913 $this->db->commit();
2916 $this->error = $this->db->lasterror().
" sql=".$sql;
2917 $this->errors[] = $this->error;
2918 $this->db->rollback();
2922 $this->error = $this->db->lasterror().
" sql=".$sql;
2923 $this->errors[] = $this->error;
2924 $this->db->rollback();
2928 $this->db->rollback();
2945 public function set_paid($user, $close_code =
'', $close_note =
'')
2948 dol_syslog(get_class($this).
"::set_paid is deprecated, use setPaid instead", LOG_NOTICE);
2949 return $this->
setPaid($user, $close_code, $close_note);
2962 public function setPaid($user, $close_code =
'', $close_note =
'')
2966 if ($this->paye != 1) {
2971 dol_syslog(get_class($this).
"::setPaid rowid=".((
int) $this->
id), LOG_DEBUG);
2973 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET';
2974 $sql .=
' fk_statut='.self::STATUS_CLOSED;
2979 $sql .=
", close_code='".$this->db->escape($close_code).
"'";
2982 $sql .=
", close_note='".$this->db->escape($close_note).
"'";
2984 $sql .=
', fk_user_closing = '.((int) $user->id);
2985 $sql .=
", date_closing = '".$this->db->idate($now).
"'";
2986 $sql .=
" WHERE rowid = ".((int) $this->
id);
2988 $resql = $this->db->query($sql);
2998 $this->error = $this->db->lasterror();
3002 $this->db->commit();
3005 $this->db->rollback();
3028 dol_syslog(get_class($this).
"::set_unpaid is deprecated, use setUnpaid instead", LOG_NOTICE);
3046 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
3047 $sql .=
' SET paye=0, fk_statut='.self::STATUS_VALIDATED.
', close_code=null, close_note=null,';
3048 $sql .=
' date_closing=null,';
3049 $sql .=
' fk_user_closing=null';
3050 $sql .=
" WHERE rowid = ".((int) $this->
id);
3052 dol_syslog(get_class($this).
"::setUnpaid", LOG_DEBUG);
3053 $resql = $this->db->query($sql);
3063 $this->error = $this->db->error();
3068 $this->db->commit();
3071 $this->db->rollback();
3093 dol_syslog(get_class($this).
"::set_canceled is deprecated, use setCanceled instead", LOG_NOTICE);
3094 return $this->
setCanceled($user, $close_code, $close_note);
3107 public function setCanceled($user, $close_code =
'', $close_note =
'')
3109 dol_syslog(get_class($this).
"::setCanceled rowid=".((
int) $this->
id), LOG_DEBUG);
3114 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET';
3115 $sql .=
' fk_statut='.self::STATUS_ABANDONED;
3117 $sql .=
", close_code='".$this->db->escape($close_code).
"'";
3120 $sql .=
", close_note='".$this->db->escape($close_note).
"'";
3122 $sql .=
', fk_user_closing = '.((int) $user->id);
3123 $sql .=
", date_closing = '".$this->db->idate($now).
"'";
3124 $sql .=
" WHERE rowid = ".((int) $this->
id);
3126 $resql = $this->db->query($sql);
3130 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
3131 $sql .=
' SET fk_facture = NULL';
3132 $sql .=
' WHERE fk_facture = '.((int) $this->
id);
3134 $resql = $this->db->query($sql);
3139 $this->db->rollback();
3144 $this->db->commit();
3147 $this->error = $this->db->error().
" sql=".$sql;
3148 $this->db->rollback();
3152 $this->error = $this->db->error().
" sql=".$sql;
3153 $this->db->rollback();
3169 public function validate($user, $force_number =
'', $idwarehouse = 0, $notrigger = 0, $batch_rule = 0)
3171 global $conf, $langs, $mysoc;
3172 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
3174 $productStatic =
null;
3175 $warehouseStatic =
null;
3176 if ($batch_rule > 0) {
3177 require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
3178 require_once DOL_DOCUMENT_ROOT.
'/product/class/productbatch.class.php';
3179 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
3180 $productStatic =
new Product($this->db);
3181 $warehouseStatic =
new Entrepot($this->db);
3188 dol_syslog(get_class($this).
'::validate user='.$user->id.
', force_number='.$force_number.
', idwarehouse='.$idwarehouse);
3195 if ($this->
status != self::STATUS_DRAFT) {
3196 dol_syslog(get_class($this).
"::validate Current status is not draft. operation canceled.", LOG_WARNING);
3199 if (count($this->lines) <= 0) {
3200 $langs->load(
"errors");
3201 $this->error = $langs->trans(
"ErrorObjectMustHaveLinesToBeValidated", $this->
ref);
3205 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && !$user->hasRight(
'facture',
'invoice_advance',
'validate'))) {
3206 $this->error =
'Permission denied';
3207 dol_syslog(get_class($this).
"::validate ".$this->error.
' MAIN_USE_ADVANCED_PERMS=' .
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS'), LOG_ERR);
3210 if ((preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) &&
3218 if (!$last_of_type[0]) {
3219 $this->error = $langs->transnoentities(
"ErrorInvoiceIsNotLastOfSameType", $this->
ref,
dol_print_date($this->date,
'day'),
dol_print_date($last_of_type[1],
'day'));
3225 if (!empty($this->thirdparty) && is_object($this->thirdparty)) {
3226 $array_to_check = array(
'IDPROF1',
'IDPROF2',
'IDPROF3',
'IDPROF4',
'IDPROF5',
'IDPROF6',
'EMAIL',
'ACCOUNTANCY_CODE_CUSTOMER');
3227 foreach ($array_to_check as $key) {
3228 $keymin = strtolower($key);
3229 if (!property_exists($this->thirdparty, $keymin)) {
3232 $vallabel = $this->thirdparty->$keymin;
3234 $i = (int) preg_replace(
'/[^0-9]/',
'', $key);
3236 if ($this->thirdparty->isACompany()) {
3238 if ($mysoc->country_id > 0 && $this->thirdparty->country_id == $mysoc->country_id) {
3239 $idprof_mandatory =
'SOCIETE_'.$key.
'_INVOICE_MANDATORY';
3240 if (!$vallabel && !empty($conf->global->$idprof_mandatory)) {
3241 $langs->load(
"errors");
3242 $this->error = $langs->trans(
'ErrorProdIdIsMandatory', $langs->transcountry(
'ProfId'.$i, $this->thirdparty->country_code)).
' ('.$langs->trans(
"ForbiddenBySetupRules").
') ['.$langs->trans(
'Company').
' : '.$this->thirdparty->name.
']';
3243 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3249 if ($key ==
'EMAIL') {
3251 if (
getDolGlobalString(
'SOCIETE_EMAIL_INVOICE_MANDATORY') && !isValidEMail($this->thirdparty->email)) {
3252 $langs->load(
"errors");
3253 $this->error = $langs->trans(
"ErrorBadEMail", $this->thirdparty->email).
' ('.$langs->trans(
"ForbiddenBySetupRules").
') ['.$langs->trans(
'Company').
' : '.$this->thirdparty->name.
']';
3254 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3258 if ($key ==
'ACCOUNTANCY_CODE_CUSTOMER') {
3260 if (
getDolGlobalString(
'SOCIETE_ACCOUNTANCY_CODE_CUSTOMER_INVOICE_MANDATORY') && empty($this->thirdparty->code_compta)) {
3261 $langs->load(
"errors");
3262 $this->error = $langs->trans(
"ErrorAccountancyCodeCustomerIsMandatory", $this->thirdparty->name).
' ('.$langs->trans(
"ForbiddenBySetupRules").
')';
3263 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3272 $array_to_check = array(
'REF_CLIENT'=>
'RefCustomer');
3273 foreach ($array_to_check as $key => $val) {
3274 $keymin = strtolower($key);
3275 $vallabel = $this->$keymin;
3278 $keymandatory =
'INVOICE_'.$key.
'_MANDATORY_FOR_VALIDATION';
3280 $langs->load(
"errors");
3282 setEventMessages($langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv($val)),
null,
'errors');
3289 if ($this->
type == self::TYPE_REPLACEMENT) {
3291 if ($this->fk_facture_source <= 0) {
3292 $this->error = $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"InvoiceReplacement"));
3293 $this->db->rollback();
3298 $facreplaced =
new Facture($this->db);
3299 $result = $facreplaced->fetch($this->fk_facture_source);
3301 $this->error = $langs->trans(
"ErrorBadInvoice");
3302 $this->db->rollback();
3307 $idreplacement = $facreplaced->getIdReplacingInvoice(
'validated');
3308 if ($idreplacement && $idreplacement != $this->
id) {
3309 $facreplacement =
new Facture($this->db);
3310 $facreplacement->fetch($idreplacement);
3311 $this->error = $langs->trans(
"ErrorInvoiceAlreadyReplaced", $facreplaced->ref, $facreplacement->ref);
3312 $this->db->rollback();
3316 $result = $facreplaced->setCanceled($user, self::CLOSECODE_REPLACED,
'');
3318 $this->error = $facreplaced->error;
3319 $this->db->rollback();
3325 if ($force_number) {
3326 $num = $force_number;
3327 } elseif (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
3343 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
3344 $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).
"'";
3346 $sql .=
", datef='".$this->db->idate($this->date).
"'";
3347 $sql .=
", date_lim_reglement='".$this->db->idate($this->date_lim_reglement).
"'";
3349 $sql .=
" WHERE rowid = ".((int) $this->
id);
3351 dol_syslog(get_class($this).
"::validate", LOG_DEBUG);
3352 $resql = $this->db->query($sql);
3359 if (!$error && (preg_match(
'/^[\(]?PROV/i', $this->
ref))) {
3365 $result = $this->thirdparty->setAsCustomer();
3368 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL') && $idwarehouse > 0) {
3369 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3370 $langs->load(
"agenda");
3373 $cpt = count($this->lines);
3374 for ($i = 0; $i < $cpt; $i++) {
3375 if ($this->lines[$i]->fk_product > 0) {
3377 $mouvP->origin = &$this;
3378 $mouvP->setOrigin($this->element, $this->
id);
3384 if ($this->
type == self::TYPE_CREDIT_NOTE) {
3385 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceValidatedInDolibarr", $num));
3388 $this->error = $mouvP->error;
3391 $is_batch_line =
false;
3392 if ($batch_rule > 0) {
3393 $productStatic->fetch($this->lines[$i]->fk_product);
3394 if ($productStatic->hasbatch()) {
3395 $is_batch_line =
true;
3396 $product_qty_remain = $this->lines[$i]->qty;
3402 $sortfield =
'pl.sellby,pl.eatby,pb.qty,pl.rowid';
3403 $sortorder =
'ASC,ASC,ASC,ASC';
3406 $resBatchList = $productbatch->findAllForProduct($productStatic->id, $idwarehouse, (
getDolGlobalInt(
'STOCK_ALLOW_NEGATIVE_TRANSFER') ?
null : 0), $sortfield, $sortorder);
3407 if (!is_array($resBatchList)) {
3409 $this->error = $this->db->lasterror();
3413 $batchList = $resBatchList;
3414 if (empty($batchList)) {
3416 $langs->load(
'errors');
3417 $warehouseStatic->fetch($idwarehouse);
3418 $this->error = $langs->trans(
'ErrorBatchNoFoundForProductInWarehouse', $productStatic->label, $warehouseStatic->ref);
3419 dol_syslog(__METHOD__.
' Error: '.$langs->transnoentitiesnoconv(
'ErrorBatchNoFoundForProductInWarehouse', $productStatic->label, $warehouseStatic->ref), LOG_ERR);
3422 foreach ($batchList as $batch) {
3423 if ($batch->qty <= 0) {
3428 if ($batch->qty >= $product_qty_remain) {
3429 $product_batch_qty = $product_qty_remain;
3432 $product_batch_qty = $batch->qty;
3434 $result = $mouvP->livraison($user, $productStatic->id, $idwarehouse, $product_batch_qty, $this->lines[$i]->subprice, $langs->trans(
'InvoiceValidatedInDolibarr', $num),
'',
'',
'', $batch->batch);
3437 $this->error = $mouvP->error;
3438 $this->errors = $mouvP->errors;
3442 $product_qty_remain -= $product_batch_qty;
3444 if ($product_qty_remain <= 0) {
3449 if (!$error && $product_qty_remain > 0) {
3452 $batch = $batchList[0];
3453 $result = $mouvP->livraison($user, $productStatic->id, $idwarehouse, $product_qty_remain, $this->lines[$i]->subprice, $langs->trans(
'InvoiceValidatedInDolibarr', $num),
'',
'',
'', $batch->batch);
3456 $this->error = $mouvP->error;
3457 $this->errors = $mouvP->errors;
3461 $langs->load(
'errors');
3462 $warehouseStatic->fetch($idwarehouse);
3463 $this->error = $langs->trans(
'ErrorBatchNoFoundEnoughQuantityForProductInWarehouse', $productStatic->label, $warehouseStatic->ref);
3464 dol_syslog(__METHOD__.
' Error: '.$langs->transnoentitiesnoconv(
'ErrorBatchNoFoundEnoughQuantityForProductInWarehouse', $productStatic->label, $warehouseStatic->ref), LOG_ERR);
3471 if (!$is_batch_line) {
3472 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceValidatedInDolibarr", $num));
3475 $this->error = $mouvP->error;
3476 $this->errors = $mouvP->errors;
3489 if (!$error && $this->
type == self::TYPE_CREDIT_NOTE && $this->fk_facture_source > 0) {
3490 $invoice_situation =
new Facture($this->db);
3491 $result = $invoice_situation->fetch($this->fk_facture_source);
3492 if ($result > 0 && $invoice_situation->type == self::TYPE_SITUATION && $invoice_situation->situation_final == 1) {
3493 $invoice_situation->situation_final = 0;
3495 $result = $invoice_situation->setFinal($user, 1);
3498 $this->error = $invoice_situation->error;
3499 $this->errors = $invoice_situation->errors;
3505 if (!$error && !$notrigger) {
3515 $this->oldref = $this->ref;
3518 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
3520 $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).
"'";
3521 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'facture/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
3522 $resql = $this->db->query($sql);
3525 $this->error = $this->db->lasterror();
3527 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'facture/".$this->db->escape($this->newref).
"'";
3528 $sql .=
" WHERE filepath = 'facture/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
3529 $resql = $this->db->query($sql);
3532 $this->error = $this->db->lasterror();
3538 $dirsource = $conf->facture->dir_output.
'/'.$oldref;
3539 $dirdest = $conf->facture->dir_output.
'/'.$newref;
3540 if (!$error && file_exists($dirsource)) {
3541 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
3543 if (@rename($dirsource, $dirdest)) {
3546 $listoffiles =
dol_dir_list($conf->facture->dir_output.
'/'.$newref,
'files', 1,
'^'.preg_quote($oldref,
'/'));
3547 foreach ($listoffiles as $fileentry) {
3548 $dirsource = $fileentry[
'name'];
3549 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
3550 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
3551 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
3552 @rename($dirsource, $dirdest);
3570 $this->date_validation = $now;
3575 $nboflines = count($this->lines);
3576 while (($i < $nboflines) && $final) {
3577 $final = ($this->lines[$i]->situation_percent == 100);
3581 if (empty($final)) {
3582 $this->situation_final = 0;
3584 $this->situation_final = 1;
3595 $this->db->commit();
3598 $this->db->rollback();
3611 foreach ($this->tab_next_situation_invoice as $next_invoice) {
3612 $is_last = $next_invoice->is_last_in_cycle();
3614 if ($next_invoice->status == self::STATUS_DRAFT && $is_last != 1) {
3615 $this->error = $langs->trans(
'updatePriceNextInvoiceErrorUpdateline', $next_invoice->ref);
3619 foreach ($next_invoice->lines as $line) {
3620 $result = $next_invoice->updateline(
3625 $line->remise_percent,
3629 $line->localtax1_tx,
3630 $line->localtax2_tx,
3633 $line->product_type,
3634 $line->fk_parent_line,
3636 $line->fk_fournprice,
3639 $line->special_code,
3640 $line->array_options,
3641 $line->situation_percent,
3646 $this->error = $langs->trans(
'updatePriceNextInvoiceErrorUpdateline', $next_invoice->ref);
3667 global $conf, $langs;
3671 if ($this->
status == self::STATUS_DRAFT) {
3672 dol_syslog(__METHOD__.
" already draft status", LOG_WARNING);
3680 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facture";
3681 $sql .=
" SET fk_statut = ".self::STATUS_DRAFT;
3682 $sql .=
" WHERE rowid = ".((int) $this->
id);
3684 $result = $this->db->query($sql);
3687 $this->oldcopy = clone $this;
3691 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL')) {
3692 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3693 $langs->load(
"agenda");
3695 $num = count($this->lines);
3696 for ($i = 0; $i < $num; $i++) {
3697 if ($this->lines[$i]->fk_product > 0) {
3699 $mouvP->origin = &$this;
3700 $mouvP->setOrigin($this->element, $this->
id);
3702 if ($this->
type == self::TYPE_CREDIT_NOTE) {
3703 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceBackToDraftInDolibarr", $this->ref));
3705 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceBackToDraftInDolibarr", $this->ref));
3712 $old_statut = $this->status;
3717 $result = $this->
call_trigger(
'BILL_UNVALIDATE', $user);
3720 $this->
statut = $old_statut;
3721 $this->
status = $old_statut;
3725 $this->db->rollback();
3730 $this->db->commit();
3733 $this->db->rollback();
3737 $this->error = $this->db->error();
3738 $this->db->rollback();
3793 $remise_percent = 0,
3798 $fk_remise_except = 0,
3799 $price_base_type =
'HT',
3806 $fk_parent_line = 0,
3807 $fk_fournprice =
null,
3810 $array_options = array(),
3811 $situation_percent = 100,
3816 $noupdateafterinsertline = 0
3820 dol_syslog(__METHOD__.
": using line label is deprecated", LOG_WARNING);
3824 global $mysoc, $conf, $langs;
3826 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);
3828 if ($this->
status == self::STATUS_DRAFT) {
3829 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
3832 if (empty($remise_percent)) {
3833 $remise_percent = 0;
3838 if (empty($info_bits)) {
3844 if (empty($ventil)) {
3847 if (empty($txtva)) {
3850 if (empty($txlocaltax1)) {
3853 if (empty($txlocaltax2)) {
3856 if (empty($fk_parent_line) || $fk_parent_line < 0) {
3857 $fk_parent_line = 0;
3859 if (empty($fk_prev_id)) {
3860 $fk_prev_id =
'null';
3862 if (!isset($situation_percent) || $situation_percent > 100 || (
string) $situation_percent ==
'') {
3863 $situation_percent = 100;
3865 if (empty($ref_ext)) {
3869 $remise_percent =
price2num($remise_percent);
3872 $pu_ht_devise =
price2num($pu_ht_devise);
3875 if (!preg_match(
'/\((.*)\)/', $txtva)) {
3881 if ($price_base_type ==
'HT') {
3892 if ($date_start && $date_end && $date_start > $date_end) {
3893 $langs->load(
"errors");
3894 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
3900 $product_type = $type;
3901 if (!empty($fk_product) && $fk_product > 0) {
3902 $product =
new Product($this->db);
3903 $result = $product->fetch($fk_product);
3904 $product_type = $product->type;
3906 if (
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_INVOICE') && $product_type == 0 && $product->stock_reel < $qty) {
3907 $langs->load(
"errors");
3908 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnInvoice', $product->ref);
3909 $this->db->rollback();
3919 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
3920 $vat_src_code = $reg[1];
3921 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
3929 $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);
3931 $total_ht = $tabprice[0];
3932 $total_tva = $tabprice[1];
3933 $total_ttc = $tabprice[2];
3934 $total_localtax1 = $tabprice[9];
3935 $total_localtax2 = $tabprice[10];
3936 $pu_ht = $tabprice[3];
3939 $multicurrency_total_ht = $tabprice[16];
3940 $multicurrency_total_tva = $tabprice[17];
3941 $multicurrency_total_ttc = $tabprice[18];
3942 $pu_ht_devise = $tabprice[19];
3946 if ($ranktouse == -1) {
3947 $rangmax = $this->
line_max($fk_parent_line);
3948 $ranktouse = $rangmax + 1;
3954 $this->line->context = $this->context;
3956 $this->line->fk_facture = $this->id;
3957 $this->line->label = $label;
3958 $this->line->desc = $desc;
3959 $this->line->ref_ext = $ref_ext;
3961 $this->line->qty = ($this->
type == self::TYPE_CREDIT_NOTE ? abs($qty) : $qty);
3962 $this->line->subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht) : $pu_ht);
3964 $this->line->vat_src_code = $vat_src_code;
3965 $this->line->tva_tx = $txtva;
3966 $this->line->localtax1_tx = ($total_localtax1 ? $localtaxes_type[1] : 0);
3967 $this->line->localtax2_tx = ($total_localtax2 ? $localtaxes_type[3] : 0);
3968 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
3969 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
3971 $this->line->total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ht) : $total_ht);
3972 $this->line->total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ttc) : $total_ttc);
3973 $this->line->total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_tva) : $total_tva);
3974 $this->line->total_localtax1 = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_localtax1) : $total_localtax1);
3975 $this->line->total_localtax2 = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_localtax2) : $total_localtax2);
3977 $this->line->fk_product = $fk_product;
3978 $this->line->product_type = $product_type;
3979 $this->line->remise_percent = $remise_percent;
3980 $this->line->date_start = $date_start;
3981 $this->line->date_end = $date_end;
3982 $this->line->ventil = $ventil;
3983 $this->line->rang = $ranktouse;
3984 $this->line->info_bits = $info_bits;
3985 $this->line->fk_remise_except = $fk_remise_except;
3987 $this->line->special_code = $special_code;
3988 $this->line->fk_parent_line = $fk_parent_line;
3989 $this->line->origin = $origin;
3990 $this->line->origin_id = $origin_id;
3991 $this->line->situation_percent = $situation_percent;
3992 $this->line->fk_prev_id = $fk_prev_id;
3993 $this->line->fk_unit = $fk_unit;
3996 $this->line->fk_fournprice = $fk_fournprice;
3997 $this->line->pa_ht = $pa_ht;
4000 $this->line->fk_multicurrency = $this->fk_multicurrency;
4001 $this->line->multicurrency_code = $this->multicurrency_code;
4002 $this->line->multicurrency_subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht_devise) : $pu_ht_devise);
4004 $this->line->multicurrency_total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ht) : $multicurrency_total_ht);
4005 $this->line->multicurrency_total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_tva) : $multicurrency_total_tva);
4006 $this->line->multicurrency_total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ttc) : $multicurrency_total_ttc);
4008 if (is_array($array_options) && count($array_options) > 0) {
4009 $this->line->array_options = $array_options;
4012 $result = $this->line->insert();
4015 if (!empty($fk_parent_line)) {
4017 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
4018 $linecount = count($this->lines);
4019 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
4025 if (empty($noupdateafterinsertline)) {
4030 $this->db->commit();
4031 return $this->line->id;
4033 $this->error = $this->db->lasterror();
4034 $this->db->rollback();
4038 $this->error = $this->line->error;
4039 $this->errors = $this->line->errors;
4040 $this->db->rollback();
4044 $this->errors[] =
'status of invoice must be Draft to allow use of ->addline()';
4045 dol_syslog(get_class($this).
"::addline status of invoice must be Draft to allow use of ->addline()", LOG_ERR);
4081 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)
4083 global $conf, $user;
4086 dol_syslog(__METHOD__.
": using line label is deprecated", LOG_WARNING);
4089 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
4091 global $mysoc, $langs;
4093 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);
4095 if ($this->
status == self::STATUS_DRAFT) {
4098 if (!$this->error) {
4099 $this->error = $langs->trans(
'invoiceLineProgressError');
4105 if ($date_start && $date_end && $date_start > $date_end) {
4106 $langs->load(
"errors");
4107 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
4117 if (empty($fk_parent_line) || $fk_parent_line < 0) {
4118 $fk_parent_line = 0;
4120 if (empty($special_code) || $special_code == 3) {
4123 if (!isset($situation_percent) || $situation_percent > 100 || (
string) $situation_percent ==
'') {
4124 $situation_percent = 100;
4126 if (empty($ref_ext)) {
4130 $remise_percent =
price2num($remise_percent);
4133 $pu_ht_devise =
price2num($pu_ht_devise);
4135 if (!preg_match(
'/\((.*)\)/', $txtva)) {
4155 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
4156 $vat_src_code = $reg[1];
4157 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
4160 $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);
4162 $total_ht = $tabprice[0];
4163 $total_tva = $tabprice[1];
4164 $total_ttc = $tabprice[2];
4165 $total_localtax1 = $tabprice[9];
4166 $total_localtax2 = $tabprice[10];
4167 $pu_ht = $tabprice[3];
4168 $pu_tva = $tabprice[4];
4169 $pu_ttc = $tabprice[5];
4172 $multicurrency_total_ht = $tabprice[16];
4173 $multicurrency_total_tva = $tabprice[17];
4174 $multicurrency_total_ttc = $tabprice[18];
4175 $pu_ht_devise = $tabprice[19];
4180 if ($remise_percent > 0) {
4181 $remise = round(((
float) $pu * (
float) $remise_percent / 100), 2);
4182 $price = ((float) $pu - $remise);
4188 $line->fetch($rowid);
4189 $line->fetch_optionals();
4191 if (!empty($line->fk_product)) {
4192 $product =
new Product($this->db);
4193 $result = $product->fetch($line->fk_product);
4194 $product_type = $product->type;
4196 if (
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_INVOICE') && $product_type == 0 && $product->stock_reel < $qty) {
4197 $langs->load(
"errors");
4198 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnInvoice', $product->ref);
4199 $this->db->rollback();
4204 $staticline = clone $line;
4206 $line->oldline = $staticline;
4207 $this->line = $line;
4208 $this->line->context = $this->context;
4209 $this->line->rang = $rang;
4212 if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
4213 $rangmax = $this->
line_max($fk_parent_line);
4214 $this->line->rang = $rangmax + 1;
4216 $apply_abs_price_on_credit_note=
false;
4218 $apply_abs_price_on_credit_note =
true;
4222 $this->line->id = $rowid;
4223 $this->line->rowid = $rowid;
4224 $this->line->label = $label;
4225 $this->line->desc = $desc;
4226 $this->line->ref_ext = $ref_ext;
4227 $this->line->qty = ($this->
type == self::TYPE_CREDIT_NOTE ? abs($qty) : $qty);
4229 $this->line->vat_src_code = $vat_src_code;
4230 $this->line->tva_tx = $txtva;
4231 $this->line->localtax1_tx = $txlocaltax1;
4232 $this->line->localtax2_tx = $txlocaltax2;
4233 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
4234 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
4236 $this->line->remise_percent = $remise_percent;
4237 $this->line->subprice = ($apply_abs_price_on_credit_note ? -abs($pu_ht) : $pu_ht);
4238 $this->line->date_start = $date_start;
4239 $this->line->date_end = $date_end;
4240 $this->line->total_ht = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($total_ht) : $total_ht);
4241 $this->line->total_tva = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($total_tva) : $total_tva);
4242 $this->line->total_localtax1 = $total_localtax1;
4243 $this->line->total_localtax2 = $total_localtax2;
4244 $this->line->total_ttc = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($total_ttc) : $total_ttc);
4245 $this->line->info_bits = $info_bits;
4246 $this->line->special_code = $special_code;
4247 $this->line->product_type = $type;
4248 $this->line->fk_parent_line = $fk_parent_line;
4249 $this->line->skip_update_total = $skip_update_total;
4250 $this->line->situation_percent = $situation_percent;
4251 $this->line->fk_unit = $fk_unit;
4253 $this->line->fk_fournprice = $fk_fournprice;
4254 $this->line->pa_ht = $pa_ht;
4257 $this->line->multicurrency_subprice = ($apply_abs_price_on_credit_note ? -abs($pu_ht_devise) : $pu_ht_devise);
4258 $this->line->multicurrency_total_ht = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($multicurrency_total_ht) : $multicurrency_total_ht);
4259 $this->line->multicurrency_total_tva = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($multicurrency_total_tva) : $multicurrency_total_tva);
4260 $this->line->multicurrency_total_ttc = (($apply_abs_price_on_credit_note || $qty < 0) ? -abs($multicurrency_total_ttc) : $multicurrency_total_ttc);
4262 if (is_array($array_options) && count($array_options) > 0) {
4264 foreach ($array_options as $key => $value) {
4265 $this->line->array_options[$key] = $array_options[$key];
4269 $result = $this->line->update($user, $notrigger);
4272 if (!empty($fk_parent_line)) {
4278 $this->db->commit();
4281 $this->error = $this->line->error;
4282 $this->db->rollback();
4286 $this->error =
"Invoice statut makes operation forbidden";
4300 $sql =
'SELECT fd.situation_percent FROM '.MAIN_DB_PREFIX.
'facturedet fd
4301 INNER JOIN '.MAIN_DB_PREFIX.
'facture f ON (fd.fk_facture = f.rowid)
4302 WHERE fd.fk_prev_id = '.((int) $idline).
' AND f.fk_statut <> 0';
4304 $result = $this->db->query($sql);
4306 $this->error = $this->db->error();
4310 $obj = $this->db->fetch_object($result);
4312 if ($obj ===
null) {
4315 return ($situation_percent < $obj->situation_percent);
4331 global $mysoc, $user;
4334 if (($line->info_bits & 2) == 2) {
4338 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
4341 if ($percent > 100) {
4344 $line->situation_percent = $percent;
4345 $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);
4346 $line->total_ht = $tabprice[0];
4347 $line->total_tva = $tabprice[1];
4348 $line->total_ttc = $tabprice[2];
4349 $line->total_localtax1 = $tabprice[9];
4350 $line->total_localtax2 = $tabprice[10];
4351 $line->multicurrency_total_ht = $tabprice[16];
4352 $line->multicurrency_total_tva = $tabprice[17];
4353 $line->multicurrency_total_ttc = $tabprice[18];
4354 $line->update($user);
4357 if ($update_price) {
4373 dol_syslog(get_class($this).
"::deleteline rowid=".((
int) $rowid), LOG_DEBUG);
4375 if ($this->
status != self::STATUS_DRAFT) {
4376 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
4382 $line->context = $this->context;
4385 $result = $line->fetch($rowid);
4386 if (!($result > 0)) {
4391 if ($id > 0 && $line->fk_facture != $id) {
4392 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
4399 $staticline = clone $line;
4400 $line->oldline = $staticline;
4402 if ($line->delete($user) > 0) {
4406 $this->db->commit();
4409 $this->db->rollback();
4410 $this->error = $this->db->lasterror();
4414 $this->db->rollback();
4415 $this->error = $line->error;
4434 dol_syslog(get_class($this).
"::set_remise is deprecated, use setDiscount instead", LOG_NOTICE);
4435 return $this->
setDiscount($user, $remise, $notrigger);
4450 if (empty($remise)) {
4454 if ($user->hasRight(
'facture',
'creer')) {
4461 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
4462 $sql .=
' SET remise_percent = '.((float) $remise);
4463 $sql .=
" WHERE rowid = ".((int) $this->
id);
4464 $sql .=
' AND fk_statut = '.self::STATUS_DRAFT;
4467 $resql = $this->db->query($sql);
4469 $this->errors[] = $this->db->error();
4473 if (!$notrigger && empty($error)) {
4483 $this->remise_percent = $remise;
4486 $this->db->commit();
4489 foreach ($this->errors as $errmsg) {
4490 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
4491 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
4493 $this->db->rollback();
4580 global $conf, $langs;
4582 if ($this->module_source ==
'takepos') {
4583 $langs->load(
'cashdesk');
4585 $moduleName =
'takepos';
4586 $moduleSourceName =
'Takepos';
4587 $addonConstName =
'TAKEPOS_REF_ADDON';
4591 $conf->global->TAKEPOS_REF_ADDON =
'mod_takepos_ref_simple';
4594 $addon = $conf->global->TAKEPOS_REF_ADDON;
4596 $langs->load(
'bills');
4598 $moduleName =
'facture';
4599 $moduleSourceName =
'Invoice';
4600 $addonConstName =
'FACTURE_ADDON';
4604 $conf->global->FACTURE_ADDON =
'mod_facture_terre';
4606 $conf->global->FACTURE_ADDON =
'mod_facture_terre';
4608 $conf->global->FACTURE_ADDON =
'mod_facture_mercure';
4611 $addon = $conf->global->FACTURE_ADDON;
4614 if (!empty($addon)) {
4615 dol_syslog(
"Call getNextNumRef with ".$addonConstName.
" = " .
getDolGlobalString(
'FACTURE_ADDON').
", thirdparty=".$soc->name.
", type=".$soc->typent_code.
", mode=".$mode, LOG_DEBUG);
4619 $file = $addon.
'.php';
4620 $classname = $addon;
4624 $dirmodels = array_merge(array(
'/'), (array) $conf->modules_parts[
'models']);
4625 foreach ($dirmodels as $reldir) {
4626 $dir =
dol_buildpath($reldir.
'core/modules/'.$moduleName.
'/');
4629 if (is_file($dir.$file) && is_readable($dir.$file)) {
4630 $mybool |= include_once $dir.$file;
4636 $file = $addon.
'/'.$addon.
'.modules.php';
4637 $classname =
'mod_'.$moduleName.
'_'.$addon;
4638 $classname = preg_replace(
'/\-.*$/',
'', $classname);
4640 foreach ($conf->file->dol_document_root as $dirroot) {
4641 $dir = $dirroot.
'/core/modules/'.$moduleName.
'/';
4644 if (is_file($dir.$file) && is_readable($dir.$file)) {
4645 $mybool |= include_once $dir.$file;
4655 $obj =
new $classname();
4657 $numref = $obj->getNextValue($soc, $this, $mode);
4664 if ($mode !=
'last' && !$numref) {
4665 $this->error = $obj->error;
4671 $langs->load(
'errors');
4672 print $langs->trans(
'Error').
' '.$langs->trans(
'ErrorModuleSetupNotComplete', $langs->transnoentitiesnoconv($moduleSourceName));
4685 $sql =
'SELECT c.rowid, datec, date_valid as datev, tms as datem,';
4686 $sql .=
' date_closing as dateclosing,';
4687 $sql .=
' fk_user_author, fk_user_valid, fk_user_closing';
4688 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facture as c';
4689 $sql .=
' WHERE c.rowid = '.((int) $id);
4691 $result = $this->db->query($sql);
4693 if ($this->db->num_rows($result)) {
4694 $obj = $this->db->fetch_object($result);
4696 $this->
id = $obj->rowid;
4697 $this->user_creation_id = $obj->fk_user_author;
4698 $this->user_validation_id = $obj->fk_user_valid;
4699 $this->user_closing_id = $obj->fk_user_closing;
4701 $this->date_creation = $this->db->jdate($obj->datec);
4702 $this->date_modification = $this->db->jdate($obj->datem);
4703 $this->date_validation = $this->db->jdate($obj->datev);
4704 $this->date_closing = $this->db->jdate($obj->dateclosing);
4706 $this->db->free($result);
4727 public function liste_array($shortlist = 0, $draft = 0, $excluser =
null, $socid = 0, $limit = 0, $offset = 0, $sortfield =
'f.datef,f.rowid', $sortorder =
'DESC')
4730 global $conf, $user;
4734 $sql =
"SELECT s.rowid, s.nom as name, s.client,";
4735 $sql .=
" f.rowid as fid, f.ref as ref, f.datef as df";
4736 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4737 $sql .=
", sc.fk_soc, sc.fk_user";
4739 $sql .=
" FROM ".MAIN_DB_PREFIX.
"societe as s, ".MAIN_DB_PREFIX.
"facture as f";
4740 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4741 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
4743 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice').
")";
4744 $sql .=
" AND f.fk_soc = s.rowid";
4745 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4746 $sql .=
" AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4749 $sql .=
" AND s.rowid = ".((int) $socid);
4752 $sql .=
" AND f.fk_statut = ".self::STATUS_DRAFT;
4754 if (is_object($excluser)) {
4755 $sql .=
" AND f.fk_user_author <> ".((int) $excluser->id);
4757 $sql .= $this->db->order($sortfield, $sortorder);
4758 $sql .= $this->db->plimit($limit, $offset);
4760 $result = $this->db->query($sql);
4762 $numc = $this->db->num_rows($result);
4765 while ($i < $numc) {
4766 $obj = $this->db->fetch_object($result);
4768 if ($shortlist == 1) {
4769 $ga[$obj->fid] = $obj->ref;
4770 } elseif ($shortlist == 2) {
4771 $ga[$obj->fid] = $obj->ref.
' ('.$obj->name.
')';
4773 $ga[$i][
'id'] = $obj->fid;
4774 $ga[$i][
'ref'] = $obj->ref;
4775 $ga[$i][
'name'] = $obj->name;
4804 $sql =
"SELECT f.rowid as rowid, f.ref, f.fk_statut as status, f.paye as paid,";
4805 $sql .=
" ff.rowid as rowidnext";
4807 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4808 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"paiement_facture as pf ON f.rowid = pf.fk_facture";
4809 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facture as ff ON f.rowid = ff.fk_facture_source";
4810 $sql .=
" WHERE (f.fk_statut = ".self::STATUS_VALIDATED.
" OR (f.fk_statut = ".self::STATUS_ABANDONED.
" AND f.close_code = '".self::CLOSECODE_ABANDONED.
"'))";
4811 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4812 $sql .=
" AND f.paye = 0";
4813 $sql .=
" AND pf.fk_paiement IS NULL";
4814 $sql .=
" AND ff.fk_statut IS NULL";
4816 $sql .=
" AND f.fk_soc = ".((int) $socid);
4819 $sql .=
" ORDER BY f.ref";
4821 dol_syslog(get_class($this).
"::list_replacable_invoices", LOG_DEBUG);
4822 $resql = $this->db->query($sql);
4824 while ($obj = $this->db->fetch_object($resql)) {
4825 $return[$obj->rowid] = array(
4826 'id' => $obj->rowid,
4828 'status' => $obj->status,
4829 'paid' => $obj->paid,
4836 $this->error = $this->db->error();
4859 $sql =
"SELECT f.rowid as rowid, f.ref, f.fk_statut, f.type, f.subtype, f.paye, pf.fk_paiement";
4860 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4861 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"paiement_facture as pf ON f.rowid = pf.fk_facture";
4862 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facture as ff ON (f.rowid = ff.fk_facture_source AND ff.type=".self::TYPE_REPLACEMENT.
")";
4863 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice').
")";
4864 $sql .=
" AND f.fk_statut in (".self::STATUS_VALIDATED.
",".self::STATUS_CLOSED.
")";
4868 $sql .=
" AND ff.type IS NULL";
4869 $sql .=
" AND f.type <> ".self::TYPE_CREDIT_NOTE;
4873 $sql .=
" AND (f.type <> ".self::TYPE_SITUATION.
" OR f.rowid IN ";
4874 $sql .=
'(SELECT MAX(fs.rowid)';
4875 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as fs";
4876 $sql .=
" WHERE fs.entity IN (".getEntity(
'invoice').
")";
4877 $sql .=
" AND fs.type = ".self::TYPE_SITUATION;
4878 $sql .=
" AND fs.fk_statut IN (".self::STATUS_VALIDATED.
",".self::STATUS_CLOSED.
")";
4880 $sql .=
" AND fs.fk_soc = ".((int) $socid);
4882 $sql .=
" GROUP BY fs.situation_cycle_ref)";
4885 $sql .=
" AND f.type <> ".self::TYPE_SITUATION;
4889 $sql .=
" AND f.fk_soc = ".((int) $socid);
4891 $sql .=
" ORDER BY f.ref";
4893 dol_syslog(get_class($this).
"::list_qualified_avoir_invoices", LOG_DEBUG);
4894 $resql = $this->db->query($sql);
4896 while ($obj = $this->db->fetch_object($resql)) {
4898 if ($obj->fk_statut == self::STATUS_VALIDATED) {
4901 if ($obj->fk_statut == self::STATUS_CLOSED) {
4906 $paymentornot = ($obj->fk_paiement ? 1 : 0);
4907 $return[$obj->rowid] = array(
'ref'=>$obj->ref,
'status'=>$obj->fk_statut,
'type'=>$obj->type,
'paye'=>$obj->paye,
'paymentornot'=>$paymentornot);
4913 $this->error = $this->db->error();
4929 global $conf, $langs;
4933 $sql =
"SELECT f.rowid, f.date_lim_reglement as datefin, f.fk_statut as status, f.total_ht";
4934 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4935 if (!$user->hasRight(
'societe',
'client',
'voir') && !$user->socid) {
4936 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON f.fk_soc = sc.fk_soc";
4937 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
4940 $sql .= $clause.
" f.paye=0";
4941 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4942 $sql .=
" AND f.fk_statut = ".self::STATUS_VALIDATED;
4944 $sql .=
" AND f.fk_soc = ".((int) $user->socid);
4947 $resql = $this->db->query($sql);
4949 $langs->load(
"bills");
4953 $response->warning_delay = $conf->facture->client->warning_delay / 60 / 60 / 24;
4954 $response->label = $langs->trans(
"CustomerBillsUnpaid");
4955 $response->labelShort = $langs->trans(
"Unpaid");
4956 $response->url = DOL_URL_ROOT.
'/compta/facture/list.php?search_status=1&mainmenu=billing&leftmenu=customers_bills';
4959 $generic_facture =
new Facture($this->db);
4961 while ($obj = $this->db->fetch_object($resql)) {
4962 $generic_facture->date_lim_reglement = $this->db->jdate($obj->datefin);
4963 $generic_facture->statut = $obj->status;
4964 $generic_facture->status = $obj->status;
4966 $response->nbtodo++;
4967 $response->total += $obj->total_ht;
4969 if ($generic_facture->hasDelay()) {
4970 $response->nbtodolate++;
4971 $response->url_late = DOL_URL_ROOT.
'/compta/facture/list.php?search_option=late&mainmenu=billing&leftmenu=customers_bills';
4975 $this->db->free($resql);
4979 $this->error = $this->db->error();
5018 global $conf, $langs, $user;
5022 $nownotime =
dol_mktime(0, 0, 0, $arraynow[
'mon'], $arraynow[
'mday'], $arraynow[
'year']);
5027 $sql =
"SELECT rowid";
5028 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
5029 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
5030 $sql .= $this->db->plimit(100);
5032 $resql = $this->db->query($sql);
5034 $num_prods = $this->db->num_rows($resql);
5036 while ($i < $num_prods) {
5038 $row = $this->db->fetch_row($resql);
5039 $prodids[$i] = $row[0];
5043 if (empty($num_prods)) {
5050 $this->
ref =
'SPECIMEN';
5051 $this->specimen = 1;
5053 $this->date = $nownotime;
5054 $this->date_lim_reglement = $nownotime + 3600 * 24 * 30;
5055 $this->cond_reglement_id = 1;
5056 $this->cond_reglement_code =
'RECEP';
5058 $this->mode_reglement_id = 0;
5059 $this->mode_reglement_code =
'';
5061 $this->note_public =
'This is a comment (public)';
5062 $this->note_private =
'This is a comment (private)';
5063 $this->note =
'This is a comment (private)';
5065 $this->fk_user_author = $user->id;
5067 $this->multicurrency_tx = 1;
5068 $this->multicurrency_code = $conf->currency;
5070 $this->fk_incoterms = 0;
5071 $this->location_incoterms =
'';
5073 if (empty($option) || $option !=
'nolines') {
5077 while ($xnbp < $nbp) {
5079 $line->desc = $langs->trans(
"Description").
" ".$xnbp;
5081 $line->subprice = 100;
5082 $line->tva_tx = 19.6;
5083 $line->localtax1_tx = 0;
5084 $line->localtax2_tx = 0;
5085 $line->remise_percent = 0;
5087 $prodid = mt_rand(1, $num_prods);
5088 $line->fk_product = $prodids[$prodid];
5090 $line->total_ht = -100;
5091 $line->total_ttc = -119.6;
5092 $line->total_tva = -19.6;
5093 $line->multicurrency_total_ht = -200;
5094 $line->multicurrency_total_ttc = -239.2;
5095 $line->multicurrency_total_tva = -39.2;
5096 } elseif ($xnbp == 2) {
5097 $line->subprice = -100;
5098 $line->total_ht = -100;
5099 $line->total_ttc = -119.6;
5100 $line->total_tva = -19.6;
5101 $line->remise_percent = 0;
5102 $line->multicurrency_total_ht = -200;
5103 $line->multicurrency_total_ttc = -239.2;
5104 $line->multicurrency_total_tva = -39.2;
5105 } elseif ($xnbp == 3) {
5106 $prodid = mt_rand(1, $num_prods);
5107 $line->fk_product = $prodids[$prodid];
5108 $line->total_ht = 50;
5109 $line->total_ttc = 59.8;
5110 $line->total_tva = 9.8;
5111 $line->multicurrency_total_ht = 100;
5112 $line->multicurrency_total_ttc = 119.6;
5113 $line->multicurrency_total_tva = 19.6;
5114 $line->remise_percent = 50;
5116 $prodid = mt_rand(1, $num_prods);
5117 $line->fk_product = $prodids[$prodid];
5118 $line->total_ht = 100;
5119 $line->total_ttc = 119.6;
5120 $line->total_tva = 19.6;
5121 $line->multicurrency_total_ht = 200;
5122 $line->multicurrency_total_ttc = 239.2;
5123 $line->multicurrency_total_tva = 39.2;
5124 $line->remise_percent = 0;
5127 $this->lines[$xnbp] = $line;
5130 $this->total_ht += $line->total_ht;
5131 $this->total_tva += $line->total_tva;
5132 $this->total_ttc += $line->total_ttc;
5134 $this->multicurrency_total_ht += $line->multicurrency_total_ht;
5135 $this->multicurrency_total_tva += $line->multicurrency_total_tva;
5136 $this->multicurrency_total_ttc += $line->multicurrency_total_ttc;
5140 $this->revenuestamp = 0;
5144 $line->desc = $langs->trans(
"Description").
" (offered line)";
5146 $line->subprice = 100;
5147 $line->tva_tx = 19.6;
5148 $line->localtax1_tx = 0;
5149 $line->localtax2_tx = 0;
5150 $line->remise_percent = 100;
5151 $line->total_ht = 0;
5152 $line->total_ttc = 0;
5153 $line->total_tva = 0;
5154 $line->multicurrency_total_ht = 0;
5155 $line->multicurrency_total_ttc = 0;
5156 $line->multicurrency_total_tva = 0;
5157 $prodid = mt_rand(1, $num_prods);
5158 $line->fk_product = $prodids[$prodid];
5160 $this->lines[$xnbp] = $line;
5174 global $conf, $user;
5176 $this->nb = array();
5180 $sql =
"SELECT count(f.rowid) as nb";
5181 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
5182 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON f.fk_soc = s.rowid";
5183 if (!$user->hasRight(
'societe',
'client',
'voir') && !$user->socid) {
5184 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON s.rowid = sc.fk_soc";
5185 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
5188 $sql .=
" ".$clause.
" f.entity IN (".
getEntity(
'invoice').
")";
5190 $resql = $this->db->query($sql);
5192 while ($obj = $this->db->fetch_object($resql)) {
5193 $this->nb[
"invoices"] = $obj->nb;
5195 $this->db->free($resql);
5199 $this->error = $this->db->error();
5225 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
5227 global $conf, $langs;
5229 $outputlangs->loadLangs(array(
"bills",
"products"));
5233 $thisTypeConfName =
'FACTURE_ADDON_PDF_'.$this->type;
5235 if (!empty($this->model_pdf)) {
5236 $modele = $this->model_pdf;
5240 $modele = $conf->global->FACTURE_ADDON_PDF;
5244 $modelpath =
"core/modules/facture/doc/";
5246 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
5256 $sql =
'SELECT max(situation_cycle_ref) FROM '.MAIN_DB_PREFIX.
'facture as f';
5257 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice', 0).
")";
5258 $resql = $this->db->query($sql);
5260 if ($this->db->num_rows($resql) > 0) {
5261 $res = $this->db->fetch_array($resql);
5262 $ref = $res[
'max(situation_cycle_ref)'];
5267 $this->db->free($resql);
5270 $this->error = $this->db->lasterror();
5271 dol_syslog(
"Error sql=".$sql.
", error=".$this->error, LOG_ERR);
5285 return ($this->situation_counter == 1);
5299 $sql =
'SELECT rowid FROM '.MAIN_DB_PREFIX.
'facture';
5300 $sql .=
' WHERE situation_cycle_ref = '.((int) $this->situation_cycle_ref);
5301 $sql .=
' AND situation_counter < '.((int) $this->situation_counter);
5302 $sql .=
' AND entity = '.($this->entity > 0 ? $this->entity : $conf->entity);
5303 $resql = $this->db->query($sql);
5305 if ($resql && $this->db->num_rows($resql) > 0) {
5306 while ($row = $this->db->fetch_object($resql)) {
5308 $situation =
new Facture($this->db);
5309 $situation->fetch($id);
5310 $res[] = $situation;
5313 $this->error = $this->db->error();
5314 dol_syslog(
"Error sql=".$sql.
", error=".$this->error, LOG_ERR);
5334 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET situation_final = '.((int) $this->situation_final).
' WHERE rowid = '.((int) $this->
id);
5337 $resql = $this->db->query($sql);
5339 $this->errors[] = $this->db->error();
5343 if (!$notrigger && empty($error)) {
5353 $this->db->commit();
5356 foreach ($this->errors as $errmsg) {
5357 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
5358 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
5360 $this->db->rollback();
5376 if (!empty($this->situation_cycle_ref)) {
5378 $sql =
'SELECT max(situation_counter) FROM '.MAIN_DB_PREFIX.
'facture';
5379 $sql .=
' WHERE situation_cycle_ref = '.((int) $this->situation_cycle_ref);
5380 $sql .=
' AND entity = '.($this->entity > 0 ? $this->entity : $conf->entity);
5381 $resql = $this->db->query($sql);
5383 if ($resql && $this->db->num_rows($resql) > 0) {
5384 $res = $this->db->fetch_array($resql);
5385 $last = $res[
'max(situation_counter)'];
5386 return ($last == $this->situation_counter);
5388 $this->error = $this->db->lasterror();
5389 dol_syslog(get_class($this).
"::select Error ".$this->error, LOG_ERR);
5447 $hasDelay = $this->date_lim_reglement < ($now - $conf->facture->client->warning_delay);
5448 if ($hasDelay && !empty($this->retained_warranty) && !empty($this->retained_warranty_date_limit)) {
5450 $totalpaid = (float) $totalpaid;
5452 if ($totalpaid >= 0 && $RetainedWarrantyAmount >= 0) {
5453 if (($totalpaid < $this->total_ttc - $RetainedWarrantyAmount) && $this->date_lim_reglement < ($now - $conf->facture->client->warning_delay)) {
5455 } elseif ($totalpaid < $this->total_ttc && $this->retained_warranty_date_limit < ($now - $conf->facture->client->warning_delay)) {
5478 $displayWarranty =
false;
5479 if (!empty($this->retained_warranty)) {
5480 $displayWarranty =
true;
5484 $displayWarranty =
false;
5485 if (!empty($this->situation_final)) {
5486 $displayWarranty =
true;
5489 $displayWarranty =
true;
5491 foreach ($this->lines as $i => $line) {
5492 if ($line->product_type < 2 && $line->situation_percent < 100) {
5493 $displayWarranty =
false;
5501 return $displayWarranty;
5511 if (empty($this->retained_warranty)) {
5515 $retainedWarrantyAmount = 0;
5519 $displayWarranty =
true;
5521 if (!empty($this->lines)) {
5522 foreach ($this->lines as $i => $line) {
5523 if ($line->product_type < 2 && $line->situation_percent < 100) {
5524 $displayWarranty =
false;
5530 if ($displayWarranty && !empty($this->situation_final)) {
5532 $TPreviousIncoice = $this->tab_previous_situation_invoice;
5535 foreach ($TPreviousIncoice as &$fac) {
5536 $total2BillWT += $fac->total_ttc;
5538 $total2BillWT += $this->total_ttc;
5540 $retainedWarrantyAmount = $total2BillWT * $this->retained_warranty / 100;
5546 $retainedWarrantyAmount = $this->total_ttc * $this->retained_warranty / 100;
5549 if ($rounding < 0) {
5553 if ($rounding > 0) {
5554 return round($retainedWarrantyAmount, $rounding);
5557 return $retainedWarrantyAmount;
5568 dol_syslog(get_class($this).
'::setRetainedWarranty('.$value.
')');
5570 if ($this->
status >= 0) {
5571 $fieldname =
'retained_warranty';
5572 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
5573 $sql .=
" SET ".$fieldname.
" = ".((float) $value);
5574 $sql .=
' WHERE rowid='.((int) $this->
id);
5576 if ($this->db->query($sql)) {
5577 $this->retained_warranty = (float) $value;
5580 dol_syslog(get_class($this).
'::setRetainedWarranty Erreur '.$sql.
' - '.$this->db->error());
5581 $this->error = $this->db->error();
5585 dol_syslog(get_class($this).
'::setRetainedWarranty, status of the object is incompatible');
5586 $this->error =
'Status of the object is incompatible '.$this->status;
5601 if (!$timestamp && $dateYmd) {
5602 $timestamp = $this->db->jdate($dateYmd);
5606 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit('.$timestamp.
')');
5607 if ($this->
status >= 0) {
5608 $fieldname =
'retained_warranty_date_limit';
5609 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
5610 $sql .=
" SET ".$fieldname.
" = ".(strval($timestamp) !=
'' ?
"'".$this->db->idate($timestamp).
"'" :
'null');
5611 $sql .=
' WHERE rowid = '.((int) $this->
id);
5613 if ($this->db->query($sql)) {
5614 $this->retained_warranty_date_limit = $timestamp;
5617 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit Erreur '.$sql.
' - '.$this->db->error());
5618 $this->error = $this->db->error();
5622 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit, status of the object is incompatible');
5623 $this->error =
'Status of the object is incompatible '.$this->status;
5642 global $conf, $langs, $user;
5648 $errorsMsg = array();
5650 $langs->load(
"bills");
5652 if (!isModEnabled(
'facture')) {
5653 $this->output .= $langs->trans(
'ModuleNotEnabled', $langs->transnoentitiesnoconv(
"Facture"));
5656 if (!in_array($datetouse, array(
'duedate',
'invoicedate'))) {
5657 $this->output .=
'Bad value for parameter datetouse. Must be "duedate" or "invoicedate"';
5667 require_once DOL_DOCUMENT_ROOT.
'/core/lib/date.lib.php';
5668 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmail.class.php';
5669 require_once DOL_DOCUMENT_ROOT.
'/core/class/CMailFile.class.php';
5670 $formmail =
new FormMail($this->db);
5675 $tmpinvoice =
new Facture($this->db);
5680 $sql =
"SELECT rowid as id FROM ".MAIN_DB_PREFIX.
"facture as f";
5681 if (!empty($paymentmode) && $paymentmode !=
'all') {
5682 $sql .=
", ".MAIN_DB_PREFIX.
"c_paiement as cp";
5684 $sql .=
" WHERE f.paye = 0";
5685 $sql .=
" AND f.fk_statut = ".self::STATUS_VALIDATED;
5686 if ($datetouse ==
'invoicedate') {
5687 $sql .=
" AND f.datef = '".$this->db->idate($tmpidate,
'gmt').
"'";
5689 $sql .=
" AND f.date_lim_reglement = '".$this->db->idate($tmpidate,
'gmt').
"'";
5691 $sql .=
" AND f.entity IN (".getEntity(
'facture', 0).
")";
5692 if (!empty($paymentmode) && $paymentmode !=
'all') {
5693 $sql .=
" AND f.fk_mode_reglement = cp.id AND cp.code = '".$this->db->escape($paymentmode).
"'";
5696 if ($datetouse ==
'invoicedate') {
5697 $sql .= $this->db->order(
"datef",
"ASC");
5699 $sql .= $this->db->order(
"date_lim_reglement",
"ASC");
5702 $resql = $this->db->query($sql);
5705 if ($datetouse ==
'invoicedate') {
5706 $this->output .= $langs->transnoentitiesnoconv(
"SearchValidatedInvoicesWithDate", $stmpidate);
5708 $this->output .= $langs->transnoentitiesnoconv(
"SearchUnpaidInvoicesWithDueDate", $stmpidate);
5710 if (!empty($paymentmode) && $paymentmode !=
'all') {
5711 $this->output .=
' ('.$langs->transnoentitiesnoconv(
"PaymentMode").
' '.$paymentmode.
')';
5713 $this->output .=
'<br>';
5716 while ($obj = $this->db->fetch_object($resql)) {
5719 $res = $tmpinvoice->fetch($obj->id);
5721 $tmpinvoice->fetch_thirdparty();
5723 $outputlangs =
new Translate(
'', $conf);
5724 if ($tmpinvoice->thirdparty->default_lang) {
5725 $outputlangs->setDefaultLang($tmpinvoice->thirdparty->default_lang);
5726 $outputlangs->loadLangs(array(
"main",
"bills"));
5728 $outputlangs = $langs;
5732 $arraymessage = $formmail->getEMailTemplate($this->db,
'facture_send', $user, $outputlangs, (is_numeric($template) ? $template : 0), 1, (is_numeric($template) ?
'' : $template));
5733 if (is_numeric($arraymessage) && $arraymessage <= 0) {
5734 $langs->load(
"errors");
5735 $this->output .= $langs->trans(
'ErrorFailedToFindEmailTemplate', $template);
5748 $sendTopic =
make_substitutions(empty($arraymessage->topic) ? $outputlangs->transnoentitiesnoconv(
'InformationMessage') : $arraymessage->topic, $substitutionarray, $outputlangs, 1);
5751 $content = $outputlangs->transnoentitiesnoconv($arraymessage->content);
5757 if ($forcerecipient) {
5758 $to = array($forcerecipient);
5760 $res = $tmpinvoice->fetch_thirdparty();
5761 $recipient = $tmpinvoice->thirdparty;
5763 $tmparraycontact = $tmpinvoice->liste_contact(-1,
'external', 0,
'BILLING');
5764 if (is_array($tmparraycontact) && count($tmparraycontact) > 0) {
5765 foreach ($tmparraycontact as $data_email) {
5766 if (!empty($data_email[
'email'])) {
5767 $to[] = $tmpinvoice->thirdparty->contact_get_property($data_email[
'id'],
'email');
5771 if (empty($to) && !empty($recipient->email)) {
5772 $to[] = $recipient->email;
5775 $errormesg =
"Failed to send remind to thirdparty id=".$tmpinvoice->socid.
". No email defined for invoice or customer.";
5779 $errormesg =
"Failed to load recipient with thirdparty id=".$tmpinvoice->socid;
5786 if (!empty($arraymessage->email_from)) {
5787 $from = $arraymessage->email_from;
5790 $errormesg =
"Failed to get sender into global setup MAIN_MAIL_EMAIL_FROM";
5794 if (!$error && !empty($to)) {
5797 $to = implode(
',', $to);
5798 if (!empty($arraymessage->email_to)) {
5799 $to = $to.
','.$arraymessage->email_to;
5803 $errors_to = $conf->global->MAIN_MAIL_ERRORS_TO;
5805 $trackid =
'inv'.$tmpinvoice->id;
5806 $sendcontext =
'standard';
5809 if (!empty($arraymessage->email_tocc)) {
5810 $email_tocc = $arraymessage->email_tocc;
5814 if (!empty($arraymessage->email_tobcc)) {
5815 $email_tobcc = $arraymessage->email_tobcc;
5822 if ($arraymessage->joinfiles == 1 && !empty($tmpinvoice->last_main_doc)) {
5823 $joinFile[] = DOL_DATA_ROOT.
'/'.$tmpinvoice->last_main_doc;
5824 $joinFileName[] = basename($tmpinvoice->last_main_doc);
5825 $joinFileMime[] =
dol_mimetype(DOL_DATA_ROOT.
'/'.$tmpinvoice->last_main_doc);
5829 $cMailFile =
new CMailFile($sendTopic, $to, $from, $sendContent, $joinFile, $joinFileMime, $joinFileName, $email_tocc, $email_tobcc, 0, 1, $errors_to,
'', $trackid,
'', $sendcontext,
'');
5832 if ($cMailFile->sendfile()) {
5836 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
5841 $actioncomm->type_code =
'AC_OTH_AUTO';
5842 $actioncomm->socid = $tmpinvoice->thirdparty->id;
5843 $actioncomm->contact_id = 0;
5845 $actioncomm->code =
'AC_EMAIL';
5846 $actioncomm->label =
'sendEmailsRemindersOnInvoiceDueDateOK (nbdays='.$nbdays.
' paymentmode='.$paymentmode.
' template='.$template.
' datetouse='.$datetouse.
' forcerecipient='.$forcerecipient.
')';
5847 $actioncomm->note_private = $sendContent;
5848 $actioncomm->fk_project = $tmpinvoice->fk_project;
5849 $actioncomm->datep =
dol_now();
5850 $actioncomm->datef = $actioncomm->datep;
5851 $actioncomm->percentage = -1;
5852 $actioncomm->authorid = $user->id;
5853 $actioncomm->userownerid = $user->id;
5855 $actioncomm->email_msgid = $cMailFile->msgid;
5856 $actioncomm->email_subject = $sendTopic;
5857 $actioncomm->email_from = $from;
5858 $actioncomm->email_sender =
'';
5859 $actioncomm->email_to = $to;
5863 $actioncomm->errors_to = $errors_to;
5865 $actioncomm->elementtype =
'invoice';
5866 $actioncomm->fk_element = $tmpinvoice->id;
5870 $actioncomm->create($user);
5872 $errormesg = $cMailFile->error.
' : '.$to;
5876 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
5881 $actioncomm->type_code =
'AC_OTH_AUTO';
5882 $actioncomm->socid = $tmpinvoice->thirdparty->id;
5883 $actioncomm->contact_id = 0;
5885 $actioncomm->code =
'AC_EMAIL';
5886 $actioncomm->label =
'sendEmailsRemindersOnInvoiceDueDateKO';
5887 $actioncomm->note_private = $errormesg;
5888 $actioncomm->fk_project = $tmpinvoice->fk_project;
5889 $actioncomm->datep =
dol_now();
5890 $actioncomm->datef = $actioncomm->datep;
5891 $actioncomm->percentage = -1;
5892 $actioncomm->authorid = $user->id;
5893 $actioncomm->userownerid = $user->id;
5895 $actioncomm->email_msgid = $cMailFile->msgid;
5896 $actioncomm->email_from = $from;
5897 $actioncomm->email_sender =
'';
5898 $actioncomm->email_to = $to;
5902 $actioncomm->errors_to = $errors_to;
5906 $actioncomm->create($user);
5909 $this->db->commit();
5913 $errorsMsg[] = $errormesg;
5916 $errorsMsg[] =
'Failed to fetch record invoice with ID = '.$obj->id;
5926 $this->output .=
'Nb of emails sent : '.$nbMailSend;
5928 dol_syslog(__METHOD__.
" end - ".$this->output, LOG_INFO);
5932 $this->error =
'Nb of emails sent : '.$nbMailSend.
', '.(!empty($errorsMsg)) ? join(
', ', $errorsMsg) : $error;
5934 dol_syslog(__METHOD__.
" end - ".$this->error, LOG_INFO);
5949 $sql =
"SELECT datef";
5950 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture";
5951 $sql .=
" WHERE type = " . (int) $this->
type ;
5952 $sql .=
" AND date_valid IS NOT NULL";
5953 $sql .=
" AND entity IN (".getEntity(
'invoice').
")";
5954 $sql .=
" ORDER BY datef DESC LIMIT 1";
5956 $result = $this->db->query($sql);
5959 if ($this->db->num_rows($result)) {
5960 $obj = $this->db->fetch_object($result);
5961 $last_date = $this->db->jdate($obj->datef);
5962 $invoice_date = $this->date;
5964 $is_last_of_same_type = $invoice_date >= $last_date;
5965 if ($allow_validated_drafts) {
5969 return array($is_last_of_same_type, $last_date);
5992 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
5994 $return =
'<div class="box-flex-item box-flex-grow-zero">';
5995 $return .=
'<div class="info-box info-box-sm">';
5996 $return .=
'<span class="info-box-icon bg-infobox-action">';
5998 $return .=
'</span>';
5999 $return .=
'<div class="info-box-content">';
6000 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl(1) : $this->ref).
'</span>';
6001 if ($selected >= 0) {
6002 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
6004 if (!empty($arraydata[
'thirdparty'])) {
6005 $return .=
'<br><span class="info-box-label">'.$arraydata[
'thirdparty'].
'</span>';
6007 if (property_exists($this,
'date')) {
6008 $return .=
'<br><span class="info-box-label">'.dol_print_date($this->date,
'day').
'</span>';
6010 if (property_exists($this,
'total_ht')) {
6011 $return .=
' <span class="info-box-label amount" title="'.dol_escape_htmltag($langs->trans(
"AmountHT")).
'">'.
price($this->total_ht);
6012 $return .=
' '.$langs->trans(
"HT");
6013 $return .=
'</span>';
6015 if (method_exists($this,
'getLibStatut')) {
6016 $alreadypaid = (empty($arraydata[
'alreadypaid']) ? 0 : $arraydata[
'alreadypaid']);
6017 $return .=
'<br><div class="info-box-status">'.$this->getLibStatut(3, $alreadypaid).
'</div>';
6019 $return .=
'</div>';
6020 $return .=
'</div>';
6021 $return .=
'</div>';
6035 public $element =
'facturedet';
6040 public $table_element =
'facturedet';
6057 public $localtax1_type;
6058 public $localtax2_type;
6059 public $fk_remise_except;
6062 public $fk_fournprice;
6072 public $remise_percent;
6090 public $fk_warehouse;
6099 public $fk_code_ventilation = 0;
6105 public $skip_update_total;
6110 public $situation_percent;
6135 $sql =
'SELECT fd.rowid, fd.fk_facture, fd.fk_parent_line, fd.fk_product, fd.product_type, fd.label as custom_label, fd.description, fd.price, fd.qty, fd.vat_src_code, fd.tva_tx,';
6136 $sql .=
' fd.localtax1_tx, fd. localtax2_tx, fd.remise, fd.remise_percent, fd.fk_remise_except, fd.subprice, fd.ref_ext,';
6137 $sql .=
' fd.date_start as date_start, fd.date_end as date_end, fd.fk_product_fournisseur_price as fk_fournprice, fd.buy_price_ht as pa_ht,';
6138 $sql .=
' fd.info_bits, fd.special_code, fd.total_ht, fd.total_tva, fd.total_ttc, fd.total_localtax1, fd.total_localtax2, fd.rang,';
6139 $sql .=
' fd.fk_code_ventilation,';
6140 $sql .=
' fd.fk_unit, fd.fk_user_author, fd.fk_user_modif,';
6141 $sql .=
' fd.situation_percent, fd.fk_prev_id,';
6142 $sql .=
' fd.multicurrency_subprice,';
6143 $sql .=
' fd.multicurrency_total_ht,';
6144 $sql .=
' fd.multicurrency_total_tva,';
6145 $sql .=
' fd.multicurrency_total_ttc,';
6146 $sql .=
' p.ref as product_ref, p.label as product_label, p.description as product_desc';
6147 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facturedet as fd';
6148 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON fd.fk_product = p.rowid';
6149 $sql .=
' WHERE fd.rowid = '.((int) $rowid);
6151 $result = $this->db->query($sql);
6153 $objp = $this->db->fetch_object($result);
6156 $this->error =
'InvoiceLine with id '. $rowid .
' not found sql='.$sql;
6160 $this->
rowid = $objp->rowid;
6161 $this->
id = $objp->rowid;
6162 $this->fk_facture = $objp->fk_facture;
6163 $this->fk_parent_line = $objp->fk_parent_line;
6164 $this->label = $objp->custom_label;
6165 $this->desc = $objp->description;
6166 $this->qty = $objp->qty;
6167 $this->subprice = $objp->subprice;
6168 $this->ref_ext = $objp->ref_ext;
6169 $this->vat_src_code = $objp->vat_src_code;
6170 $this->tva_tx = $objp->tva_tx;
6171 $this->localtax1_tx = $objp->localtax1_tx;
6172 $this->localtax2_tx = $objp->localtax2_tx;
6173 $this->remise_percent = $objp->remise_percent;
6174 $this->fk_remise_except = $objp->fk_remise_except;
6175 $this->fk_product = $objp->fk_product;
6176 $this->product_type = $objp->product_type;
6177 $this->date_start = $this->db->jdate($objp->date_start);
6178 $this->date_end = $this->db->jdate($objp->date_end);
6179 $this->info_bits = $objp->info_bits;
6180 $this->tva_npr = ($objp->info_bits & 1 == 1) ? 1 : 0;
6181 $this->special_code = $objp->special_code;
6182 $this->total_ht = $objp->total_ht;
6183 $this->total_tva = $objp->total_tva;
6184 $this->total_localtax1 = $objp->total_localtax1;
6185 $this->total_localtax2 = $objp->total_localtax2;
6186 $this->total_ttc = $objp->total_ttc;
6187 $this->fk_code_ventilation = $objp->fk_code_ventilation;
6188 $this->rang = $objp->rang;
6189 $this->fk_fournprice = $objp->fk_fournprice;
6190 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $this->fk_fournprice, $objp->pa_ht);
6191 $this->pa_ht = $marginInfos[0];
6192 $this->marge_tx = $marginInfos[1];
6193 $this->marque_tx = $marginInfos[2];
6195 $this->
ref = $objp->product_ref;
6197 $this->product_ref = $objp->product_ref;
6198 $this->product_label = $objp->product_label;
6199 $this->product_desc = $objp->product_desc;
6201 $this->fk_unit = $objp->fk_unit;
6202 $this->fk_user_modif = $objp->fk_user_modif;
6203 $this->fk_user_author = $objp->fk_user_author;
6205 $this->situation_percent = $objp->situation_percent;
6206 $this->fk_prev_id = $objp->fk_prev_id;
6208 $this->multicurrency_subprice = $objp->multicurrency_subprice;
6209 $this->multicurrency_total_ht = $objp->multicurrency_total_ht;
6210 $this->multicurrency_total_tva = $objp->multicurrency_total_tva;
6211 $this->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
6215 $this->db->free($result);
6219 $this->error = $this->db->lasterror();
6231 public function insert($notrigger = 0, $noerrorifdiscountalreadylinked = 0)
6233 global $langs, $user, $conf;
6237 $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht ==
'');
6239 dol_syslog(get_class($this).
"::insert rang=".$this->rang, LOG_DEBUG);
6242 $this->desc = trim($this->desc);
6243 if (empty($this->tva_tx)) {
6246 if (empty($this->localtax1_tx)) {
6247 $this->localtax1_tx = 0;
6249 if (empty($this->localtax2_tx)) {
6250 $this->localtax2_tx = 0;
6252 if (empty($this->localtax1_type)) {
6253 $this->localtax1_type = 0;
6255 if (empty($this->localtax2_type)) {
6256 $this->localtax2_type = 0;
6258 if (empty($this->total_localtax1)) {
6259 $this->total_localtax1 = 0;
6261 if (empty($this->total_localtax2)) {
6262 $this->total_localtax2 = 0;
6264 if (empty($this->rang)) {
6267 if (empty($this->remise_percent)) {
6268 $this->remise_percent = 0;
6270 if (empty($this->info_bits)) {
6271 $this->info_bits = 0;
6273 if (empty($this->subprice)) {
6274 $this->subprice = 0;
6276 if (empty($this->ref_ext)) {
6277 $this->ref_ext =
'';
6279 if (empty($this->special_code)) {
6280 $this->special_code = 0;
6282 if (empty($this->fk_parent_line)) {
6283 $this->fk_parent_line = 0;
6285 if (empty($this->fk_prev_id)) {
6286 $this->fk_prev_id = 0;
6288 if (!isset($this->situation_percent) || $this->situation_percent > 100 || (
string) $this->situation_percent ==
'') {
6289 $this->situation_percent = 100;
6292 if (empty($this->pa_ht)) {
6295 if (empty($this->multicurrency_subprice)) {
6296 $this->multicurrency_subprice = 0;
6298 if (empty($this->multicurrency_total_ht)) {
6299 $this->multicurrency_total_ht = 0;
6301 if (empty($this->multicurrency_total_tva)) {
6302 $this->multicurrency_total_tva = 0;
6304 if (empty($this->multicurrency_total_ttc)) {
6305 $this->multicurrency_total_ttc = 0;
6309 if ($this->pa_ht == 0 && $pa_ht_isemptystring) {
6310 if (($result = $this->
defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0) {
6313 $this->pa_ht = $result;
6318 if ($this->product_type < 0) {
6319 $this->error =
'ErrorProductTypeMustBe0orMore';
6322 if (!empty($this->fk_product) && $this->fk_product > 0) {
6326 $this->error =
'ErrorProductIdDoesNotExists';
6327 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6335 $sql =
'INSERT INTO '.MAIN_DB_PREFIX.
'facturedet';
6336 $sql .=
' (fk_facture, fk_parent_line, label, description, qty,';
6337 $sql .=
' vat_src_code, tva_tx, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type,';
6338 $sql .=
' fk_product, product_type, remise_percent, subprice, ref_ext, fk_remise_except,';
6339 $sql .=
' date_start, date_end, fk_code_ventilation, ';
6340 $sql .=
' rang, special_code, fk_product_fournisseur_price, buy_price_ht,';
6341 $sql .=
' info_bits, total_ht, total_tva, total_ttc, total_localtax1, total_localtax2,';
6342 $sql .=
' situation_percent, fk_prev_id,';
6343 $sql .=
' fk_unit, fk_user_author, fk_user_modif,';
6344 $sql .=
' fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc';
6346 $sql .=
" VALUES (".$this->fk_facture.
",";
6347 $sql .=
" ".($this->fk_parent_line > 0 ? $this->fk_parent_line :
"null").
",";
6348 $sql .=
" ".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null").
",";
6349 $sql .=
" '".$this->db->escape($this->desc).
"',";
6350 $sql .=
" ".price2num($this->qty).
",";
6351 $sql .=
" ".(empty($this->vat_src_code) ?
"''" :
"'".$this->db->escape($this->vat_src_code).
"'").
",";
6352 $sql .=
" ".price2num($this->tva_tx).
",";
6353 $sql .=
" ".price2num($this->localtax1_tx).
",";
6354 $sql .=
" ".price2num($this->localtax2_tx).
",";
6355 $sql .=
" '".$this->db->escape($this->localtax1_type).
"',";
6356 $sql .=
" '".$this->db->escape($this->localtax2_type).
"',";
6357 $sql .=
' '.((!empty($this->fk_product) && $this->fk_product > 0) ? $this->fk_product :
"null").
',';
6358 $sql .=
" ".((int) $this->product_type).
",";
6359 $sql .=
" ".price2num($this->remise_percent).
",";
6360 $sql .=
" ".price2num($this->subprice).
",";
6361 $sql .=
" '".$this->db->escape($this->ref_ext).
"',";
6362 $sql .=
' '.(!empty($this->fk_remise_except) ? $this->fk_remise_except :
"null").
',';
6363 $sql .=
" ".(!empty($this->date_start) ?
"'".$this->db->idate($this->date_start).
"'" :
"null").
",";
6364 $sql .=
" ".(!empty($this->date_end) ?
"'".$this->db->idate($this->date_end).
"'" :
"null").
",";
6365 $sql .=
' '.((int) $this->fk_code_ventilation).
',';
6366 $sql .=
' '.((int) $this->rang).
',';
6367 $sql .=
' '.((int) $this->special_code).
',';
6368 $sql .=
' '.(!empty($this->fk_fournprice) ? $this->fk_fournprice :
"null").
',';
6369 $sql .=
' '.price2num($this->pa_ht).
',';
6370 $sql .=
" '".$this->db->escape($this->info_bits).
"',";
6371 $sql .=
" ".price2num($this->total_ht).
",";
6372 $sql .=
" ".price2num($this->total_tva).
",";
6373 $sql .=
" ".price2num($this->total_ttc).
",";
6374 $sql .=
" ".price2num($this->total_localtax1).
",";
6375 $sql .=
" ".price2num($this->total_localtax2);
6376 $sql .=
", ".((float) $this->situation_percent);
6377 $sql .=
", ".(!empty($this->fk_prev_id) ? $this->fk_prev_id :
"null");
6378 $sql .=
", ".(!$this->fk_unit ?
'NULL' : $this->fk_unit);
6379 $sql .=
", ".((int) $user->id);
6380 $sql .=
", ".((int) $user->id);
6381 $sql .=
", ".(int) $this->fk_multicurrency;
6382 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
6383 $sql .=
", ".price2num($this->multicurrency_subprice);
6384 $sql .=
", ".price2num($this->multicurrency_total_ht);
6385 $sql .=
", ".price2num($this->multicurrency_total_tva);
6386 $sql .=
", ".price2num($this->multicurrency_total_ttc);
6389 dol_syslog(get_class($this).
"::insert", LOG_DEBUG);
6390 $resql = $this->db->query($sql);
6392 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
'facturedet');
6393 $this->
rowid = $this->id;
6404 if ($this->fk_remise_except && empty($error)) {
6406 $result = $discount->fetch($this->fk_remise_except);
6411 if ($discount->fk_facture_line > 0) {
6412 if (empty($noerrorifdiscountalreadylinked)) {
6413 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed", $discount->id);
6414 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6415 $this->db->rollback();
6419 $result = $discount->link_to_invoice($this->
rowid, 0);
6421 $this->error = $discount->error;
6422 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6423 $this->db->rollback();
6428 $this->error = $langs->trans(
"ErrorADiscountThatHasBeenRemovedIsIncluded");
6429 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6430 $this->db->rollback();
6434 $this->error = $discount->error;
6435 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6436 $this->db->rollback();
6441 if (!$notrigger && empty($error)) {
6443 $result = $this->
call_trigger(
'LINEBILL_INSERT', $user);
6445 $this->db->rollback();
6452 $this->db->commit();
6456 foreach ($this->errors as $errmsg) {
6457 dol_syslog(get_class($this).
"::insert ".$errmsg, LOG_ERR);
6458 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
6460 $this->db->rollback();
6463 $this->error = $this->db->lasterror();
6464 $this->db->rollback();
6476 public function update($user =
null, $notrigger = 0)
6478 global $user, $conf;
6482 $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht ==
'');
6485 $this->desc = trim($this->desc);
6486 if (empty($this->ref_ext)) {
6487 $this->ref_ext =
'';
6489 if (empty($this->tva_tx)) {
6492 if (empty($this->localtax1_tx)) {
6493 $this->localtax1_tx = 0;
6495 if (empty($this->localtax2_tx)) {
6496 $this->localtax2_tx = 0;
6498 if (empty($this->localtax1_type)) {
6499 $this->localtax1_type = 0;
6501 if (empty($this->localtax2_type)) {
6502 $this->localtax2_type = 0;
6504 if (empty($this->total_localtax1)) {
6505 $this->total_localtax1 = 0;
6507 if (empty($this->total_localtax2)) {
6508 $this->total_localtax2 = 0;
6510 if (empty($this->remise_percent)) {
6511 $this->remise_percent = 0;
6513 if (empty($this->info_bits)) {
6514 $this->info_bits = 0;
6516 if (empty($this->special_code)) {
6517 $this->special_code = 0;
6519 if (empty($this->product_type)) {
6520 $this->product_type = 0;
6522 if (empty($this->fk_parent_line)) {
6523 $this->fk_parent_line = 0;
6525 if (!isset($this->situation_percent) || $this->situation_percent > 100 || (
string) $this->situation_percent ==
'') {
6526 $this->situation_percent = 100;
6528 if (empty($this->pa_ht)) {
6532 if (empty($this->multicurrency_subprice)) {
6533 $this->multicurrency_subprice = 0;
6535 if (empty($this->multicurrency_total_ht)) {
6536 $this->multicurrency_total_ht = 0;
6538 if (empty($this->multicurrency_total_tva)) {
6539 $this->multicurrency_total_tva = 0;
6541 if (empty($this->multicurrency_total_ttc)) {
6542 $this->multicurrency_total_ttc = 0;
6546 if ($this->product_type < 0) {
6551 if ($this->pa_ht == 0 && $pa_ht_isemptystring) {
6553 $result = $this->
defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product);
6557 $this->pa_ht = $result;
6564 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facturedet SET";
6565 $sql .=
" description='".$this->db->escape($this->desc).
"'";
6566 $sql .=
", ref_ext='".$this->db->escape($this->ref_ext).
"'";
6567 $sql .=
", label=".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null");
6568 $sql .=
", subprice=".price2num($this->subprice);
6569 $sql .=
", remise_percent=".price2num($this->remise_percent);
6570 if ($this->fk_remise_except) {
6571 $sql .=
", fk_remise_except=".$this->fk_remise_except;
6573 $sql .=
", fk_remise_except=null";
6575 $sql .=
", vat_src_code = '".(empty($this->vat_src_code) ?
'' : $this->db->escape($this->vat_src_code)).
"'";
6576 $sql .=
", tva_tx=".price2num($this->tva_tx);
6577 $sql .=
", localtax1_tx=".price2num($this->localtax1_tx);
6578 $sql .=
", localtax2_tx=".price2num($this->localtax2_tx);
6579 $sql .=
", localtax1_type='".$this->db->escape($this->localtax1_type).
"'";
6580 $sql .=
", localtax2_type='".$this->db->escape($this->localtax2_type).
"'";
6581 $sql .=
", qty=".price2num($this->qty);
6582 $sql .=
", date_start=".(!empty($this->date_start) ?
"'".$this->db->idate($this->date_start).
"'" :
"null");
6583 $sql .=
", date_end=".(!empty($this->date_end) ?
"'".$this->db->idate($this->date_end).
"'" :
"null");
6584 $sql .=
", product_type=".$this->product_type;
6585 $sql .=
", info_bits='".$this->db->escape($this->info_bits).
"'";
6586 $sql .=
", special_code='".$this->db->escape($this->special_code).
"'";
6587 if (empty($this->skip_update_total)) {
6588 $sql .=
", total_ht=".price2num($this->total_ht);
6589 $sql .=
", total_tva=".price2num($this->total_tva);
6590 $sql .=
", total_ttc=".price2num($this->total_ttc);
6591 $sql .=
", total_localtax1=".price2num($this->total_localtax1);
6592 $sql .=
", total_localtax2=".price2num($this->total_localtax2);
6594 $sql .=
", fk_product_fournisseur_price=".(!empty($this->fk_fournprice) ?
"'".$this->db->escape($this->fk_fournprice).
"'" :
"null");
6595 $sql .=
", buy_price_ht=".(($this->pa_ht || (string) $this->pa_ht ===
'0') ?
price2num($this->pa_ht) :
"null");
6596 $sql .=
", fk_parent_line=".($this->fk_parent_line > 0 ? $this->fk_parent_line :
"null");
6597 if (!empty($this->rang)) {
6598 $sql .=
", rang=".((int) $this->rang);
6600 $sql .=
", situation_percent = ".((float) $this->situation_percent);
6601 $sql .=
", fk_unit = ".(!$this->fk_unit ?
'NULL' : $this->fk_unit);
6602 $sql .=
", fk_user_modif = ".((int) $user->id);
6605 $sql .=
", multicurrency_subprice=".price2num($this->multicurrency_subprice);
6606 $sql .=
", multicurrency_total_ht=".price2num($this->multicurrency_total_ht);
6607 $sql .=
", multicurrency_total_tva=".price2num($this->multicurrency_total_tva);
6608 $sql .=
", multicurrency_total_ttc=".price2num($this->multicurrency_total_ttc);
6610 $sql .=
" WHERE rowid = ".((int) $this->
rowid);
6612 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
6613 $resql = $this->db->query($sql);
6616 $this->
id = $this->rowid;
6623 if (!$error && !$notrigger) {
6625 $result = $this->
call_trigger(
'LINEBILL_MODIFY', $user);
6627 $this->db->rollback();
6634 $this->db->commit();
6638 foreach ($this->errors as $errmsg) {
6639 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
6640 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
6642 $this->db->rollback();
6645 $this->error = $this->db->error();
6646 $this->db->rollback();
6658 public function delete($tmpuser =
null, $notrigger =
false)
6665 if (empty($notrigger)) {
6666 $result = $this->
call_trigger(
'LINEBILL_DELETE', $user);
6668 $this->db->rollback();
6677 $this->db->rollback();
6682 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
6683 $sql .=
' SET fk_facture_line = NULL';
6684 $sql .=
' WHERE fk_facture_line = '.((int) $this->
id);
6686 dol_syslog(get_class($this).
"::deleteline", LOG_DEBUG);
6687 $result = $this->db->query($sql);
6689 $this->error = $this->db->error();
6690 $this->errors[] = $this->error;
6691 $this->db->rollback();
6695 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'element_time';
6696 $sql .=
' SET invoice_id = NULL, invoice_line_id = NULL';
6697 $sql .=
' WHERE invoice_line_id = '.((int) $this->
id);
6698 if (!$this->db->query($sql)) {
6699 $this->error = $this->db->error().
" sql=".$sql;
6700 $this->errors[] = $this->error;
6701 $this->db->rollback();
6705 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"facturedet WHERE rowid = ".((int) $this->
id);
6707 if ($this->db->query($sql)) {
6708 $this->db->commit();
6711 $this->error = $this->db->error().
" sql=".$sql;
6712 $this->errors[] = $this->error;
6713 $this->db->rollback();
6729 dol_syslog(get_class($this).
"::update_total", LOG_DEBUG);
6732 if (empty($this->total_localtax1)) {
6733 $this->total_localtax1 = 0;
6735 if (empty($this->total_localtax2)) {
6736 $this->total_localtax2 = 0;
6740 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facturedet SET";
6741 $sql .=
" total_ht=".price2num($this->total_ht);
6742 $sql .=
",total_tva=".price2num($this->total_tva);
6743 $sql .=
",total_localtax1=".price2num($this->total_localtax1);
6744 $sql .=
",total_localtax2=".price2num($this->total_localtax2);
6745 $sql .=
",total_ttc=".price2num($this->total_ttc);
6746 $sql .=
" WHERE rowid = ".((int) $this->
rowid);
6748 dol_syslog(get_class($this).
"::update_total", LOG_DEBUG);
6750 $resql = $this->db->query($sql);
6752 $this->db->commit();
6755 $this->error = $this->db->error();
6756 $this->db->rollback();
6773 global $invoicecache;
6775 if (is_null($this->fk_prev_id) || empty($this->fk_prev_id) || $this->fk_prev_id ==
"") {
6779 if (!isset($invoicecache[$invoiceid])) {
6780 $invoicecache[$invoiceid] =
new Facture($this->db);
6781 $invoicecache[$invoiceid]->fetch($invoiceid);
6787 $sql =
"SELECT situation_percent FROM ".MAIN_DB_PREFIX.
"facturedet WHERE rowid = ".((int) $this->fk_prev_id);
6788 $resql = $this->db->query($sql);
6789 if ($resql && $this->db->num_rows($resql) > 0) {
6790 $res = $this->db->fetch_array($resql);
6792 $returnPercent = (float) $res[
'situation_percent'];
6794 if ($include_credit_note) {
6795 $sql =
'SELECT fd.situation_percent FROM '.MAIN_DB_PREFIX.
'facturedet fd';
6796 $sql .=
' JOIN '.MAIN_DB_PREFIX.
'facture f ON (f.rowid = fd.fk_facture) ';
6797 $sql .=
" WHERE fd.fk_prev_id = ".((int) $this->fk_prev_id);
6798 $sql .=
" AND f.situation_cycle_ref = ".((int) $invoicecache[$invoiceid]->situation_cycle_ref);
6799 $sql .=
" AND f.type = ".Facture::TYPE_CREDIT_NOTE;
6801 $res = $this->db->query($sql);
6803 while ($obj = $this->db->fetch_object($res)) {
6804 $returnPercent = $returnPercent + (float) $obj->situation_percent;
6811 return $returnPercent;
6813 $this->error = $this->db->error();
6814 dol_syslog(get_class($this).
"::select Error ".$this->error, LOG_ERR);
6815 $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