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) {
982 if ($_facrec->lines[$i]->fk_product) {
983 $prod =
new Product($this->db);
984 $res = $prod->fetch($_facrec->lines[$i]->fk_product);
988 if (($_facrec->lines[$i]->product_type != 9 && empty($_facrec->lines[$i]->fk_parent_line)) || $_facrec->lines[$i]->product_type == 9) {
1000 $tva_tx = $_facrec->lines[$i]->tva_tx.($_facrec->lines[$i]->vat_src_code ?
'('.$_facrec->lines[$i]->vat_src_code.
')' :
'');
1001 $tva_npr = $_facrec->lines[$i]->info_bits;
1002 if (empty($tva_tx)) {
1005 $localtax1_tx = $_facrec->lines[$i]->localtax1_tx;
1006 $localtax2_tx = $_facrec->lines[$i]->localtax2_tx;
1008 $fk_product_fournisseur_price = empty($_facrec->lines[$i]->fk_product_fournisseur_price) ? null : $_facrec->lines[$i]->fk_product_fournisseur_price;
1009 $buyprice = empty($_facrec->lines[$i]->buyprice) ? 0 : $_facrec->lines[$i]->buyprice;
1012 if (!$buyprice && $_facrec->lines[$i]->fk_product > 0) {
1013 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
1015 $producttmp->fetch($_facrec->lines[$i]->fk_product);
1020 if (
getDolGlobalString(
'MARGIN_TYPE') ==
'costprice' && !empty($producttmp->cost_price)) {
1021 $buyprice = $producttmp->cost_price;
1023 $buyprice = $producttmp->pmp;
1025 if ($producttmp->find_min_price_product_fournisseur($_facrec->lines[$i]->fk_product) > 0) {
1026 if ($producttmp->product_fourn_price_id > 0) {
1027 $buyprice =
price2num($producttmp->fourn_unitprice * (1 - $producttmp->fourn_remise_percent / 100) + $producttmp->fourn_remise,
'MU');
1033 $result_insert = $this->
addline(
1034 $_facrec->lines[$i]->desc,
1035 $_facrec->lines[$i]->subprice,
1036 $_facrec->lines[$i]->qty,
1040 $_facrec->lines[$i]->fk_product,
1041 $_facrec->lines[$i]->remise_percent,
1042 ($_facrec->lines[$i]->date_start_fill == 1 && $originaldatewhen) ? $originaldatewhen :
'',
1043 ($_facrec->lines[$i]->date_end_fill == 1 && $previousdaynextdatewhen) ? $previousdaynextdatewhen :
'',
1049 $_facrec->lines[$i]->product_type,
1050 $_facrec->lines[$i]->rang,
1051 $_facrec->lines[$i]->special_code,
1055 $fk_product_fournisseur_price,
1057 $_facrec->lines[$i]->label,
1058 empty($_facrec->lines[$i]->array_options) ? null : $_facrec->lines[$i]->array_options,
1061 $_facrec->lines[$i]->fk_unit,
1062 $_facrec->lines[$i]->multicurrency_subprice,
1063 $_facrec->lines[$i]->ref_ext,
1068 if ($result_insert > 0 && $_facrec->lines[$i]->product_type == 9) {
1069 $fk_parent_line = $result_insert;
1072 if ($result_insert < 0) {
1074 $this->error = $this->db->error();
1093 if (!$error && !$notrigger) {
1103 $this->db->commit();
1106 $this->db->rollback();
1110 $this->error = $langs->trans(
'FailedToUpdatePrice');
1111 $this->db->rollback();
1115 dol_syslog(get_class($this).
"::create error ".$this->error, LOG_ERR);
1116 $this->db->rollback();
1120 $this->error = $this->db->error();
1121 $this->db->rollback();
1139 $facture =
new Facture($this->db);
1145 if (!empty($this->array_options)) {
1146 $facture->array_options = $this->array_options;
1149 foreach ($this->lines as &$line) {
1150 $line->fetch_optionals();
1154 $facture->type = $this->type;
1155 $facture->subtype = $this->subtype;
1156 $facture->socid = $this->socid;
1157 $facture->date = $this->date;
1158 $facture->date_pointoftax = $this->date_pointoftax;
1159 $facture->note_public = $this->note_public;
1160 $facture->note_private = $this->note_private;
1161 $facture->ref_client = $this->ref_client;
1162 $facture->model_pdf = $this->model_pdf;
1163 $facture->fk_project = $this->fk_project;
1164 $facture->cond_reglement_id = $this->cond_reglement_id;
1165 $facture->mode_reglement_id = $this->mode_reglement_id;
1169 $facture->origin = $this->origin;
1170 $facture->origin_id = $this->origin_id;
1171 $facture->fk_account = $this->fk_account;
1173 $facture->lines = $this->lines;
1174 $facture->situation_counter = $this->situation_counter;
1175 $facture->situation_cycle_ref = $this->situation_cycle_ref;
1176 $facture->situation_final = $this->situation_final;
1178 $facture->retained_warranty = $this->retained_warranty;
1179 $facture->retained_warranty_fk_cond_reglement = $this->retained_warranty_fk_cond_reglement;
1180 $facture->retained_warranty_date_limit = $this->retained_warranty_date_limit;
1182 $facture->fk_user_author = $user->id;
1186 foreach ($facture->lines as $i => $tmpline) {
1187 $facture->lines[$i]->fk_prev_id = $this->lines[$i]->rowid;
1188 if ($invertdetail) {
1189 $facture->lines[$i]->subprice = -$facture->lines[$i]->subprice;
1190 $facture->lines[$i]->total_ht = -$facture->lines[$i]->total_ht;
1191 $facture->lines[$i]->total_tva = -$facture->lines[$i]->total_tva;
1192 $facture->lines[$i]->total_localtax1 = -$facture->lines[$i]->total_localtax1;
1193 $facture->lines[$i]->total_localtax2 = -$facture->lines[$i]->total_localtax2;
1194 $facture->lines[$i]->total_ttc = -$facture->lines[$i]->total_ttc;
1195 $facture->lines[$i]->ref_ext =
'';
1199 dol_syslog(get_class($this).
"::createFromCurrent invertdetail=".$invertdetail.
" socid=".$this->socid.
" nboflines=".count($facture->lines));
1201 $facid = $facture->create($user);
1203 $this->error = $facture->error;
1204 $this->errors = $facture->errors;
1208 foreach ($this->linkedObjectsIds as $typeObject => $Tfk_object) {
1209 foreach ($Tfk_object as $fk_object) {
1210 $facture->add_object_linked($typeObject, $fk_object);
1214 $facture->add_object_linked(
'facture', $this->fk_facture_source);
1230 global $conf, $hookmanager;
1234 $object =
new Facture($this->db);
1238 $object->fetch($fromid);
1241 $objFrom = clone $object;
1244 if (!empty($this->socid) && $this->socid != $object->socid) {
1245 $objsoc =
new Societe($this->db);
1247 if ($objsoc->fetch($this->socid) > 0) {
1248 $object->socid = $objsoc->id;
1249 $object->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1250 $object->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1251 $object->fk_project =
'';
1252 $object->fk_delivery_address =
'';
1263 $object->date = (empty($this->date) ?
dol_now() : $this->date);
1264 $object->user_creation_id = $user->id;
1265 $object->user_validation_id =
null;
1266 $object->fk_user_author = $user->id;
1267 $object->fk_user_valid =
null;
1268 $object->fk_facture_source = 0;
1269 $object->date_creation =
'';
1270 $object->date_modification =
'';
1271 $object->date_validation =
'';
1272 $object->ref_client =
'';
1273 $object->close_code =
'';
1274 $object->close_note =
'';
1276 $object->note_private =
'';
1277 $object->note_public =
'';
1281 foreach ($object->lines as $i => $line) {
1282 if (($object->lines[$i]->info_bits & 0x02) == 0x02) {
1283 unset($object->lines[$i]);
1289 if (
getDolGlobalString(
'INVOICE_AUTO_NEXT_MONTH_ON_LINES') && !empty($line->date_start) && !empty($line->date_end)) {
1301 if (
dol_mktime(0, 0, 0, $start[
'mon'], $start[
'mday'], $start[
'year'],
'gmt') == $first
1302 &&
dol_mktime(23, 59, 59, $end[
'mon'], $end[
'mday'], $end[
'year'],
'gmt') == $last) {
1306 $object->lines[$i]->date_start = $newFirst;
1307 $object->lines[$i]->date_end = $newLast;
1311 $object->lines[$i]->ref_ext =
'';
1315 $object->context[
'createfromclone'] =
'createfromclone';
1316 $result = $object->create($user);
1319 $this->error = $object->error;
1320 $this->errors = $object->errors;
1323 if ($object->copy_linked_contact($objFrom,
'internal') < 0) {
1325 $this->error = $object->error;
1326 $this->errors = $object->errors;
1327 } elseif ($object->socid == $objFrom->socid) {
1329 if ($object->copy_linked_contact($objFrom,
'external') < 0) {
1331 $this->error = $object->error;
1332 $this->errors = $object->errors;
1339 if (is_object($hookmanager)) {
1340 $parameters = array(
'objFrom'=>$objFrom);
1342 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $object, $action);
1350 unset($object->context[
'createfromclone']);
1354 $this->db->commit();
1357 $this->db->rollback();
1371 global $conf, $hookmanager;
1379 $num = count($object->lines);
1380 for ($i = 0; $i < $num; $i++) {
1383 $line->libelle = $object->lines[$i]->libelle;
1384 $line->label = $object->lines[$i]->label;
1385 $line->desc = $object->lines[$i]->desc;
1386 $line->subprice = $object->lines[$i]->subprice;
1387 $line->total_ht = $object->lines[$i]->total_ht;
1388 $line->total_tva = $object->lines[$i]->total_tva;
1389 $line->total_localtax1 = $object->lines[$i]->total_localtax1;
1390 $line->total_localtax2 = $object->lines[$i]->total_localtax2;
1391 $line->total_ttc = $object->lines[$i]->total_ttc;
1392 $line->vat_src_code = $object->lines[$i]->vat_src_code;
1393 $line->tva_tx = $object->lines[$i]->tva_tx;
1394 $line->localtax1_tx = $object->lines[$i]->localtax1_tx;
1395 $line->localtax2_tx = $object->lines[$i]->localtax2_tx;
1396 $line->qty = $object->lines[$i]->qty;
1397 $line->fk_remise_except = $object->lines[$i]->fk_remise_except;
1398 $line->remise_percent = $object->lines[$i]->remise_percent;
1399 $line->fk_product = $object->lines[$i]->fk_product;
1400 $line->info_bits = $object->lines[$i]->info_bits;
1401 $line->product_type = $object->lines[$i]->product_type;
1402 $line->rang = $object->lines[$i]->rang;
1403 $line->special_code = $object->lines[$i]->special_code;
1404 $line->fk_parent_line = $object->lines[$i]->fk_parent_line;
1405 $line->fk_unit = $object->lines[$i]->fk_unit;
1406 $line->date_start = $object->lines[$i]->date_start;
1407 $line->date_end = $object->lines[$i]->date_end;
1410 $line->fk_multicurrency = $object->lines[$i]->fk_multicurrency;
1411 $line->multicurrency_code = $object->lines[$i]->multicurrency_code;
1412 $line->multicurrency_subprice = $object->lines[$i]->multicurrency_subprice;
1413 $line->multicurrency_total_ht = $object->lines[$i]->multicurrency_total_ht;
1414 $line->multicurrency_total_tva = $object->lines[$i]->multicurrency_total_tva;
1415 $line->multicurrency_total_ttc = $object->lines[$i]->multicurrency_total_ttc;
1417 $line->fk_fournprice = $object->lines[$i]->fk_fournprice;
1418 $marginInfos =
getMarginInfos($object->lines[$i]->subprice, $object->lines[$i]->remise_percent, $object->lines[$i]->tva_tx, $object->lines[$i]->localtax1_tx, $object->lines[$i]->localtax2_tx, $object->lines[$i]->fk_fournprice, $object->lines[$i]->pa_ht);
1419 $line->pa_ht = $marginInfos[0];
1422 $object->lines[$i]->fetch_optionals();
1423 foreach ($object->lines[$i]->array_options as $options_key => $value) {
1424 $line->array_options[$options_key] = $value;
1427 $this->lines[$i] = $line;
1430 $this->socid = $object->socid;
1431 $this->fk_project = $object->fk_project;
1432 $this->fk_account = $object->fk_account;
1433 $this->cond_reglement_id = $object->cond_reglement_id;
1434 $this->mode_reglement_id = $object->mode_reglement_id;
1435 $this->availability_id = $object->availability_id;
1436 $this->demand_reason_id = $object->demand_reason_id;
1437 $this->delivery_date = $object->delivery_date;
1438 $this->fk_delivery_address = $object->fk_delivery_address;
1439 $this->contact_id = $object->contact_id;
1440 $this->ref_client = $object->ref_client;
1443 $this->note_private = $object->note_private;
1444 $this->note_public = $object->note_public;
1447 $this->module_source = $object->module_source;
1448 $this->pos_source = $object->pos_source;
1450 $this->origin = $object->element;
1451 $this->origin_id = $object->id;
1453 $this->fk_user_author = $user->id;
1456 $object->fetch_optionals();
1457 foreach ($object->array_options as $options_key => $value) {
1458 $this->array_options[$options_key] = $value;
1462 $this->linked_objects[$this->origin] = $this->origin_id;
1463 if (!empty($object->other_linked_objects) && is_array($object->other_linked_objects)) {
1464 $this->linked_objects = array_merge($this->linked_objects, $object->other_linked_objects);
1467 $ret = $this->
create($user);
1471 $hookmanager->initHooks(array(
'invoicedao'));
1473 $parameters = array(
'objFrom'=>$object);
1475 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $this, $action);
1501 global $conf, $hookmanager;
1509 $use_all_lines = empty($lines);
1510 $num = count($object->lines);
1511 for ($i = 0; $i < $num; $i++) {
1512 if (!$use_all_lines && !in_array($object->lines[$i]->id, $lines)) {
1518 $line->libelle = $object->lines[$i]->libelle;
1519 $line->label = $object->lines[$i]->label;
1520 $line->desc = $object->lines[$i]->desc;
1521 $line->subprice = $object->lines[$i]->subprice;
1522 $line->total_ht = $object->lines[$i]->total_ht;
1523 $line->total_tva = $object->lines[$i]->total_tva;
1524 $line->total_localtax1 = $object->lines[$i]->total_localtax1;
1525 $line->total_localtax2 = $object->lines[$i]->total_localtax2;
1526 $line->total_ttc = $object->lines[$i]->total_ttc;
1527 $line->vat_src_code = $object->lines[$i]->vat_src_code;
1528 $line->tva_tx = $object->lines[$i]->tva_tx;
1529 $line->localtax1_tx = $object->lines[$i]->localtax1_tx;
1530 $line->localtax2_tx = $object->lines[$i]->localtax2_tx;
1531 $line->qty = $object->lines[$i]->qty;
1532 $line->fk_remise_except = $object->lines[$i]->fk_remise_except;
1533 $line->remise_percent = $object->lines[$i]->remise_percent;
1534 $line->fk_product = $object->lines[$i]->fk_product;
1535 $line->info_bits = $object->lines[$i]->info_bits;
1536 $line->product_type = $object->lines[$i]->product_type;
1537 $line->rang = $object->lines[$i]->rang;
1538 $line->special_code = $object->lines[$i]->special_code;
1539 $line->fk_parent_line = $object->lines[$i]->fk_parent_line;
1540 $line->fk_unit = $object->lines[$i]->fk_unit;
1541 $line->date_start = $object->lines[$i]->date_start;
1542 $line->date_end = $object->lines[$i]->date_end;
1545 $line->fk_multicurrency = $object->lines[$i]->fk_multicurrency;
1546 $line->multicurrency_code = $object->lines[$i]->multicurrency_code;
1547 $line->multicurrency_subprice = $object->lines[$i]->multicurrency_subprice;
1548 $line->multicurrency_total_ht = $object->lines[$i]->multicurrency_total_ht;
1549 $line->multicurrency_total_tva = $object->lines[$i]->multicurrency_total_tva;
1550 $line->multicurrency_total_ttc = $object->lines[$i]->multicurrency_total_ttc;
1552 $line->fk_fournprice = $object->lines[$i]->fk_fournprice;
1553 $marginInfos =
getMarginInfos($object->lines[$i]->subprice, $object->lines[$i]->remise_percent, $object->lines[$i]->tva_tx, $object->lines[$i]->localtax1_tx, $object->lines[$i]->localtax2_tx, $object->lines[$i]->fk_fournprice, $object->lines[$i]->pa_ht);
1554 $line->pa_ht = $marginInfos[0];
1557 $object->lines[$i]->fetch_optionals();
1558 foreach ($object->lines[$i]->array_options as $options_key => $value) {
1559 $line->array_options[$options_key] = $value;
1562 $this->lines[$i] = $line;
1565 $this->socid = $object->socid;
1566 $this->fk_project = $object->fk_project;
1567 $this->fk_account = $object->fk_account;
1568 $this->cond_reglement_id = $object->cond_reglement_id;
1569 $this->mode_reglement_id = $object->mode_reglement_id;
1570 $this->availability_id = $object->availability_id;
1571 $this->demand_reason_id = $object->demand_reason_id;
1572 $this->delivery_date = $object->delivery_date;
1573 $this->fk_delivery_address = $object->fk_delivery_address;
1574 $this->contact_id = $object->contact_id;
1575 $this->ref_client = $object->ref_client;
1578 $this->note_private = $object->note_private;
1579 $this->note_public = $object->note_public;
1582 $this->module_source = $object->module_source;
1583 $this->pos_source = $object->pos_source;
1585 $this->origin = $object->element;
1586 $this->origin_id = $object->id;
1588 $this->fk_user_author = $user->id;
1591 $object->fetch_optionals();
1592 foreach ($object->array_options as $options_key => $value) {
1593 $this->array_options[$options_key] = $value;
1597 $this->linked_objects[$this->origin] = $this->origin_id;
1598 if (!empty($object->other_linked_objects) && is_array($object->other_linked_objects)) {
1599 $this->linked_objects = array_merge($this->linked_objects, $object->other_linked_objects);
1602 $ret = $this->
create($user);
1606 $hookmanager->initHooks(array(
'invoicedao'));
1608 $parameters = array(
'objFrom'=>$object);
1610 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $this, $action);
1640 global $conf, $langs, $hookmanager, $action;
1642 if (! in_array($origin->element, array(
'propal',
'commande'))) {
1643 $origin->error =
'ErrorCanOnlyAutomaticallyGenerateADepositFromProposalOrOrder';
1648 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'DateInvoice'));
1652 require_once DOL_DOCUMENT_ROOT .
'/core/lib/date.lib.php';
1655 $origin->error =
'ErrorDateIsInFuture';
1659 if ($payment_terms_id <= 0) {
1660 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'PaymentConditionsShort'));
1664 $payment_conditions_deposit_percent =
getDictionaryValue(
'c_payment_term',
'deposit_percent', $origin->cond_reglement_id);
1666 if (empty($payment_conditions_deposit_percent)) {
1667 $origin->error =
'ErrorPaymentConditionsNotEligibleToDepositCreation';
1671 if (empty($origin->deposit_percent)) {
1672 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'DepositPercent'));
1676 $deposit =
new self($origin->db);
1677 $deposit->socid = $origin->socid;
1679 $deposit->fk_project = $origin->fk_project;
1680 $deposit->ref_client = $origin->ref_client;
1681 $deposit->date = $date;
1682 $deposit->mode_reglement_id = $origin->mode_reglement_id;
1683 $deposit->cond_reglement_id = $payment_terms_id;
1684 $deposit->availability_id = $origin->availability_id;
1685 $deposit->demand_reason_id = $origin->demand_reason_id;
1686 $deposit->fk_account = $origin->fk_account;
1687 $deposit->fk_incoterms = $origin->fk_incoterms;
1688 $deposit->location_incoterms = $origin->location_incoterms;
1689 $deposit->fk_multicurrency = $origin->fk_multicurrency;
1690 $deposit->multicurrency_code = $origin->multicurrency_code;
1691 $deposit->multicurrency_tx = $origin->multicurrency_tx;
1692 $deposit->module_source = $origin->module_source;
1693 $deposit->pos_source = $origin->pos_source;
1694 $deposit->model_pdf =
'crabe';
1696 $modelByTypeConfName =
'FACTURE_ADDON_PDF_' . $deposit->type;
1705 $deposit->note_private = $origin->note_private;
1706 $deposit->note_public = $origin->note_public;
1709 $deposit->origin = $origin->element;
1710 $deposit->origin_id = $origin->id;
1712 $origin->fetch_optionals();
1714 foreach ($origin->array_options as $extrakey => $value) {
1715 $deposit->array_options[$extrakey] = $value;
1718 $deposit->linked_objects[$deposit->origin] = $deposit->origin_id;
1720 foreach ($overrideFields as $key => $value) {
1721 $deposit->$key = $value;
1724 $deposit->context[
'createdepositfromorigin'] =
'createdepositfromorigin';
1726 $origin->db->begin();
1729 $createReturn = $deposit->create($user, $notrigger);
1731 if ($createReturn <= 0) {
1732 $origin->db->rollback();
1733 $origin->error = $deposit->error;
1734 $origin->errors = $deposit->errors;
1738 $amount_ttc_diff = 0;
1739 $amountdeposit = array();
1740 $descriptions = array();
1743 $amount = $origin->total_ttc * ($origin->deposit_percent / 100);
1745 $TTotalByTva = array();
1746 foreach ($origin->lines as &$line) {
1747 if (!empty($line->special_code)) {
1750 $TTotalByTva[$line->tva_tx] += $line->total_ttc;
1751 $descriptions[$line->tva_tx] .=
'<li>' . (!empty($line->product_ref) ? $line->product_ref .
' - ' :
'');
1752 $descriptions[$line->tva_tx] .= (!empty($line->product_label) ? $line->product_label .
' - ' :
'');
1753 $descriptions[$line->tva_tx] .= $langs->trans(
'Qty') .
' : ' . $line->qty;
1754 $descriptions[$line->tva_tx] .=
' - ' . $langs->trans(
'TotalHT') .
' : ' .
price($line->total_ht) .
'</li>';
1757 foreach ($TTotalByTva as $tva => &$total) {
1758 $coef = $total / $origin->total_ttc;
1759 $am = $amount * $coef;
1760 $amount_ttc_diff += $am;
1761 $amountdeposit[$tva] += $am / (1 + $tva / 100);
1765 $lines = $origin->lines;
1766 $numlines = count($lines);
1767 for ($i = 0; $i < $numlines; $i++) {
1768 if (empty($lines[$i]->qty)) {
1771 if (!empty($lines[$i]->special_code)) {
1775 $totalamount += $lines[$i]->total_ht;
1776 $tva_tx = $lines[$i]->tva_tx;
1777 $amountdeposit[$tva_tx] += ($lines[$i]->total_ht * $origin->deposit_percent) / 100;
1778 $descriptions[$tva_tx] .=
'<li>' . (!empty($lines[$i]->product_ref) ? $lines[$i]->product_ref .
' - ' :
'');
1779 $descriptions[$tva_tx] .= (!empty($lines[$i]->product_label) ? $lines[$i]->product_label .
' - ' :
'');
1780 $descriptions[$tva_tx] .= $langs->trans(
'Qty') .
' : ' . $lines[$i]->qty;
1781 $descriptions[$tva_tx] .=
' - ' . $langs->trans(
'TotalHT') .
' : ' .
price($lines[$i]->total_ht) .
'</li>';
1784 if ($totalamount == 0) {
1785 $amountdeposit[0] = 0;
1788 $amount_ttc_diff = $amountdeposit[0];
1791 foreach ($amountdeposit as $tva => $amount) {
1792 if (empty($amount)) {
1796 $descline =
'(DEPOSIT) ('. $origin->deposit_percent .
'%) - '.$origin->ref;
1799 if (
getDolGlobalString(
'INVOICE_DEPOSIT_VARIABLE_MODE_DETAIL_LINES_IN_DESCRIPTION') && !empty($descriptions[$tva])) {
1800 $descline .=
'<ul>' . $descriptions[$tva] .
'</ul>';
1803 $addlineResult = $deposit->addline(
1810 (!
getDolGlobalString(
'INVOICE_PRODUCTID_DEPOSIT') ? 0 : $conf->global->INVOICE_PRODUCTID_DEPOSIT),
1830 if ($addlineResult < 0) {
1831 $origin->db->rollback();
1832 $origin->error = $deposit->error;
1833 $origin->errors = $deposit->errors;
1838 $diff = $deposit->total_ttc - $amount_ttc_diff;
1841 $deposit->fetch_lines();
1842 $subprice_diff = $deposit->lines[0]->subprice - $diff / (1 + $deposit->lines[0]->tva_tx / 100);
1844 $updatelineResult = $deposit->updateline(
1845 $deposit->lines[0]->id,
1846 $deposit->lines[0]->desc,
1848 $deposit->lines[0]->qty,
1849 $deposit->lines[0]->remise_percent,
1850 $deposit->lines[0]->date_start,
1851 $deposit->lines[0]->date_end,
1852 $deposit->lines[0]->tva_tx,
1856 $deposit->lines[0]->info_bits,
1857 $deposit->lines[0]->product_type,
1861 $deposit->lines[0]->pa_ht,
1862 $deposit->lines[0]->label,
1868 if ($updatelineResult < 0) {
1869 $origin->db->rollback();
1870 $origin->error = $deposit->error;
1871 $origin->errors = $deposit->errors;
1876 $hookmanager->initHooks(array(
'invoicedao'));
1878 $parameters = array(
'objFrom' => $origin);
1879 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $deposit, $action);
1882 $origin->db->rollback();
1883 $origin->error = $hookmanager->error;
1884 $origin->errors = $hookmanager->errors;
1888 if (!empty($autoValidateDeposit)) {
1889 $validateReturn = $deposit->validate($user,
'', 0, $notrigger);
1891 if ($validateReturn < 0) {
1892 $origin->db->rollback();
1893 $origin->error = $deposit->error;
1894 $origin->errors = $deposit->errors;
1899 unset($deposit->context[
'createdepositfromorigin']);
1901 $origin->db->commit();
1915 global $conf, $langs, $mysoc, $user;
1917 $langs->load(
'bills');
1920 $moretitle = $params[
'moretitle'] ??
'';
1921 $picto = $this->picto;
1922 if ($this->
type == self::TYPE_REPLACEMENT) {
1925 if ($this->
type == self::TYPE_CREDIT_NOTE) {
1928 if ($this->
type == self::TYPE_DEPOSIT) {
1932 if ($user->hasRight(
"facture",
"read")) {
1933 $datas[
'picto'] =
img_picto(
'', $picto).
' <u class="paddingrightonly">'.$langs->trans(
"Invoice").
'</u>';
1935 $datas[
'picto'] .=
' '.$this->getLibType(1);
1938 if (!empty($params[
'fromajaxtooltip']) && !isset($this->alreadypaid)) {
1942 if (isset($this->
status) && isset($this->alreadypaid)) {
1943 $datas[
'picto'] .=
' '.$this->getLibStatut(5, $this->alreadypaid);
1946 $datas[
'picto'] .=
' - '.$moretitle;
1948 if (!empty($this->
ref)) {
1949 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
1951 if (!empty($this->ref_customer)) {
1952 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.$this->ref_customer;
1954 if (!empty($this->date)) {
1955 $datas[
'date'] =
'<br><b>'.$langs->trans(
'Date').
':</b> '.
dol_print_date($this->date,
'day');
1957 if (!empty($this->total_ht)) {
1958 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
1960 if (!empty($this->total_tva)) {
1961 $datas[
'amountvat'] =
'<br><b>'.$langs->trans(
'AmountVAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
1963 if (!empty($this->revenuestamp) && $this->revenuestamp != 0) {
1964 $datas[
'amountrevenustamp'] =
'<br><b>'.$langs->trans(
'RevenueStamp').
':</b> '.
price($this->revenuestamp, 0, $langs, 0, -1, -1, $conf->currency);
1966 if (!empty($this->total_localtax1) && $this->total_localtax1 != 0) {
1968 $datas[
'amountlt1'] =
'<br><b>'.$langs->transcountry(
'AmountLT1', $mysoc->country_code).
':</b> '.
price($this->total_localtax1, 0, $langs, 0, -1, -1, $conf->currency);
1970 if (!empty($this->total_localtax2) && $this->total_localtax2 != 0) {
1971 $datas[
'amountlt2'] =
'<br><b>'.$langs->transcountry(
'AmountLT2', $mysoc->country_code).
':</b> '.
price($this->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency);
1973 if (!empty($this->total_ttc)) {
1974 $datas[
'amountttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
1995 public function getNomUrl($withpicto = 0, $option =
'', $max = 0, $short = 0, $moretitle =
'', $notooltip = 0, $addlinktonotes = 0, $save_lastsearch_value = -1, $target =
'')
1997 global $langs, $conf, $user, $mysoc;
1999 if (!empty($conf->dol_no_mouse_hover)) {
2005 if ($option ==
'withdraw') {
2006 $url = DOL_URL_ROOT.
'/compta/facture/prelevement.php?facid='.$this->id;
2008 $url = DOL_URL_ROOT.
'/compta/facture/card.php?facid='.$this->id;
2011 if (!$user->hasRight(
"facture",
"read")) {
2015 if ($option !==
'nolink') {
2017 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2018 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
2019 $add_save_lastsearch_values = 1;
2021 if ($add_save_lastsearch_values) {
2022 $url .=
'&save_lastsearch_values=1';
2030 $picto = $this->picto;
2031 if ($this->
type == self::TYPE_REPLACEMENT) {
2034 if ($this->
type == self::TYPE_CREDIT_NOTE) {
2037 if ($this->
type == self::TYPE_DEPOSIT) {
2042 'objecttype' => $this->element,
2043 'moretitle' => $moretitle,
2044 'option' => $option,
2046 $classfortooltip =
'classfortooltip';
2049 $classfortooltip =
'classforajaxtooltip';
2050 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
2056 $linkclose = ($target ?
' target="'.$target.
'"' :
'');
2057 if (empty($notooltip) && $user->hasRight(
"facture",
"read")) {
2059 $label = $langs->trans(
"Invoice");
2060 $linkclose .=
' alt="'.dol_escape_htmltag($label, 1).
'"';
2062 $linkclose .= ($label ?
' title="'.dol_escape_htmltag($label, 1).
'"' :
' title="tocomplete"');
2063 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
2066 $linkstart =
'<a href="'.$url.
'"';
2067 $linkstart .= $linkclose.
'>';
2070 if ($option ==
'nolink') {
2075 $result .= $linkstart;
2077 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), ($notooltip ? (($withpicto != 2) ?
'class="paddingright"' :
'') :
'class="'.(($withpicto != 2) ?
'paddingright ' :
'').
'"'), 0, 0, $notooltip ? 0 : 1);
2079 if ($withpicto != 2) {
2080 $result .= ($max ?
dol_trunc($this->
ref, $max) : $this->ref);
2082 $result .= $linkend;
2084 if ($addlinktonotes) {
2085 $txttoshow = ($user->socid > 0 ? $this->note_public : $this->note_private);
2088 $notetoshow = $langs->trans(
"ViewPrivateNote").
':<br>'.$txttoshow;
2089 $result .=
' <span class="note inline-block">';
2090 $result .=
'<a href="'.DOL_URL_ROOT.
'/compta/facture/note.php?id='.$this->
id.
'" class="classfortooltip" title="'.
dol_escape_htmltag($notetoshow, 1, 1).
'">';
2095 $result .=
'</span>';
2099 global $action, $hookmanager;
2100 $hookmanager->initHooks(array(
'invoicedao'));
2101 $parameters = array(
'id'=>$this->
id,
'getnomurl' => &$result,
'notooltip' => $notooltip,
'addlinktonotes' => $addlinktonotes,
'save_lastsearch_value'=> $save_lastsearch_value,
'target' => $target);
2102 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
2104 $result = $hookmanager->resPrint;
2106 $result .= $hookmanager->resPrint;
2122 public function fetch($rowid, $ref =
'', $ref_ext =
'', $notused = 0, $fetch_situation =
false)
2124 if (empty($rowid) && empty($ref) && empty($ref_ext)) {
2128 $sql =
'SELECT f.rowid, f.entity, f.ref, f.ref_client, f.ref_ext, f.type, f.subtype, f.fk_soc';
2129 $sql .=
', f.total_tva, f.localtax1, f.localtax2, f.total_ht, f.total_ttc, f.revenuestamp';
2130 $sql .=
', f.datef as df, f.date_pointoftax';
2131 $sql .=
', f.date_lim_reglement as dlr';
2132 $sql .=
', f.datec as datec';
2133 $sql .=
', f.date_valid as datev';
2134 $sql .=
', f.tms as datem';
2135 $sql .=
', f.note_private, f.note_public, f.fk_statut as status, f.paye, f.close_code, f.close_note, f.fk_user_author, f.fk_user_valid, f.fk_user_modif, f.model_pdf, f.last_main_doc';
2136 $sql .=
', f.fk_facture_source, f.fk_fac_rec_source';
2137 $sql .=
', f.fk_mode_reglement, f.fk_cond_reglement, f.fk_projet as fk_project, f.extraparams';
2138 $sql .=
', f.situation_cycle_ref, f.situation_counter, f.situation_final';
2139 $sql .=
', f.fk_account';
2140 $sql .=
", f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc";
2141 $sql .=
', p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
2142 $sql .=
', c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_doc';
2143 $sql .=
', f.fk_incoterms, f.location_incoterms';
2144 $sql .=
', f.module_source, f.pos_source';
2145 $sql .=
", i.libelle as label_incoterms";
2146 $sql .=
", f.retained_warranty as retained_warranty, f.retained_warranty_date_limit as retained_warranty_date_limit, f.retained_warranty_fk_cond_reglement as retained_warranty_fk_cond_reglement";
2147 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facture as f';
2148 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_payment_term as c ON f.fk_cond_reglement = c.rowid';
2149 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_paiement as p ON f.fk_mode_reglement = p.id';
2150 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON f.fk_incoterms = i.rowid';
2153 $sql .=
" WHERE f.rowid = ".((int) $rowid);
2155 $sql .=
' WHERE f.entity IN ('.getEntity(
'invoice').
')';
2157 $sql .=
" AND f.ref = '".$this->db->escape($ref).
"'";
2160 $sql .=
" AND f.ref_ext = '".$this->db->escape($ref_ext).
"'";
2164 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
2165 $resql = $this->db->query($sql);
2167 if ($this->db->num_rows($resql)) {
2168 $obj = $this->db->fetch_object($resql);
2170 $this->
id = $obj->rowid;
2171 $this->entity = $obj->entity;
2173 $this->
ref = $obj->ref;
2174 $this->ref_client = $obj->ref_client;
2175 $this->ref_customer = $obj->ref_client;
2176 $this->ref_ext = $obj->ref_ext;
2177 $this->
type = $obj->type;
2178 $this->subtype = $obj->subtype;
2179 $this->date = $this->db->jdate($obj->df);
2180 $this->date_pointoftax = $this->db->jdate($obj->date_pointoftax);
2181 $this->date_creation = $this->db->jdate($obj->datec);
2182 $this->date_validation = $this->db->jdate($obj->datev);
2183 $this->date_modification = $this->db->jdate($obj->datem);
2184 $this->datem = $this->db->jdate($obj->datem);
2185 $this->total_ht = $obj->total_ht;
2186 $this->total_tva = $obj->total_tva;
2187 $this->total_localtax1 = $obj->localtax1;
2188 $this->total_localtax2 = $obj->localtax2;
2189 $this->total_ttc = $obj->total_ttc;
2190 $this->revenuestamp = $obj->revenuestamp;
2191 $this->paye = $obj->paye;
2192 $this->close_code = $obj->close_code;
2193 $this->close_note = $obj->close_note;
2195 $this->socid = $obj->fk_soc;
2196 $this->thirdparty =
null;
2198 $this->fk_project = $obj->fk_project;
2199 $this->project =
null;
2201 $this->
statut = $obj->status;
2202 $this->
status = $obj->status;
2204 $this->date_lim_reglement = $this->db->jdate($obj->dlr);
2205 $this->mode_reglement_id = $obj->fk_mode_reglement;
2206 $this->mode_reglement_code = $obj->mode_reglement_code;
2207 $this->mode_reglement = $obj->mode_reglement_libelle;
2208 $this->cond_reglement_id = $obj->fk_cond_reglement;
2209 $this->cond_reglement_code = $obj->cond_reglement_code;
2210 $this->cond_reglement = $obj->cond_reglement_libelle;
2211 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
2212 $this->fk_account = ($obj->fk_account > 0) ? $obj->fk_account :
null;
2213 $this->fk_facture_source = $obj->fk_facture_source;
2214 $this->fk_fac_rec_source = $obj->fk_fac_rec_source;
2215 $this->note = $obj->note_private;
2216 $this->note_private = $obj->note_private;
2217 $this->note_public = $obj->note_public;
2218 $this->user_creation_id = $obj->fk_user_author;
2219 $this->user_validation_id = $obj->fk_user_valid;
2220 $this->user_modification_id = $obj->fk_user_modif;
2221 $this->fk_user_author = $obj->fk_user_author;
2222 $this->fk_user_valid = $obj->fk_user_valid;
2223 $this->fk_user_modif = $obj->fk_user_modif;
2224 $this->model_pdf = $obj->model_pdf;
2225 $this->last_main_doc = $obj->last_main_doc;
2226 $this->situation_cycle_ref = $obj->situation_cycle_ref;
2227 $this->situation_counter = $obj->situation_counter;
2228 $this->situation_final = $obj->situation_final;
2229 $this->retained_warranty = $obj->retained_warranty;
2230 $this->retained_warranty_date_limit = $this->db->jdate($obj->retained_warranty_date_limit);
2231 $this->retained_warranty_fk_cond_reglement = $obj->retained_warranty_fk_cond_reglement;
2233 $this->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
2236 $this->fk_incoterms = $obj->fk_incoterms;
2237 $this->location_incoterms = $obj->location_incoterms;
2238 $this->label_incoterms = $obj->label_incoterms;
2240 $this->module_source = $obj->module_source;
2241 $this->pos_source = $obj->pos_source;
2244 $this->fk_multicurrency = $obj->fk_multicurrency;
2245 $this->multicurrency_code = $obj->multicurrency_code;
2246 $this->multicurrency_tx = $obj->multicurrency_tx;
2247 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
2248 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
2249 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
2251 if (($this->
type == self::TYPE_SITUATION || ($this->
type == self::TYPE_CREDIT_NOTE && $this->situation_cycle_ref > 0)) && $fetch_situation) {
2260 $this->lines = array();
2264 $this->error = $this->db->error();
2268 $this->db->free($resql);
2272 $this->error =
'Invoice with id='.$rowid.
' or ref='.$ref.
' or ref_ext='.$ref_ext.
' not found';
2274 dol_syslog(__METHOD__.$this->error, LOG_WARNING);
2278 $this->error = $this->db->lasterror();
2293 public function fetch_lines($only_product = 0, $loadalsotranslation = 0)
2296 $this->lines = array();
2298 $sql =
'SELECT l.rowid, l.fk_facture, l.fk_product, l.fk_parent_line, l.label as custom_label, l.description, l.product_type, l.price, l.qty, l.vat_src_code, l.tva_tx,';
2299 $sql .=
' l.localtax1_tx, l.localtax2_tx, l.localtax1_type, l.localtax2_type, l.remise_percent, l.fk_remise_except, l.subprice, l.ref_ext,';
2300 $sql .=
' l.situation_percent, l.fk_prev_id,';
2301 $sql .=
' l.rang, l.special_code, l.batch, l.fk_warehouse,';
2302 $sql .=
' l.date_start as date_start, l.date_end as date_end,';
2303 $sql .=
' l.info_bits, l.total_ht, l.total_tva, l.total_localtax1, l.total_localtax2, l.total_ttc, l.fk_code_ventilation, l.fk_product_fournisseur_price as fk_fournprice, l.buy_price_ht as pa_ht,';
2304 $sql .=
' l.fk_unit,';
2305 $sql .=
' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
2306 $sql .=
' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc, p.barcode as product_barcode';
2307 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facturedet as l';
2308 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON l.fk_product = p.rowid';
2309 $sql .=
' WHERE l.fk_facture = '.((int) $this->
id);
2310 $sql .=
' ORDER BY l.rang, l.rowid';
2312 dol_syslog(get_class($this).
'::fetch_lines', LOG_DEBUG);
2313 $result = $this->db->query($sql);
2315 $num = $this->db->num_rows($result);
2318 $objp = $this->db->fetch_object($result);
2321 $line->id = $objp->rowid;
2322 $line->rowid = $objp->rowid;
2323 $line->fk_facture = $objp->fk_facture;
2324 $line->label = $objp->custom_label;
2325 $line->desc = $objp->description;
2326 $line->description = $objp->description;
2327 $line->product_type = $objp->product_type;
2328 $line->ref = $objp->product_ref;
2329 $line->product_ref = $objp->product_ref;
2330 $line->libelle = $objp->product_label;
2331 $line->product_label = $objp->product_label;
2332 $line->product_barcode = $objp->product_barcode;
2333 $line->product_desc = $objp->product_desc;
2334 $line->fk_product_type = $objp->fk_product_type;
2335 $line->qty = $objp->qty;
2336 $line->subprice = $objp->subprice;
2337 $line->ref_ext = $objp->ref_ext;
2339 $line->vat_src_code = $objp->vat_src_code;
2340 $line->tva_tx = $objp->tva_tx;
2341 $line->localtax1_tx = $objp->localtax1_tx;
2342 $line->localtax2_tx = $objp->localtax2_tx;
2343 $line->localtax1_type = $objp->localtax1_type;
2344 $line->localtax2_type = $objp->localtax2_type;
2345 $line->remise_percent = $objp->remise_percent;
2346 $line->fk_remise_except = $objp->fk_remise_except;
2347 $line->fk_product = $objp->fk_product;
2348 $line->date_start = $this->db->jdate($objp->date_start);
2349 $line->date_end = $this->db->jdate($objp->date_end);
2350 $line->info_bits = $objp->info_bits;
2351 $line->total_ht = $objp->total_ht;
2352 $line->total_tva = $objp->total_tva;
2353 $line->total_localtax1 = $objp->total_localtax1;
2354 $line->total_localtax2 = $objp->total_localtax2;
2355 $line->total_ttc = $objp->total_ttc;
2357 $line->code_ventilation = $objp->fk_code_ventilation;
2358 $line->fk_fournprice = $objp->fk_fournprice;
2359 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
2360 $line->pa_ht = $marginInfos[0];
2361 $line->marge_tx = $marginInfos[1];
2362 $line->marque_tx = $marginInfos[2];
2363 $line->rang = $objp->rang;
2364 $line->special_code = $objp->special_code;
2365 $line->fk_parent_line = $objp->fk_parent_line;
2366 $line->situation_percent = $objp->situation_percent;
2367 $line->fk_prev_id = $objp->fk_prev_id;
2368 $line->fk_unit = $objp->fk_unit;
2370 $line->batch = $objp->batch;
2371 $line->fk_warehouse = $objp->fk_warehouse;
2374 $line->fk_accounting_account = $objp->fk_code_ventilation;
2377 $line->fk_multicurrency = $objp->fk_multicurrency;
2378 $line->multicurrency_code = $objp->multicurrency_code;
2379 $line->multicurrency_subprice = $objp->multicurrency_subprice;
2380 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
2381 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
2382 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
2384 $line->fetch_optionals();
2387 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
2388 $tmpproduct =
new Product($this->db);
2389 $tmpproduct->fetch($objp->fk_product);
2390 $tmpproduct->getMultiLangs();
2392 $line->multilangs = $tmpproduct->multilangs;
2395 $this->lines[$i] = $line;
2399 $this->db->free($result);
2402 $this->error = $this->db->error();
2417 $this->tab_previous_situation_invoice = array();
2418 $this->tab_next_situation_invoice = array();
2420 $sql =
'SELECT rowid, type, situation_cycle_ref, situation_counter FROM '.MAIN_DB_PREFIX.
'facture';
2421 $sql .=
" WHERE rowid <> ".((int) $this->
id);
2422 $sql .=
' AND entity = '.((int) $this->entity);
2423 $sql .=
' AND situation_cycle_ref = '.(int) $this->situation_cycle_ref;
2424 $sql .=
' ORDER BY situation_counter ASC';
2426 dol_syslog(get_class($this).
'::fetchPreviousNextSituationInvoice ', LOG_DEBUG);
2427 $result = $this->db->query($sql);
2428 if ($result && $this->db->num_rows($result) > 0) {
2429 while ($objp = $this->db->fetch_object($result)) {
2430 $invoice =
new Facture($this->db);
2431 if ($invoice->fetch($objp->rowid) > 0) {
2432 if ($objp->situation_counter < $this->situation_counter
2433 || ($objp->situation_counter == $this->situation_counter && $objp->rowid < $this->id)
2435 $this->tab_previous_situation_invoice[] = $invoice;
2437 $this->tab_next_situation_invoice[] = $invoice;
2456 if (empty($this->
type)) {
2459 if (isset($this->
ref)) {
2460 $this->
ref = trim($this->
ref);
2462 if (isset($this->ref_ext)) {
2463 $this->ref_ext = trim($this->ref_ext);
2465 if (isset($this->ref_client)) {
2466 $this->ref_client = trim($this->ref_client);
2468 if (isset($this->increment)) {
2469 $this->increment = trim($this->increment);
2471 if (isset($this->close_code)) {
2472 $this->close_code = trim($this->close_code);
2474 if (isset($this->close_note)) {
2475 $this->close_note = trim($this->close_note);
2477 if (isset($this->note) || isset($this->note_private)) {
2478 $this->note = (isset($this->note) ? trim($this->note) : trim($this->note_private));
2480 if (isset($this->note) || isset($this->note_private)) {
2481 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note));
2483 if (isset($this->note_public)) {
2484 $this->note_public = trim($this->note_public);
2486 if (isset($this->model_pdf)) {
2487 $this->model_pdf = trim($this->model_pdf);
2489 if (isset($this->import_key)) {
2490 $this->import_key = trim($this->import_key);
2492 if (isset($this->retained_warranty)) {
2493 $this->retained_warranty = (float) $this->retained_warranty;
2501 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facture SET";
2502 $sql .=
" ref=".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
2503 $sql .=
" ref_ext=".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
2504 $sql .=
" type=".(isset($this->
type) ? $this->db->escape($this->
type) :
"null").
",";
2505 $sql .=
" subtype=".(isset($this->subtype) ? $this->db->escape($this->subtype) :
"null").
",";
2506 $sql .=
" ref_client=".(isset($this->ref_client) ?
"'".$this->db->escape($this->ref_client).
"'" :
"null").
",";
2507 $sql .=
" increment=".(isset($this->increment) ?
"'".$this->db->escape($this->increment).
"'" :
"null").
",";
2508 $sql .=
" fk_soc=".(isset($this->socid) ? $this->db->escape($this->socid) :
"null").
",";
2509 $sql .=
" datec=".(strval($this->date_creation) !=
'' ?
"'".$this->db->idate($this->date_creation).
"'" :
'null').
",";
2510 $sql .=
" datef=".(strval($this->date) !=
'' ?
"'".$this->db->idate($this->date).
"'" :
'null').
",";
2511 $sql .=
" date_pointoftax=".(strval($this->date_pointoftax) !=
'' ?
"'".$this->db->idate($this->date_pointoftax).
"'" :
'null').
",";
2512 $sql .=
" date_valid=".(strval($this->date_validation) !=
'' ?
"'".$this->db->idate($this->date_validation).
"'" :
'null').
",";
2513 $sql .=
" paye=".(isset($this->paye) ? $this->db->escape($this->paye) : 0).
",";
2514 $sql .=
" close_code=".(isset($this->close_code) ?
"'".$this->db->escape($this->close_code).
"'" :
"null").
",";
2515 $sql .=
" close_note=".(isset($this->close_note) ?
"'".$this->db->escape($this->close_note).
"'" :
"null").
",";
2516 $sql .=
" total_tva=".(isset($this->total_tva) ? $this->total_tva :
"null").
",";
2517 $sql .=
" localtax1=".(isset($this->total_localtax1) ? $this->total_localtax1 :
"null").
",";
2518 $sql .=
" localtax2=".(isset($this->total_localtax2) ? $this->total_localtax2 :
"null").
",";
2519 $sql .=
" total_ht=".(isset($this->total_ht) ? $this->total_ht :
"null").
",";
2520 $sql .=
" total_ttc=".(isset($this->total_ttc) ? $this->total_ttc :
"null").
",";
2521 $sql .=
" revenuestamp=".((isset($this->revenuestamp) && $this->revenuestamp !=
'') ? $this->db->escape($this->revenuestamp) :
"null").
",";
2522 $sql .=
" fk_statut=".(isset($this->
status) ? $this->db->escape($this->
status) :
"null").
",";
2523 $sql .=
" fk_user_author=".(isset($this->user_author) ? $this->db->escape($this->user_author) :
"null").
",";
2524 $sql .=
" fk_user_valid=".(isset($this->fk_user_valid) ? $this->db->escape($this->fk_user_valid) :
"null").
",";
2525 $sql .=
" fk_facture_source=".(isset($this->fk_facture_source) ? $this->db->escape($this->fk_facture_source) :
"null").
",";
2526 $sql .=
" fk_projet=".(isset($this->fk_project) ? $this->db->escape($this->fk_project) :
"null").
",";
2527 $sql .=
" fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->db->escape($this->cond_reglement_id) :
"null").
",";
2528 $sql .=
" fk_mode_reglement=".(isset($this->mode_reglement_id) ? $this->db->escape($this->mode_reglement_id) :
"null").
",";
2529 $sql .=
" date_lim_reglement=".(strval($this->date_lim_reglement) !=
'' ?
"'".$this->db->idate($this->date_lim_reglement).
"'" :
'null').
",";
2530 $sql .=
" note_private=".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
2531 $sql .=
" note_public=".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
2532 $sql .=
" model_pdf=".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
2533 $sql .=
" import_key=".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null").
",";
2534 $sql .=
" situation_cycle_ref=".(empty($this->situation_cycle_ref) ?
"null" : $this->db->escape($this->situation_cycle_ref)).
",";
2535 $sql .=
" situation_counter=".(empty($this->situation_counter) ?
"null" : $this->db->escape($this->situation_counter)).
",";
2536 $sql .=
" situation_final=".(empty($this->situation_final) ?
"0" : $this->db->escape($this->situation_final)).
",";
2537 $sql .=
" retained_warranty=".(empty($this->retained_warranty) ?
"0" : $this->db->escape($this->retained_warranty)).
",";
2538 $sql .=
" retained_warranty_date_limit=".(strval($this->retained_warranty_date_limit) !=
'' ?
"'".$this->db->idate($this->retained_warranty_date_limit).
"'" :
'null').
",";
2539 $sql .=
" retained_warranty_fk_cond_reglement=".(isset($this->retained_warranty_fk_cond_reglement) ? intval($this->retained_warranty_fk_cond_reglement) :
"null");
2540 $sql .=
" WHERE rowid=".((int) $this->
id);
2544 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
2545 $resql = $this->db->query($sql);
2548 $this->errors[] =
"Error ".$this->db->lasterror();
2558 if (!$error && !$notrigger) {
2569 foreach ($this->errors as $errmsg) {
2570 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
2571 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2573 $this->db->rollback();
2576 $this->db->commit();
2592 global $conf, $langs;
2594 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
2595 include_once DOL_DOCUMENT_ROOT.
'/core/class/discount.class.php';
2600 $result = $remise->fetch($idremise);
2603 if ($remise->fk_facture) {
2604 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed");
2605 $this->db->rollback();
2610 $facligne->fk_facture = $this->id;
2611 $facligne->fk_remise_except = $remise->id;
2612 $facligne->desc = $remise->description;
2613 $facligne->vat_src_code = $remise->vat_src_code;
2614 $facligne->tva_tx = $remise->tva_tx;
2615 $facligne->subprice = -$remise->amount_ht;
2616 $facligne->fk_product = 0;
2618 $facligne->remise_percent = 0;
2619 $facligne->rang = -1;
2620 $facligne->info_bits = 2;
2623 $facligne->rang = 1;
2624 $linecount = count($this->lines);
2625 for ($ii = 1; $ii <= $linecount; $ii++) {
2631 if ($remise->fk_facture_source > 0) {
2632 $srcinvoice =
new Facture($this->db);
2633 $srcinvoice->fetch($remise->fk_facture_source);
2634 include_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmargin.class.php';
2636 $arraytmp = $formmargin->getMarginInfosArray($srcinvoice,
false);
2637 $facligne->pa_ht = $arraytmp[
'pa_total'];
2640 $facligne->total_ht = -$remise->amount_ht;
2641 $facligne->total_tva = -$remise->amount_tva;
2642 $facligne->total_ttc = -$remise->amount_ttc;
2644 $facligne->multicurrency_subprice = -$remise->multicurrency_subprice;
2645 $facligne->multicurrency_total_ht = -$remise->multicurrency_amount_ht;
2646 $facligne->multicurrency_total_tva = -$remise->multicurrency_amount_tva;
2647 $facligne->multicurrency_total_ttc = -$remise->multicurrency_amount_ttc;
2649 $lineid = $facligne->insert();
2654 $result = $remise->link_to_invoice($lineid, 0);
2656 $this->error = $remise->error;
2657 $this->db->rollback();
2661 $this->db->commit();
2664 $this->error = $facligne->error;
2665 $this->db->rollback();
2669 $this->error = $facligne->error;
2670 $this->db->rollback();
2674 $this->db->rollback();
2696 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
2697 if (empty($ref_client)) {
2698 $sql .=
' SET ref_client = NULL';
2700 $sql .=
' SET ref_client = \''.$this->db->escape($ref_client).
'\'';
2702 $sql .=
" WHERE rowid = ".((int) $this->
id);
2704 dol_syslog(__METHOD__.
' this->id='.$this->id.
', ref_client='.$ref_client, LOG_DEBUG);
2705 $resql = $this->db->query($sql);
2707 $this->errors[] = $this->db->error();
2712 $this->ref_client = $ref_client;
2715 if (!$notrigger && empty($error)) {
2725 $this->ref_client = $ref_client;
2727 $this->db->commit();
2730 foreach ($this->errors as $errmsg) {
2731 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2732 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2734 $this->db->rollback();
2747 public function delete($user, $notrigger = 0, $idwarehouse = -1)
2749 global $langs, $conf;
2750 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
2754 dol_syslog(get_class($this).
"::delete rowid=".$rowid.
", ref=".$this->ref.
", thirdparty=".(empty($this->thirdparty) ?
'' : $this->thirdparty->name), LOG_DEBUG);
2767 if (!$error && !$notrigger) {
2781 dol_syslog(get_class($this).
"::delete error deleteExtraFields ".$this->error, LOG_ERR);
2795 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'societe_remise_except';
2796 $sql .=
' WHERE fk_facture_source = '.((int) $rowid);
2797 $sql .=
' AND fk_facture_line IS NULL';
2798 $resql = $this->db->query($sql);
2802 $list_rowid_det = array();
2803 foreach ($this->lines as $key => $invoiceline) {
2804 $list_rowid_det[] = $invoiceline->id;
2808 if (count($list_rowid_det)) {
2809 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
2810 $sql .=
' SET fk_facture = NULL, fk_facture_line = NULL';
2811 $sql .=
' WHERE fk_facture_line IN ('.$this->db->sanitize(join(
',', $list_rowid_det)).
')';
2813 if (!$this->db->query($sql)) {
2814 $this->error = $this->db->error().
" sql=".$sql;
2815 $this->errors[] = $this->error;
2816 $this->db->rollback();
2823 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'eventorganization_conferenceorboothattendee';
2824 $sql .=
' SET fk_invoice = NULL';
2825 $sql .=
' WHERE fk_invoice = '.((int) $rowid);
2827 if (!$this->db->query($sql)) {
2828 $this->error = $this->db->error().
" sql=".$sql;
2829 $this->errors[] = $this->error;
2830 $this->db->rollback();
2834 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'element_time';
2835 $sql .=
' SET invoice_id = NULL, invoice_line_id = NULL';
2836 $sql .=
' WHERE invoice_id = '.((int) $rowid);
2838 if (!$this->db->query($sql)) {
2839 $this->error = $this->db->error().
" sql=".$sql;
2840 $this->errors[] = $this->error;
2841 $this->db->rollback();
2846 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL') && $idwarehouse != -1) {
2847 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
2848 $langs->load(
"agenda");
2850 $num = count($this->lines);
2851 for ($i = 0; $i < $num; $i++) {
2852 if ($this->lines[$i]->fk_product > 0) {
2854 $mouvP->origin = &$this;
2855 $mouvP->setOrigin($this->element, $this->
id);
2857 if ($this->
type == self::TYPE_CREDIT_NOTE) {
2858 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceDeleteDolibarr", $this->ref));
2860 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceDeleteDolibarr", $this->ref));
2867 $main = MAIN_DB_PREFIX.
'facturedet';
2868 $ef = $main.
"_extrafields";
2869 $sqlef =
"DELETE FROM ".$ef.
" WHERE fk_object IN (SELECT rowid FROM ".$main.
" WHERE fk_facture = ".((int) $rowid).
")";
2871 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'facturedet WHERE fk_facture = '.((int) $rowid);
2874 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'facture WHERE rowid = '.((int) $rowid);
2876 $resql = $this->db->query($sql);
2884 if ($conf->facture->dir_output && !empty($this->
ref)) {
2885 $dir = $conf->facture->dir_output.
"/".$ref;
2886 $file = $conf->facture->dir_output.
"/".$ref.
"/".$ref.
".pdf";
2887 if (file_exists($file)) {
2891 $langs->load(
"errors");
2892 $this->error = $langs->trans(
"ErrorFailToDeleteFile", $file);
2893 $this->errors[] = $this->error;
2894 $this->db->rollback();
2898 if (file_exists($dir)) {
2900 $langs->load(
"errors");
2901 $this->error = $langs->trans(
"ErrorFailToDeleteDir", $dir);
2902 $this->errors[] = $this->error;
2903 $this->db->rollback();
2909 $this->db->commit();
2912 $this->error = $this->db->lasterror().
" sql=".$sql;
2913 $this->errors[] = $this->error;
2914 $this->db->rollback();
2918 $this->error = $this->db->lasterror().
" sql=".$sql;
2919 $this->errors[] = $this->error;
2920 $this->db->rollback();
2924 $this->db->rollback();
2941 public function set_paid($user, $close_code =
'', $close_note =
'')
2944 dol_syslog(get_class($this).
"::set_paid is deprecated, use setPaid instead", LOG_NOTICE);
2945 return $this->
setPaid($user, $close_code, $close_note);
2958 public function setPaid($user, $close_code =
'', $close_note =
'')
2962 if ($this->paye != 1) {
2967 dol_syslog(get_class($this).
"::setPaid rowid=".((
int) $this->
id), LOG_DEBUG);
2969 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET';
2970 $sql .=
' fk_statut='.self::STATUS_CLOSED;
2975 $sql .=
", close_code='".$this->db->escape($close_code).
"'";
2978 $sql .=
", close_note='".$this->db->escape($close_note).
"'";
2980 $sql .=
', fk_user_closing = '.((int) $user->id);
2981 $sql .=
", date_closing = '".$this->db->idate($now).
"'";
2982 $sql .=
" WHERE rowid = ".((int) $this->
id);
2984 $resql = $this->db->query($sql);
2994 $this->error = $this->db->lasterror();
2998 $this->db->commit();
3001 $this->db->rollback();
3024 dol_syslog(get_class($this).
"::set_unpaid is deprecated, use setUnpaid instead", LOG_NOTICE);
3042 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
3043 $sql .=
' SET paye=0, fk_statut='.self::STATUS_VALIDATED.
', close_code=null, close_note=null,';
3044 $sql .=
' date_closing=null,';
3045 $sql .=
' fk_user_closing=null';
3046 $sql .=
" WHERE rowid = ".((int) $this->
id);
3048 dol_syslog(get_class($this).
"::setUnpaid", LOG_DEBUG);
3049 $resql = $this->db->query($sql);
3059 $this->error = $this->db->error();
3064 $this->db->commit();
3067 $this->db->rollback();
3089 dol_syslog(get_class($this).
"::set_canceled is deprecated, use setCanceled instead", LOG_NOTICE);
3090 return $this->
setCanceled($user, $close_code, $close_note);
3103 public function setCanceled($user, $close_code =
'', $close_note =
'')
3105 dol_syslog(get_class($this).
"::setCanceled rowid=".((
int) $this->
id), LOG_DEBUG);
3110 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET';
3111 $sql .=
' fk_statut='.self::STATUS_ABANDONED;
3113 $sql .=
", close_code='".$this->db->escape($close_code).
"'";
3116 $sql .=
", close_note='".$this->db->escape($close_note).
"'";
3118 $sql .=
', fk_user_closing = '.((int) $user->id);
3119 $sql .=
", date_closing = '".$this->db->idate($now).
"'";
3120 $sql .=
" WHERE rowid = ".((int) $this->
id);
3122 $resql = $this->db->query($sql);
3126 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
3127 $sql .=
' SET fk_facture = NULL';
3128 $sql .=
' WHERE fk_facture = '.((int) $this->
id);
3130 $resql = $this->db->query($sql);
3135 $this->db->rollback();
3140 $this->db->commit();
3143 $this->error = $this->db->error().
" sql=".$sql;
3144 $this->db->rollback();
3148 $this->error = $this->db->error().
" sql=".$sql;
3149 $this->db->rollback();
3165 public function validate($user, $force_number =
'', $idwarehouse = 0, $notrigger = 0, $batch_rule = 0)
3167 global $conf, $langs, $mysoc;
3168 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
3170 $productStatic =
null;
3171 $warehouseStatic =
null;
3172 if ($batch_rule > 0) {
3173 require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
3174 require_once DOL_DOCUMENT_ROOT.
'/product/class/productbatch.class.php';
3175 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
3176 $productStatic =
new Product($this->db);
3177 $warehouseStatic =
new Entrepot($this->db);
3184 dol_syslog(get_class($this).
'::validate user='.$user->id.
', force_number='.$force_number.
', idwarehouse='.$idwarehouse);
3191 if ($this->
status != self::STATUS_DRAFT) {
3192 dol_syslog(get_class($this).
"::validate Current status is not draft. operation canceled.", LOG_WARNING);
3195 if (count($this->lines) <= 0) {
3196 $langs->load(
"errors");
3197 $this->error = $langs->trans(
"ErrorObjectMustHaveLinesToBeValidated", $this->
ref);
3201 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && !$user->hasRight(
'facture',
'invoice_advance',
'validate'))) {
3202 $this->error =
'Permission denied';
3203 dol_syslog(get_class($this).
"::validate ".$this->error.
' MAIN_USE_ADVANCED_PERMS=' .
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS'), LOG_ERR);
3206 if ((preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) &&
3214 if (!$last_of_type[0]) {
3215 $this->error = $langs->transnoentities(
"ErrorInvoiceIsNotLastOfSameType", $this->
ref,
dol_print_date($this->date,
'day'),
dol_print_date($last_of_type[1],
'day'));
3221 if (!empty($this->thirdparty) && is_object($this->thirdparty)) {
3222 $array_to_check = array(
'IDPROF1',
'IDPROF2',
'IDPROF3',
'IDPROF4',
'IDPROF5',
'IDPROF6',
'EMAIL',
'ACCOUNTANCY_CODE_CUSTOMER');
3223 foreach ($array_to_check as $key) {
3224 $keymin = strtolower($key);
3225 if (!property_exists($this->thirdparty, $keymin)) {
3228 $vallabel = $this->thirdparty->$keymin;
3230 $i = (int) preg_replace(
'/[^0-9]/',
'', $key);
3232 if ($this->thirdparty->isACompany()) {
3234 if ($mysoc->country_id > 0 && $this->thirdparty->country_id == $mysoc->country_id) {
3235 $idprof_mandatory =
'SOCIETE_'.$key.
'_INVOICE_MANDATORY';
3236 if (!$vallabel && !empty($conf->global->$idprof_mandatory)) {
3237 $langs->load(
"errors");
3238 $this->error = $langs->trans(
'ErrorProdIdIsMandatory', $langs->transcountry(
'ProfId'.$i, $this->thirdparty->country_code)).
' ('.$langs->trans(
"ForbiddenBySetupRules").
') ['.$langs->trans(
'Company').
' : '.$this->thirdparty->name.
']';
3239 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3245 if ($key ==
'EMAIL') {
3247 if (
getDolGlobalString(
'SOCIETE_EMAIL_INVOICE_MANDATORY') && !isValidEMail($this->thirdparty->email)) {
3248 $langs->load(
"errors");
3249 $this->error = $langs->trans(
"ErrorBadEMail", $this->thirdparty->email).
' ('.$langs->trans(
"ForbiddenBySetupRules").
') ['.$langs->trans(
'Company').
' : '.$this->thirdparty->name.
']';
3250 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3254 if ($key ==
'ACCOUNTANCY_CODE_CUSTOMER') {
3256 if (
getDolGlobalString(
'SOCIETE_ACCOUNTANCY_CODE_CUSTOMER_INVOICE_MANDATORY') && empty($this->thirdparty->code_compta)) {
3257 $langs->load(
"errors");
3258 $this->error = $langs->trans(
"ErrorAccountancyCodeCustomerIsMandatory", $this->thirdparty->name).
' ('.$langs->trans(
"ForbiddenBySetupRules").
')';
3259 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3268 $array_to_check = array(
'REF_CLIENT'=>
'RefCustomer');
3269 foreach ($array_to_check as $key => $val) {
3270 $keymin = strtolower($key);
3271 $vallabel = $this->$keymin;
3274 $keymandatory =
'INVOICE_'.$key.
'_MANDATORY_FOR_VALIDATION';
3276 $langs->load(
"errors");
3278 setEventMessages($langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv($val)),
null,
'errors');
3285 if ($this->
type == self::TYPE_REPLACEMENT) {
3287 if ($this->fk_facture_source <= 0) {
3288 $this->error = $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"InvoiceReplacement"));
3289 $this->db->rollback();
3294 $facreplaced =
new Facture($this->db);
3295 $result = $facreplaced->fetch($this->fk_facture_source);
3297 $this->error = $langs->trans(
"ErrorBadInvoice");
3298 $this->db->rollback();
3303 $idreplacement = $facreplaced->getIdReplacingInvoice(
'validated');
3304 if ($idreplacement && $idreplacement != $this->
id) {
3305 $facreplacement =
new Facture($this->db);
3306 $facreplacement->fetch($idreplacement);
3307 $this->error = $langs->trans(
"ErrorInvoiceAlreadyReplaced", $facreplaced->ref, $facreplacement->ref);
3308 $this->db->rollback();
3312 $result = $facreplaced->setCanceled($user, self::CLOSECODE_REPLACED,
'');
3314 $this->error = $facreplaced->error;
3315 $this->db->rollback();
3321 if ($force_number) {
3322 $num = $force_number;
3323 } elseif (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
3339 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
3340 $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).
"'";
3342 $sql .=
", datef='".$this->db->idate($this->date).
"'";
3343 $sql .=
", date_lim_reglement='".$this->db->idate($this->date_lim_reglement).
"'";
3345 $sql .=
" WHERE rowid = ".((int) $this->
id);
3347 dol_syslog(get_class($this).
"::validate", LOG_DEBUG);
3348 $resql = $this->db->query($sql);
3355 if (!$error && (preg_match(
'/^[\(]?PROV/i', $this->
ref))) {
3361 $result = $this->thirdparty->setAsCustomer();
3364 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL') && $idwarehouse > 0) {
3365 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3366 $langs->load(
"agenda");
3369 $cpt = count($this->lines);
3370 for ($i = 0; $i < $cpt; $i++) {
3371 if ($this->lines[$i]->fk_product > 0) {
3373 $mouvP->origin = &$this;
3374 $mouvP->setOrigin($this->element, $this->
id);
3380 if ($this->
type == self::TYPE_CREDIT_NOTE) {
3381 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceValidatedInDolibarr", $num));
3384 $this->error = $mouvP->error;
3387 $is_batch_line =
false;
3388 if ($batch_rule > 0) {
3389 $productStatic->fetch($this->lines[$i]->fk_product);
3390 if ($productStatic->hasbatch()) {
3391 $is_batch_line =
true;
3392 $product_qty_remain = $this->lines[$i]->qty;
3398 $sortfield =
'pl.sellby,pl.eatby,pb.qty,pl.rowid';
3399 $sortorder =
'ASC,ASC,ASC,ASC';
3402 $resBatchList = $productbatch->findAllForProduct($productStatic->id, $idwarehouse, (
getDolGlobalInt(
'STOCK_ALLOW_NEGATIVE_TRANSFER') ?
null : 0), $sortfield, $sortorder);
3403 if (!is_array($resBatchList)) {
3405 $this->error = $this->db->lasterror();
3409 $batchList = $resBatchList;
3410 if (empty($batchList)) {
3412 $langs->load(
'errors');
3413 $warehouseStatic->fetch($idwarehouse);
3414 $this->error = $langs->trans(
'ErrorBatchNoFoundForProductInWarehouse', $productStatic->label, $warehouseStatic->ref);
3415 dol_syslog(__METHOD__.
' Error: '.$langs->transnoentitiesnoconv(
'ErrorBatchNoFoundForProductInWarehouse', $productStatic->label, $warehouseStatic->ref), LOG_ERR);
3418 foreach ($batchList as $batch) {
3419 if ($batch->qty <= 0) {
3424 if ($batch->qty >= $product_qty_remain) {
3425 $product_batch_qty = $product_qty_remain;
3428 $product_batch_qty = $batch->qty;
3430 $result = $mouvP->livraison($user, $productStatic->id, $idwarehouse, $product_batch_qty, $this->lines[$i]->subprice, $langs->trans(
'InvoiceValidatedInDolibarr', $num),
'',
'',
'', $batch->batch);
3433 $this->error = $mouvP->error;
3434 $this->errors = $mouvP->errors;
3438 $product_qty_remain -= $product_batch_qty;
3440 if ($product_qty_remain <= 0) {
3445 if (!$error && $product_qty_remain > 0) {
3448 $batch = $batchList[0];
3449 $result = $mouvP->livraison($user, $productStatic->id, $idwarehouse, $product_qty_remain, $this->lines[$i]->subprice, $langs->trans(
'InvoiceValidatedInDolibarr', $num),
'',
'',
'', $batch->batch);
3452 $this->error = $mouvP->error;
3453 $this->errors = $mouvP->errors;
3457 $langs->load(
'errors');
3458 $warehouseStatic->fetch($idwarehouse);
3459 $this->error = $langs->trans(
'ErrorBatchNoFoundEnoughQuantityForProductInWarehouse', $productStatic->label, $warehouseStatic->ref);
3460 dol_syslog(__METHOD__.
' Error: '.$langs->transnoentitiesnoconv(
'ErrorBatchNoFoundEnoughQuantityForProductInWarehouse', $productStatic->label, $warehouseStatic->ref), LOG_ERR);
3467 if (!$is_batch_line) {
3468 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceValidatedInDolibarr", $num));
3471 $this->error = $mouvP->error;
3472 $this->errors = $mouvP->errors;
3485 if (!$error && $this->
type == self::TYPE_CREDIT_NOTE && $this->fk_facture_source > 0) {
3486 $invoice_situation =
new Facture($this->db);
3487 $result = $invoice_situation->fetch($this->fk_facture_source);
3488 if ($result > 0 && $invoice_situation->type == self::TYPE_SITUATION && $invoice_situation->situation_final == 1) {
3489 $invoice_situation->situation_final = 0;
3491 $result = $invoice_situation->setFinal($user, 1);
3494 $this->error = $invoice_situation->error;
3495 $this->errors = $invoice_situation->errors;
3501 if (!$error && !$notrigger) {
3511 $this->oldref = $this->ref;
3514 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
3516 $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).
"'";
3517 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'facture/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
3518 $resql = $this->db->query($sql);
3521 $this->error = $this->db->lasterror();
3523 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'facture/".$this->db->escape($this->newref).
"'";
3524 $sql .=
" WHERE filepath = 'facture/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
3525 $resql = $this->db->query($sql);
3528 $this->error = $this->db->lasterror();
3534 $dirsource = $conf->facture->dir_output.
'/'.$oldref;
3535 $dirdest = $conf->facture->dir_output.
'/'.$newref;
3536 if (!$error && file_exists($dirsource)) {
3537 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
3539 if (@rename($dirsource, $dirdest)) {
3542 $listoffiles =
dol_dir_list($conf->facture->dir_output.
'/'.$newref,
'files', 1,
'^'.preg_quote($oldref,
'/'));
3543 foreach ($listoffiles as $fileentry) {
3544 $dirsource = $fileentry[
'name'];
3545 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
3546 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
3547 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
3548 @rename($dirsource, $dirdest);
3566 $this->date_validation = $now;
3571 $nboflines = count($this->lines);
3572 while (($i < $nboflines) && $final) {
3573 $final = ($this->lines[$i]->situation_percent == 100);
3577 if (empty($final)) {
3578 $this->situation_final = 0;
3580 $this->situation_final = 1;
3591 $this->db->commit();
3594 $this->db->rollback();
3607 foreach ($this->tab_next_situation_invoice as $next_invoice) {
3608 $is_last = $next_invoice->is_last_in_cycle();
3610 if ($next_invoice->status == self::STATUS_DRAFT && $is_last != 1) {
3611 $this->error = $langs->trans(
'updatePriceNextInvoiceErrorUpdateline', $next_invoice->ref);
3615 foreach ($next_invoice->lines as $line) {
3616 $result = $next_invoice->updateline(
3621 $line->remise_percent,
3625 $line->localtax1_tx,
3626 $line->localtax2_tx,
3629 $line->product_type,
3630 $line->fk_parent_line,
3632 $line->fk_fournprice,
3635 $line->special_code,
3636 $line->array_options,
3637 $line->situation_percent,
3642 $this->error = $langs->trans(
'updatePriceNextInvoiceErrorUpdateline', $next_invoice->ref);
3663 global $conf, $langs;
3667 if ($this->
status == self::STATUS_DRAFT) {
3668 dol_syslog(__METHOD__.
" already draft status", LOG_WARNING);
3676 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facture";
3677 $sql .=
" SET fk_statut = ".self::STATUS_DRAFT;
3678 $sql .=
" WHERE rowid = ".((int) $this->
id);
3680 $result = $this->db->query($sql);
3683 $this->oldcopy = clone $this;
3687 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL')) {
3688 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3689 $langs->load(
"agenda");
3691 $num = count($this->lines);
3692 for ($i = 0; $i < $num; $i++) {
3693 if ($this->lines[$i]->fk_product > 0) {
3695 $mouvP->origin = &$this;
3696 $mouvP->setOrigin($this->element, $this->
id);
3698 if ($this->
type == self::TYPE_CREDIT_NOTE) {
3699 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceBackToDraftInDolibarr", $this->ref));
3701 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceBackToDraftInDolibarr", $this->ref));
3708 $old_statut = $this->status;
3713 $result = $this->
call_trigger(
'BILL_UNVALIDATE', $user);
3716 $this->
statut = $old_statut;
3717 $this->
status = $old_statut;
3721 $this->db->rollback();
3726 $this->db->commit();
3729 $this->db->rollback();
3733 $this->error = $this->db->error();
3734 $this->db->rollback();
3789 $remise_percent = 0,
3794 $fk_remise_except = 0,
3795 $price_base_type =
'HT',
3802 $fk_parent_line = 0,
3803 $fk_fournprice =
null,
3806 $array_options = array(),
3807 $situation_percent = 100,
3812 $noupdateafterinsertline = 0
3816 dol_syslog(__METHOD__.
": using line label is deprecated", LOG_WARNING);
3820 global $mysoc, $conf, $langs;
3822 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);
3824 if ($this->
status == self::STATUS_DRAFT) {
3825 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
3828 if (empty($remise_percent)) {
3829 $remise_percent = 0;
3834 if (empty($info_bits)) {
3840 if (empty($ventil)) {
3843 if (empty($txtva)) {
3846 if (empty($txlocaltax1)) {
3849 if (empty($txlocaltax2)) {
3852 if (empty($fk_parent_line) || $fk_parent_line < 0) {
3853 $fk_parent_line = 0;
3855 if (empty($fk_prev_id)) {
3856 $fk_prev_id =
'null';
3858 if (!isset($situation_percent) || $situation_percent > 100 || (
string) $situation_percent ==
'') {
3859 $situation_percent = 100;
3861 if (empty($ref_ext)) {
3865 $remise_percent =
price2num($remise_percent);
3868 $pu_ht_devise =
price2num($pu_ht_devise);
3871 if (!preg_match(
'/\((.*)\)/', $txtva)) {
3877 if ($price_base_type ==
'HT') {
3888 if ($date_start && $date_end && $date_start > $date_end) {
3889 $langs->load(
"errors");
3890 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
3896 $product_type = $type;
3897 if (!empty($fk_product) && $fk_product > 0) {
3898 $product =
new Product($this->db);
3899 $result = $product->fetch($fk_product);
3900 $product_type = $product->type;
3902 if (
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_INVOICE') && $product_type == 0 && $product->stock_reel < $qty) {
3903 $langs->load(
"errors");
3904 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnInvoice', $product->ref);
3905 $this->db->rollback();
3915 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
3916 $vat_src_code = $reg[1];
3917 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
3925 $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);
3927 $total_ht = $tabprice[0];
3928 $total_tva = $tabprice[1];
3929 $total_ttc = $tabprice[2];
3930 $total_localtax1 = $tabprice[9];
3931 $total_localtax2 = $tabprice[10];
3932 $pu_ht = $tabprice[3];
3935 $multicurrency_total_ht = $tabprice[16];
3936 $multicurrency_total_tva = $tabprice[17];
3937 $multicurrency_total_ttc = $tabprice[18];
3938 $pu_ht_devise = $tabprice[19];
3942 if ($ranktouse == -1) {
3943 $rangmax = $this->
line_max($fk_parent_line);
3944 $ranktouse = $rangmax + 1;
3950 $this->line->context = $this->context;
3952 $this->line->fk_facture = $this->id;
3953 $this->line->label = $label;
3954 $this->line->desc = $desc;
3955 $this->line->ref_ext = $ref_ext;
3957 $this->line->qty = ($this->
type == self::TYPE_CREDIT_NOTE ? abs($qty) : $qty);
3958 $this->line->subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht) : $pu_ht);
3960 $this->line->vat_src_code = $vat_src_code;
3961 $this->line->tva_tx = $txtva;
3962 $this->line->localtax1_tx = ($total_localtax1 ? $localtaxes_type[1] : 0);
3963 $this->line->localtax2_tx = ($total_localtax2 ? $localtaxes_type[3] : 0);
3964 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
3965 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
3967 $this->line->total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ht) : $total_ht);
3968 $this->line->total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ttc) : $total_ttc);
3969 $this->line->total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_tva) : $total_tva);
3970 $this->line->total_localtax1 = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_localtax1) : $total_localtax1);
3971 $this->line->total_localtax2 = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_localtax2) : $total_localtax2);
3973 $this->line->fk_product = $fk_product;
3974 $this->line->product_type = $product_type;
3975 $this->line->remise_percent = $remise_percent;
3976 $this->line->date_start = $date_start;
3977 $this->line->date_end = $date_end;
3978 $this->line->ventil = $ventil;
3979 $this->line->rang = $ranktouse;
3980 $this->line->info_bits = $info_bits;
3981 $this->line->fk_remise_except = $fk_remise_except;
3983 $this->line->special_code = $special_code;
3984 $this->line->fk_parent_line = $fk_parent_line;
3985 $this->line->origin = $origin;
3986 $this->line->origin_id = $origin_id;
3987 $this->line->situation_percent = $situation_percent;
3988 $this->line->fk_prev_id = $fk_prev_id;
3989 $this->line->fk_unit = $fk_unit;
3992 $this->line->fk_fournprice = $fk_fournprice;
3993 $this->line->pa_ht = $pa_ht;
3996 $this->line->fk_multicurrency = $this->fk_multicurrency;
3997 $this->line->multicurrency_code = $this->multicurrency_code;
3998 $this->line->multicurrency_subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht_devise) : $pu_ht_devise);
4000 $this->line->multicurrency_total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ht) : $multicurrency_total_ht);
4001 $this->line->multicurrency_total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_tva) : $multicurrency_total_tva);
4002 $this->line->multicurrency_total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ttc) : $multicurrency_total_ttc);
4004 if (is_array($array_options) && count($array_options) > 0) {
4005 $this->line->array_options = $array_options;
4008 $result = $this->line->insert();
4011 if (!empty($fk_parent_line)) {
4013 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
4014 $linecount = count($this->lines);
4015 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
4021 if (empty($noupdateafterinsertline)) {
4026 $this->db->commit();
4027 return $this->line->id;
4029 $this->error = $this->db->lasterror();
4030 $this->db->rollback();
4034 $this->error = $this->line->error;
4035 $this->errors = $this->line->errors;
4036 $this->db->rollback();
4040 $this->errors[] =
'status of invoice must be Draft to allow use of ->addline()';
4041 dol_syslog(get_class($this).
"::addline status of invoice must be Draft to allow use of ->addline()", LOG_ERR);
4077 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)
4079 global $conf, $user;
4082 dol_syslog(__METHOD__.
": using line label is deprecated", LOG_WARNING);
4085 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
4087 global $mysoc, $langs;
4089 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);
4091 if ($this->
status == self::STATUS_DRAFT) {
4094 if (!$this->error) {
4095 $this->error = $langs->trans(
'invoiceLineProgressError');
4101 if ($date_start && $date_end && $date_start > $date_end) {
4102 $langs->load(
"errors");
4103 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
4113 if (empty($fk_parent_line) || $fk_parent_line < 0) {
4114 $fk_parent_line = 0;
4116 if (empty($special_code) || $special_code == 3) {
4119 if (!isset($situation_percent) || $situation_percent > 100 || (
string) $situation_percent ==
'') {
4120 $situation_percent = 100;
4122 if (empty($ref_ext)) {
4126 $remise_percent =
price2num($remise_percent);
4129 $pu_ht_devise =
price2num($pu_ht_devise);
4131 if (!preg_match(
'/\((.*)\)/', $txtva)) {
4151 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
4152 $vat_src_code = $reg[1];
4153 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
4156 $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);
4158 $total_ht = $tabprice[0];
4159 $total_tva = $tabprice[1];
4160 $total_ttc = $tabprice[2];
4161 $total_localtax1 = $tabprice[9];
4162 $total_localtax2 = $tabprice[10];
4163 $pu_ht = $tabprice[3];
4164 $pu_tva = $tabprice[4];
4165 $pu_ttc = $tabprice[5];
4168 $multicurrency_total_ht = $tabprice[16];
4169 $multicurrency_total_tva = $tabprice[17];
4170 $multicurrency_total_ttc = $tabprice[18];
4171 $pu_ht_devise = $tabprice[19];
4176 if ($remise_percent > 0) {
4177 $remise = round(((
float) $pu * (
float) $remise_percent / 100), 2);
4178 $price = ((float) $pu - $remise);
4184 $line->fetch($rowid);
4185 $line->fetch_optionals();
4187 if (!empty($line->fk_product)) {
4188 $product =
new Product($this->db);
4189 $result = $product->fetch($line->fk_product);
4190 $product_type = $product->type;
4192 if (
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_INVOICE') && $product_type == 0 && $product->stock_reel < $qty) {
4193 $langs->load(
"errors");
4194 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnInvoice', $product->ref);
4195 $this->db->rollback();
4200 $staticline = clone $line;
4202 $line->oldline = $staticline;
4203 $this->line = $line;
4204 $this->line->context = $this->context;
4205 $this->line->rang = $rang;
4208 if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
4209 $rangmax = $this->
line_max($fk_parent_line);
4210 $this->line->rang = $rangmax + 1;
4213 $this->line->id = $rowid;
4214 $this->line->rowid = $rowid;
4215 $this->line->label = $label;
4216 $this->line->desc = $desc;
4217 $this->line->ref_ext = $ref_ext;
4218 $this->line->qty = ($this->
type == self::TYPE_CREDIT_NOTE ? abs($qty) : $qty);
4220 $this->line->vat_src_code = $vat_src_code;
4221 $this->line->tva_tx = $txtva;
4222 $this->line->localtax1_tx = $txlocaltax1;
4223 $this->line->localtax2_tx = $txlocaltax2;
4224 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
4225 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
4227 $this->line->remise_percent = $remise_percent;
4228 $this->line->subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht) : $pu_ht);
4229 $this->line->date_start = $date_start;
4230 $this->line->date_end = $date_end;
4231 $this->line->total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ht) : $total_ht);
4232 $this->line->total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_tva) : $total_tva);
4233 $this->line->total_localtax1 = $total_localtax1;
4234 $this->line->total_localtax2 = $total_localtax2;
4235 $this->line->total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ttc) : $total_ttc);
4236 $this->line->info_bits = $info_bits;
4237 $this->line->special_code = $special_code;
4238 $this->line->product_type = $type;
4239 $this->line->fk_parent_line = $fk_parent_line;
4240 $this->line->skip_update_total = $skip_update_total;
4241 $this->line->situation_percent = $situation_percent;
4242 $this->line->fk_unit = $fk_unit;
4244 $this->line->fk_fournprice = $fk_fournprice;
4245 $this->line->pa_ht = $pa_ht;
4248 $this->line->multicurrency_subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht_devise) : $pu_ht_devise);
4249 $this->line->multicurrency_total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ht) : $multicurrency_total_ht);
4250 $this->line->multicurrency_total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_tva) : $multicurrency_total_tva);
4251 $this->line->multicurrency_total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ttc) : $multicurrency_total_ttc);
4253 if (is_array($array_options) && count($array_options) > 0) {
4255 foreach ($array_options as $key => $value) {
4256 $this->line->array_options[$key] = $array_options[$key];
4260 $result = $this->line->update($user, $notrigger);
4263 if (!empty($fk_parent_line)) {
4269 $this->db->commit();
4272 $this->error = $this->line->error;
4273 $this->db->rollback();
4277 $this->error =
"Invoice statut makes operation forbidden";
4291 $sql =
'SELECT fd.situation_percent FROM '.MAIN_DB_PREFIX.
'facturedet fd
4292 INNER JOIN '.MAIN_DB_PREFIX.
'facture f ON (fd.fk_facture = f.rowid)
4293 WHERE fd.fk_prev_id = '.((int) $idline).
' AND f.fk_statut <> 0';
4295 $result = $this->db->query($sql);
4297 $this->error = $this->db->error();
4301 $obj = $this->db->fetch_object($result);
4303 if ($obj ===
null) {
4306 return ($situation_percent < $obj->situation_percent);
4322 global $mysoc, $user;
4325 if (($line->info_bits & 2) == 2) {
4329 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
4332 if ($percent > 100) {
4335 $line->situation_percent = $percent;
4336 $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);
4337 $line->total_ht = $tabprice[0];
4338 $line->total_tva = $tabprice[1];
4339 $line->total_ttc = $tabprice[2];
4340 $line->total_localtax1 = $tabprice[9];
4341 $line->total_localtax2 = $tabprice[10];
4342 $line->multicurrency_total_ht = $tabprice[16];
4343 $line->multicurrency_total_tva = $tabprice[17];
4344 $line->multicurrency_total_ttc = $tabprice[18];
4345 $line->update($user);
4348 if ($update_price) {
4364 dol_syslog(get_class($this).
"::deleteline rowid=".((
int) $rowid), LOG_DEBUG);
4366 if ($this->
status != self::STATUS_DRAFT) {
4367 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
4373 $line->context = $this->context;
4376 $result = $line->fetch($rowid);
4377 if (!($result > 0)) {
4382 if ($id > 0 && $line->fk_facture != $id) {
4383 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
4390 $staticline = clone $line;
4391 $line->oldline = $staticline;
4393 if ($line->delete($user) > 0) {
4397 $this->db->commit();
4400 $this->db->rollback();
4401 $this->error = $this->db->lasterror();
4405 $this->db->rollback();
4406 $this->error = $line->error;
4425 dol_syslog(get_class($this).
"::set_remise is deprecated, use setDiscount instead", LOG_NOTICE);
4426 return $this->
setDiscount($user, $remise, $notrigger);
4441 if (empty($remise)) {
4445 if ($user->hasRight(
'facture',
'creer')) {
4452 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
4453 $sql .=
' SET remise_percent = '.((float) $remise);
4454 $sql .=
" WHERE rowid = ".((int) $this->
id);
4455 $sql .=
' AND fk_statut = '.self::STATUS_DRAFT;
4458 $resql = $this->db->query($sql);
4460 $this->errors[] = $this->db->error();
4464 if (!$notrigger && empty($error)) {
4474 $this->remise_percent = $remise;
4477 $this->db->commit();
4480 foreach ($this->errors as $errmsg) {
4481 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
4482 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
4484 $this->db->rollback();
4571 global $conf, $langs;
4573 if ($this->module_source ==
'takepos') {
4574 $langs->load(
'cashdesk');
4576 $moduleName =
'takepos';
4577 $moduleSourceName =
'Takepos';
4578 $addonConstName =
'TAKEPOS_REF_ADDON';
4582 $conf->global->TAKEPOS_REF_ADDON =
'mod_takepos_ref_simple';
4585 $addon = $conf->global->TAKEPOS_REF_ADDON;
4587 $langs->load(
'bills');
4589 $moduleName =
'facture';
4590 $moduleSourceName =
'Invoice';
4591 $addonConstName =
'FACTURE_ADDON';
4595 $conf->global->FACTURE_ADDON =
'mod_facture_terre';
4597 $conf->global->FACTURE_ADDON =
'mod_facture_terre';
4599 $conf->global->FACTURE_ADDON =
'mod_facture_mercure';
4602 $addon = $conf->global->FACTURE_ADDON;
4605 if (!empty($addon)) {
4606 dol_syslog(
"Call getNextNumRef with ".$addonConstName.
" = " .
getDolGlobalString(
'FACTURE_ADDON').
", thirdparty=".$soc->name.
", type=".$soc->typent_code.
", mode=".$mode, LOG_DEBUG);
4610 $file = $addon.
'.php';
4611 $classname = $addon;
4615 $dirmodels = array_merge(array(
'/'), (array) $conf->modules_parts[
'models']);
4616 foreach ($dirmodels as $reldir) {
4617 $dir =
dol_buildpath($reldir.
'core/modules/'.$moduleName.
'/');
4620 if (is_file($dir.$file) && is_readable($dir.$file)) {
4621 $mybool |= include_once $dir.$file;
4627 $file = $addon.
'/'.$addon.
'.modules.php';
4628 $classname =
'mod_'.$moduleName.
'_'.$addon;
4629 $classname = preg_replace(
'/\-.*$/',
'', $classname);
4631 foreach ($conf->file->dol_document_root as $dirroot) {
4632 $dir = $dirroot.
'/core/modules/'.$moduleName.
'/';
4635 if (is_file($dir.$file) && is_readable($dir.$file)) {
4636 $mybool |= include_once $dir.$file;
4646 $obj =
new $classname();
4648 $numref = $obj->getNextValue($soc, $this, $mode);
4655 if ($mode !=
'last' && !$numref) {
4656 $this->error = $obj->error;
4662 $langs->load(
'errors');
4663 print $langs->trans(
'Error').
' '.$langs->trans(
'ErrorModuleSetupNotComplete', $langs->transnoentitiesnoconv($moduleSourceName));
4676 $sql =
'SELECT c.rowid, datec, date_valid as datev, tms as datem,';
4677 $sql .=
' date_closing as dateclosing,';
4678 $sql .=
' fk_user_author, fk_user_valid, fk_user_closing';
4679 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facture as c';
4680 $sql .=
' WHERE c.rowid = '.((int) $id);
4682 $result = $this->db->query($sql);
4684 if ($this->db->num_rows($result)) {
4685 $obj = $this->db->fetch_object($result);
4687 $this->
id = $obj->rowid;
4688 $this->user_creation_id = $obj->fk_user_author;
4689 $this->user_validation_id = $obj->fk_user_valid;
4690 $this->user_closing_id = $obj->fk_user_closing;
4692 $this->date_creation = $this->db->jdate($obj->datec);
4693 $this->date_modification = $this->db->jdate($obj->datem);
4694 $this->date_validation = $this->db->jdate($obj->datev);
4695 $this->date_closing = $this->db->jdate($obj->dateclosing);
4697 $this->db->free($result);
4718 public function liste_array($shortlist = 0, $draft = 0, $excluser =
null, $socid = 0, $limit = 0, $offset = 0, $sortfield =
'f.datef,f.rowid', $sortorder =
'DESC')
4721 global $conf, $user;
4725 $sql =
"SELECT s.rowid, s.nom as name, s.client,";
4726 $sql .=
" f.rowid as fid, f.ref as ref, f.datef as df";
4727 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4728 $sql .=
", sc.fk_soc, sc.fk_user";
4730 $sql .=
" FROM ".MAIN_DB_PREFIX.
"societe as s, ".MAIN_DB_PREFIX.
"facture as f";
4731 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4732 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
4734 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice').
")";
4735 $sql .=
" AND f.fk_soc = s.rowid";
4736 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4737 $sql .=
" AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4740 $sql .=
" AND s.rowid = ".((int) $socid);
4743 $sql .=
" AND f.fk_statut = ".self::STATUS_DRAFT;
4745 if (is_object($excluser)) {
4746 $sql .=
" AND f.fk_user_author <> ".((int) $excluser->id);
4748 $sql .= $this->db->order($sortfield, $sortorder);
4749 $sql .= $this->db->plimit($limit, $offset);
4751 $result = $this->db->query($sql);
4753 $numc = $this->db->num_rows($result);
4756 while ($i < $numc) {
4757 $obj = $this->db->fetch_object($result);
4759 if ($shortlist == 1) {
4760 $ga[$obj->fid] = $obj->ref;
4761 } elseif ($shortlist == 2) {
4762 $ga[$obj->fid] = $obj->ref.
' ('.$obj->name.
')';
4764 $ga[$i][
'id'] = $obj->fid;
4765 $ga[$i][
'ref'] = $obj->ref;
4766 $ga[$i][
'name'] = $obj->name;
4795 $sql =
"SELECT f.rowid as rowid, f.ref, f.fk_statut as status, f.paye as paid,";
4796 $sql .=
" ff.rowid as rowidnext";
4798 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4799 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"paiement_facture as pf ON f.rowid = pf.fk_facture";
4800 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facture as ff ON f.rowid = ff.fk_facture_source";
4801 $sql .=
" WHERE (f.fk_statut = ".self::STATUS_VALIDATED.
" OR (f.fk_statut = ".self::STATUS_ABANDONED.
" AND f.close_code = '".self::CLOSECODE_ABANDONED.
"'))";
4802 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4803 $sql .=
" AND f.paye = 0";
4804 $sql .=
" AND pf.fk_paiement IS NULL";
4805 $sql .=
" AND ff.fk_statut IS NULL";
4807 $sql .=
" AND f.fk_soc = ".((int) $socid);
4810 $sql .=
" ORDER BY f.ref";
4812 dol_syslog(get_class($this).
"::list_replacable_invoices", LOG_DEBUG);
4813 $resql = $this->db->query($sql);
4815 while ($obj = $this->db->fetch_object($resql)) {
4816 $return[$obj->rowid] = array(
4817 'id' => $obj->rowid,
4819 'status' => $obj->status,
4820 'paid' => $obj->paid,
4827 $this->error = $this->db->error();
4850 $sql =
"SELECT f.rowid as rowid, f.ref, f.fk_statut, f.type, f.subtype, f.paye, pf.fk_paiement";
4851 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4852 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"paiement_facture as pf ON f.rowid = pf.fk_facture";
4853 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facture as ff ON (f.rowid = ff.fk_facture_source AND ff.type=".self::TYPE_REPLACEMENT.
")";
4854 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice').
")";
4855 $sql .=
" AND f.fk_statut in (".self::STATUS_VALIDATED.
",".self::STATUS_CLOSED.
")";
4859 $sql .=
" AND ff.type IS NULL";
4860 $sql .=
" AND f.type <> ".self::TYPE_CREDIT_NOTE;
4864 $sql .=
" AND (f.type <> ".self::TYPE_SITUATION.
" OR f.rowid IN ";
4865 $sql .=
'(SELECT MAX(fs.rowid)';
4866 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as fs";
4867 $sql .=
" WHERE fs.entity IN (".getEntity(
'invoice').
")";
4868 $sql .=
" AND fs.type = ".self::TYPE_SITUATION;
4869 $sql .=
" AND fs.fk_statut IN (".self::STATUS_VALIDATED.
",".self::STATUS_CLOSED.
")";
4871 $sql .=
" AND fs.fk_soc = ".((int) $socid);
4873 $sql .=
" GROUP BY fs.situation_cycle_ref)";
4876 $sql .=
" AND f.type <> ".self::TYPE_SITUATION;
4880 $sql .=
" AND f.fk_soc = ".((int) $socid);
4882 $sql .=
" ORDER BY f.ref";
4884 dol_syslog(get_class($this).
"::list_qualified_avoir_invoices", LOG_DEBUG);
4885 $resql = $this->db->query($sql);
4887 while ($obj = $this->db->fetch_object($resql)) {
4889 if ($obj->fk_statut == self::STATUS_VALIDATED) {
4892 if ($obj->fk_statut == self::STATUS_CLOSED) {
4897 $paymentornot = ($obj->fk_paiement ? 1 : 0);
4898 $return[$obj->rowid] = array(
'ref'=>$obj->ref,
'status'=>$obj->fk_statut,
'type'=>$obj->type,
'paye'=>$obj->paye,
'paymentornot'=>$paymentornot);
4904 $this->error = $this->db->error();
4920 global $conf, $langs;
4924 $sql =
"SELECT f.rowid, f.date_lim_reglement as datefin, f.fk_statut as status, f.total_ht";
4925 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4926 if (!$user->hasRight(
'societe',
'client',
'voir') && !$user->socid) {
4927 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON f.fk_soc = sc.fk_soc";
4928 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
4931 $sql .= $clause.
" f.paye=0";
4932 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4933 $sql .=
" AND f.fk_statut = ".self::STATUS_VALIDATED;
4935 $sql .=
" AND f.fk_soc = ".((int) $user->socid);
4938 $resql = $this->db->query($sql);
4940 $langs->load(
"bills");
4944 $response->warning_delay = $conf->facture->client->warning_delay / 60 / 60 / 24;
4945 $response->label = $langs->trans(
"CustomerBillsUnpaid");
4946 $response->labelShort = $langs->trans(
"Unpaid");
4947 $response->url = DOL_URL_ROOT.
'/compta/facture/list.php?search_status=1&mainmenu=billing&leftmenu=customers_bills';
4950 $generic_facture =
new Facture($this->db);
4952 while ($obj = $this->db->fetch_object($resql)) {
4953 $generic_facture->date_lim_reglement = $this->db->jdate($obj->datefin);
4954 $generic_facture->statut = $obj->status;
4955 $generic_facture->status = $obj->status;
4957 $response->nbtodo++;
4958 $response->total += $obj->total_ht;
4960 if ($generic_facture->hasDelay()) {
4961 $response->nbtodolate++;
4962 $response->url_late = DOL_URL_ROOT.
'/compta/facture/list.php?search_option=late&mainmenu=billing&leftmenu=customers_bills';
4966 $this->db->free($resql);
4970 $this->error = $this->db->error();
5009 global $conf, $langs, $user;
5013 $nownotime =
dol_mktime(0, 0, 0, $arraynow[
'mon'], $arraynow[
'mday'], $arraynow[
'year']);
5018 $sql =
"SELECT rowid";
5019 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
5020 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
5021 $sql .= $this->db->plimit(100);
5023 $resql = $this->db->query($sql);
5025 $num_prods = $this->db->num_rows($resql);
5027 while ($i < $num_prods) {
5029 $row = $this->db->fetch_row($resql);
5030 $prodids[$i] = $row[0];
5034 if (empty($num_prods)) {
5041 $this->
ref =
'SPECIMEN';
5042 $this->specimen = 1;
5044 $this->date = $nownotime;
5045 $this->date_lim_reglement = $nownotime + 3600 * 24 * 30;
5046 $this->cond_reglement_id = 1;
5047 $this->cond_reglement_code =
'RECEP';
5049 $this->mode_reglement_id = 0;
5050 $this->mode_reglement_code =
'';
5052 $this->note_public =
'This is a comment (public)';
5053 $this->note_private =
'This is a comment (private)';
5054 $this->note =
'This is a comment (private)';
5056 $this->fk_user_author = $user->id;
5058 $this->multicurrency_tx = 1;
5059 $this->multicurrency_code = $conf->currency;
5061 $this->fk_incoterms = 0;
5062 $this->location_incoterms =
'';
5064 if (empty($option) || $option !=
'nolines') {
5068 while ($xnbp < $nbp) {
5070 $line->desc = $langs->trans(
"Description").
" ".$xnbp;
5072 $line->subprice = 100;
5073 $line->tva_tx = 19.6;
5074 $line->localtax1_tx = 0;
5075 $line->localtax2_tx = 0;
5076 $line->remise_percent = 0;
5078 $prodid = mt_rand(1, $num_prods);
5079 $line->fk_product = $prodids[$prodid];
5081 $line->total_ht = -100;
5082 $line->total_ttc = -119.6;
5083 $line->total_tva = -19.6;
5084 $line->multicurrency_total_ht = -200;
5085 $line->multicurrency_total_ttc = -239.2;
5086 $line->multicurrency_total_tva = -39.2;
5087 } elseif ($xnbp == 2) {
5088 $line->subprice = -100;
5089 $line->total_ht = -100;
5090 $line->total_ttc = -119.6;
5091 $line->total_tva = -19.6;
5092 $line->remise_percent = 0;
5093 $line->multicurrency_total_ht = -200;
5094 $line->multicurrency_total_ttc = -239.2;
5095 $line->multicurrency_total_tva = -39.2;
5096 } elseif ($xnbp == 3) {
5097 $prodid = mt_rand(1, $num_prods);
5098 $line->fk_product = $prodids[$prodid];
5099 $line->total_ht = 50;
5100 $line->total_ttc = 59.8;
5101 $line->total_tva = 9.8;
5102 $line->multicurrency_total_ht = 100;
5103 $line->multicurrency_total_ttc = 119.6;
5104 $line->multicurrency_total_tva = 19.6;
5105 $line->remise_percent = 50;
5107 $prodid = mt_rand(1, $num_prods);
5108 $line->fk_product = $prodids[$prodid];
5109 $line->total_ht = 100;
5110 $line->total_ttc = 119.6;
5111 $line->total_tva = 19.6;
5112 $line->multicurrency_total_ht = 200;
5113 $line->multicurrency_total_ttc = 239.2;
5114 $line->multicurrency_total_tva = 39.2;
5115 $line->remise_percent = 0;
5118 $this->lines[$xnbp] = $line;
5121 $this->total_ht += $line->total_ht;
5122 $this->total_tva += $line->total_tva;
5123 $this->total_ttc += $line->total_ttc;
5125 $this->multicurrency_total_ht += $line->multicurrency_total_ht;
5126 $this->multicurrency_total_tva += $line->multicurrency_total_tva;
5127 $this->multicurrency_total_ttc += $line->multicurrency_total_ttc;
5131 $this->revenuestamp = 0;
5135 $line->desc = $langs->trans(
"Description").
" (offered line)";
5137 $line->subprice = 100;
5138 $line->tva_tx = 19.6;
5139 $line->localtax1_tx = 0;
5140 $line->localtax2_tx = 0;
5141 $line->remise_percent = 100;
5142 $line->total_ht = 0;
5143 $line->total_ttc = 0;
5144 $line->total_tva = 0;
5145 $line->multicurrency_total_ht = 0;
5146 $line->multicurrency_total_ttc = 0;
5147 $line->multicurrency_total_tva = 0;
5148 $prodid = mt_rand(1, $num_prods);
5149 $line->fk_product = $prodids[$prodid];
5151 $this->lines[$xnbp] = $line;
5165 global $conf, $user;
5167 $this->nb = array();
5171 $sql =
"SELECT count(f.rowid) as nb";
5172 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
5173 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON f.fk_soc = s.rowid";
5174 if (!$user->hasRight(
'societe',
'client',
'voir') && !$user->socid) {
5175 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON s.rowid = sc.fk_soc";
5176 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
5179 $sql .=
" ".$clause.
" f.entity IN (".
getEntity(
'invoice').
")";
5181 $resql = $this->db->query($sql);
5183 while ($obj = $this->db->fetch_object($resql)) {
5184 $this->nb[
"invoices"] = $obj->nb;
5186 $this->db->free($resql);
5190 $this->error = $this->db->error();
5216 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
5218 global $conf, $langs;
5220 $outputlangs->loadLangs(array(
"bills",
"products"));
5224 $thisTypeConfName =
'FACTURE_ADDON_PDF_'.$this->type;
5226 if (!empty($this->model_pdf)) {
5227 $modele = $this->model_pdf;
5231 $modele = $conf->global->FACTURE_ADDON_PDF;
5235 $modelpath =
"core/modules/facture/doc/";
5237 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
5247 $sql =
'SELECT max(situation_cycle_ref) FROM '.MAIN_DB_PREFIX.
'facture as f';
5248 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice', 0).
")";
5249 $resql = $this->db->query($sql);
5251 if ($this->db->num_rows($resql) > 0) {
5252 $res = $this->db->fetch_array($resql);
5253 $ref = $res[
'max(situation_cycle_ref)'];
5258 $this->db->free($resql);
5261 $this->error = $this->db->lasterror();
5262 dol_syslog(
"Error sql=".$sql.
", error=".$this->error, LOG_ERR);
5276 return ($this->situation_counter == 1);
5290 $sql =
'SELECT rowid FROM '.MAIN_DB_PREFIX.
'facture';
5291 $sql .=
' WHERE situation_cycle_ref = '.((int) $this->situation_cycle_ref);
5292 $sql .=
' AND situation_counter < '.((int) $this->situation_counter);
5293 $sql .=
' AND entity = '.($this->entity > 0 ? $this->entity : $conf->entity);
5294 $resql = $this->db->query($sql);
5296 if ($resql && $this->db->num_rows($resql) > 0) {
5297 while ($row = $this->db->fetch_object($resql)) {
5299 $situation =
new Facture($this->db);
5300 $situation->fetch($id);
5301 $res[] = $situation;
5304 $this->error = $this->db->error();
5305 dol_syslog(
"Error sql=".$sql.
", error=".$this->error, LOG_ERR);
5325 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET situation_final = '.((int) $this->situation_final).
' WHERE rowid = '.((int) $this->
id);
5328 $resql = $this->db->query($sql);
5330 $this->errors[] = $this->db->error();
5334 if (!$notrigger && empty($error)) {
5344 $this->db->commit();
5347 foreach ($this->errors as $errmsg) {
5348 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
5349 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
5351 $this->db->rollback();
5367 if (!empty($this->situation_cycle_ref)) {
5369 $sql =
'SELECT max(situation_counter) FROM '.MAIN_DB_PREFIX.
'facture';
5370 $sql .=
' WHERE situation_cycle_ref = '.((int) $this->situation_cycle_ref);
5371 $sql .=
' AND entity = '.($this->entity > 0 ? $this->entity : $conf->entity);
5372 $resql = $this->db->query($sql);
5374 if ($resql && $this->db->num_rows($resql) > 0) {
5375 $res = $this->db->fetch_array($resql);
5376 $last = $res[
'max(situation_counter)'];
5377 return ($last == $this->situation_counter);
5379 $this->error = $this->db->lasterror();
5380 dol_syslog(get_class($this).
"::select Error ".$this->error, LOG_ERR);
5438 $hasDelay = $this->date_lim_reglement < ($now - $conf->facture->client->warning_delay);
5439 if ($hasDelay && !empty($this->retained_warranty) && !empty($this->retained_warranty_date_limit)) {
5441 $totalpaid = (float) $totalpaid;
5443 if ($totalpaid >= 0 && $RetainedWarrantyAmount >= 0) {
5444 if (($totalpaid < $this->total_ttc - $RetainedWarrantyAmount) && $this->date_lim_reglement < ($now - $conf->facture->client->warning_delay)) {
5446 } elseif ($totalpaid < $this->total_ttc && $this->retained_warranty_date_limit < ($now - $conf->facture->client->warning_delay)) {
5469 $displayWarranty =
false;
5470 if (!empty($this->retained_warranty)) {
5471 $displayWarranty =
true;
5475 $displayWarranty =
false;
5476 if (!empty($this->situation_final)) {
5477 $displayWarranty =
true;
5480 $displayWarranty =
true;
5482 foreach ($this->lines as $i => $line) {
5483 if ($line->product_type < 2 && $line->situation_percent < 100) {
5484 $displayWarranty =
false;
5492 return $displayWarranty;
5502 if (empty($this->retained_warranty)) {
5506 $retainedWarrantyAmount = 0;
5510 $displayWarranty =
true;
5512 if (!empty($this->lines)) {
5513 foreach ($this->lines as $i => $line) {
5514 if ($line->product_type < 2 && $line->situation_percent < 100) {
5515 $displayWarranty =
false;
5521 if ($displayWarranty && !empty($this->situation_final)) {
5523 $TPreviousIncoice = $this->tab_previous_situation_invoice;
5526 foreach ($TPreviousIncoice as &$fac) {
5527 $total2BillWT += $fac->total_ttc;
5529 $total2BillWT += $this->total_ttc;
5531 $retainedWarrantyAmount = $total2BillWT * $this->retained_warranty / 100;
5537 $retainedWarrantyAmount = $this->total_ttc * $this->retained_warranty / 100;
5540 if ($rounding < 0) {
5544 if ($rounding > 0) {
5545 return round($retainedWarrantyAmount, $rounding);
5548 return $retainedWarrantyAmount;
5559 dol_syslog(get_class($this).
'::setRetainedWarranty('.$value.
')');
5561 if ($this->
status >= 0) {
5562 $fieldname =
'retained_warranty';
5563 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
5564 $sql .=
" SET ".$fieldname.
" = ".((float) $value);
5565 $sql .=
' WHERE rowid='.((int) $this->
id);
5567 if ($this->db->query($sql)) {
5568 $this->retained_warranty = (float) $value;
5571 dol_syslog(get_class($this).
'::setRetainedWarranty Erreur '.$sql.
' - '.$this->db->error());
5572 $this->error = $this->db->error();
5576 dol_syslog(get_class($this).
'::setRetainedWarranty, status of the object is incompatible');
5577 $this->error =
'Status of the object is incompatible '.$this->status;
5592 if (!$timestamp && $dateYmd) {
5593 $timestamp = $this->db->jdate($dateYmd);
5597 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit('.$timestamp.
')');
5598 if ($this->
status >= 0) {
5599 $fieldname =
'retained_warranty_date_limit';
5600 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
5601 $sql .=
" SET ".$fieldname.
" = ".(strval($timestamp) !=
'' ?
"'".$this->db->idate($timestamp).
"'" :
'null');
5602 $sql .=
' WHERE rowid = '.((int) $this->
id);
5604 if ($this->db->query($sql)) {
5605 $this->retained_warranty_date_limit = $timestamp;
5608 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit Erreur '.$sql.
' - '.$this->db->error());
5609 $this->error = $this->db->error();
5613 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit, status of the object is incompatible');
5614 $this->error =
'Status of the object is incompatible '.$this->status;
5633 global $conf, $langs, $user;
5639 $errorsMsg = array();
5641 $langs->load(
"bills");
5643 if (!isModEnabled(
'facture')) {
5644 $this->output .= $langs->trans(
'ModuleNotEnabled', $langs->transnoentitiesnoconv(
"Facture"));
5647 if (!in_array($datetouse, array(
'duedate',
'invoicedate'))) {
5648 $this->output .=
'Bad value for parameter datetouse. Must be "duedate" or "invoicedate"';
5658 require_once DOL_DOCUMENT_ROOT.
'/core/lib/date.lib.php';
5659 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmail.class.php';
5660 require_once DOL_DOCUMENT_ROOT.
'/core/class/CMailFile.class.php';
5661 $formmail =
new FormMail($this->db);
5666 $tmpinvoice =
new Facture($this->db);
5671 $sql =
"SELECT rowid as id FROM ".MAIN_DB_PREFIX.
"facture as f";
5672 if (!empty($paymentmode) && $paymentmode !=
'all') {
5673 $sql .=
", ".MAIN_DB_PREFIX.
"c_paiement as cp";
5675 $sql .=
" WHERE f.paye = 0";
5676 $sql .=
" AND f.fk_statut = ".self::STATUS_VALIDATED;
5677 if ($datetouse ==
'invoicedate') {
5678 $sql .=
" AND f.datef = '".$this->db->idate($tmpidate,
'gmt').
"'";
5680 $sql .=
" AND f.date_lim_reglement = '".$this->db->idate($tmpidate,
'gmt').
"'";
5682 $sql .=
" AND f.entity IN (".getEntity(
'facture', 0).
")";
5683 if (!empty($paymentmode) && $paymentmode !=
'all') {
5684 $sql .=
" AND f.fk_mode_reglement = cp.id AND cp.code = '".$this->db->escape($paymentmode).
"'";
5687 if ($datetouse ==
'invoicedate') {
5688 $sql .= $this->db->order(
"datef",
"ASC");
5690 $sql .= $this->db->order(
"date_lim_reglement",
"ASC");
5693 $resql = $this->db->query($sql);
5696 if ($datetouse ==
'invoicedate') {
5697 $this->output .= $langs->transnoentitiesnoconv(
"SearchValidatedInvoicesWithDate", $stmpidate);
5699 $this->output .= $langs->transnoentitiesnoconv(
"SearchUnpaidInvoicesWithDueDate", $stmpidate);
5701 if (!empty($paymentmode) && $paymentmode !=
'all') {
5702 $this->output .=
' ('.$langs->transnoentitiesnoconv(
"PaymentMode").
' '.$paymentmode.
')';
5704 $this->output .=
'<br>';
5707 while ($obj = $this->db->fetch_object($resql)) {
5710 $res = $tmpinvoice->fetch($obj->id);
5712 $tmpinvoice->fetch_thirdparty();
5714 $outputlangs =
new Translate(
'', $conf);
5715 if ($tmpinvoice->thirdparty->default_lang) {
5716 $outputlangs->setDefaultLang($tmpinvoice->thirdparty->default_lang);
5717 $outputlangs->loadLangs(array(
"main",
"bills"));
5719 $outputlangs = $langs;
5723 $arraymessage = $formmail->getEMailTemplate($this->db,
'facture_send', $user, $outputlangs, (is_numeric($template) ? $template : 0), 1, (is_numeric($template) ?
'' : $template));
5724 if (is_numeric($arraymessage) && $arraymessage <= 0) {
5725 $langs->load(
"errors");
5726 $this->output .= $langs->trans(
'ErrorFailedToFindEmailTemplate', $template);
5739 $sendTopic =
make_substitutions(empty($arraymessage->topic) ? $outputlangs->transnoentitiesnoconv(
'InformationMessage') : $arraymessage->topic, $substitutionarray, $outputlangs, 1);
5742 $content = $outputlangs->transnoentitiesnoconv($arraymessage->content);
5748 if ($forcerecipient) {
5749 $to = array($forcerecipient);
5751 $res = $tmpinvoice->fetch_thirdparty();
5752 $recipient = $tmpinvoice->thirdparty;
5754 $tmparraycontact = $tmpinvoice->liste_contact(-1,
'external', 0,
'BILLING');
5755 if (is_array($tmparraycontact) && count($tmparraycontact) > 0) {
5756 foreach ($tmparraycontact as $data_email) {
5757 if (!empty($data_email[
'email'])) {
5758 $to[] = $tmpinvoice->thirdparty->contact_get_property($data_email[
'id'],
'email');
5762 if (empty($to) && !empty($recipient->email)) {
5763 $to[] = $recipient->email;
5766 $errormesg =
"Failed to send remind to thirdparty id=".$tmpinvoice->socid.
". No email defined for invoice or customer.";
5770 $errormesg =
"Failed to load recipient with thirdparty id=".$tmpinvoice->socid;
5777 if (!empty($arraymessage->email_from)) {
5778 $from = $arraymessage->email_from;
5781 $errormesg =
"Failed to get sender into global setup MAIN_MAIL_EMAIL_FROM";
5785 if (!$error && !empty($to)) {
5788 $to = implode(
',', $to);
5789 if (!empty($arraymessage->email_to)) {
5790 $to = $to.
','.$arraymessage->email_to;
5794 $errors_to = $conf->global->MAIN_MAIL_ERRORS_TO;
5796 $trackid =
'inv'.$tmpinvoice->id;
5797 $sendcontext =
'standard';
5800 if (!empty($arraymessage->email_tocc)) {
5801 $email_tocc = $arraymessage->email_tocc;
5805 if (!empty($arraymessage->email_tobcc)) {
5806 $email_tobcc = $arraymessage->email_tobcc;
5813 if ($arraymessage->joinfiles == 1 && !empty($tmpinvoice->last_main_doc)) {
5814 $joinFile[] = DOL_DATA_ROOT.
'/'.$tmpinvoice->last_main_doc;
5815 $joinFileName[] = basename($tmpinvoice->last_main_doc);
5816 $joinFileMime[] =
dol_mimetype(DOL_DATA_ROOT.
'/'.$tmpinvoice->last_main_doc);
5820 $cMailFile =
new CMailFile($sendTopic, $to, $from, $sendContent, $joinFile, $joinFileMime, $joinFileName, $email_tocc, $email_tobcc, 0, 1, $errors_to,
'', $trackid,
'', $sendcontext,
'');
5823 if ($cMailFile->sendfile()) {
5827 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
5832 $actioncomm->type_code =
'AC_OTH_AUTO';
5833 $actioncomm->socid = $tmpinvoice->thirdparty->id;
5834 $actioncomm->contact_id = 0;
5836 $actioncomm->code =
'AC_EMAIL';
5837 $actioncomm->label =
'sendEmailsRemindersOnInvoiceDueDateOK (nbdays='.$nbdays.
' paymentmode='.$paymentmode.
' template='.$template.
' datetouse='.$datetouse.
' forcerecipient='.$forcerecipient.
')';
5838 $actioncomm->note_private = $sendContent;
5839 $actioncomm->fk_project = $tmpinvoice->fk_project;
5840 $actioncomm->datep =
dol_now();
5841 $actioncomm->datef = $actioncomm->datep;
5842 $actioncomm->percentage = -1;
5843 $actioncomm->authorid = $user->id;
5844 $actioncomm->userownerid = $user->id;
5846 $actioncomm->email_msgid = $cMailFile->msgid;
5847 $actioncomm->email_subject = $sendTopic;
5848 $actioncomm->email_from = $from;
5849 $actioncomm->email_sender =
'';
5850 $actioncomm->email_to = $to;
5854 $actioncomm->errors_to = $errors_to;
5856 $actioncomm->elementtype =
'invoice';
5857 $actioncomm->fk_element = $tmpinvoice->id;
5861 $actioncomm->create($user);
5863 $errormesg = $cMailFile->error.
' : '.$to;
5867 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
5872 $actioncomm->type_code =
'AC_OTH_AUTO';
5873 $actioncomm->socid = $tmpinvoice->thirdparty->id;
5874 $actioncomm->contact_id = 0;
5876 $actioncomm->code =
'AC_EMAIL';
5877 $actioncomm->label =
'sendEmailsRemindersOnInvoiceDueDateKO';
5878 $actioncomm->note_private = $errormesg;
5879 $actioncomm->fk_project = $tmpinvoice->fk_project;
5880 $actioncomm->datep =
dol_now();
5881 $actioncomm->datef = $actioncomm->datep;
5882 $actioncomm->percentage = -1;
5883 $actioncomm->authorid = $user->id;
5884 $actioncomm->userownerid = $user->id;
5886 $actioncomm->email_msgid = $cMailFile->msgid;
5887 $actioncomm->email_from = $from;
5888 $actioncomm->email_sender =
'';
5889 $actioncomm->email_to = $to;
5893 $actioncomm->errors_to = $errors_to;
5897 $actioncomm->create($user);
5900 $this->db->commit();
5904 $errorsMsg[] = $errormesg;
5907 $errorsMsg[] =
'Failed to fetch record invoice with ID = '.$obj->id;
5917 $this->output .=
'Nb of emails sent : '.$nbMailSend;
5919 dol_syslog(__METHOD__.
" end - ".$this->output, LOG_INFO);
5923 $this->error =
'Nb of emails sent : '.$nbMailSend.
', '.(!empty($errorsMsg)) ? join(
', ', $errorsMsg) : $error;
5925 dol_syslog(__METHOD__.
" end - ".$this->error, LOG_INFO);
5940 $sql =
"SELECT datef";
5941 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture";
5942 $sql .=
" WHERE type = " . (int) $this->
type ;
5943 $sql .=
" AND date_valid IS NOT NULL";
5944 $sql .=
" AND entity IN (".getEntity(
'invoice').
")";
5945 $sql .=
" ORDER BY datef DESC LIMIT 1";
5947 $result = $this->db->query($sql);
5950 if ($this->db->num_rows($result)) {
5951 $obj = $this->db->fetch_object($result);
5952 $last_date = $this->db->jdate($obj->datef);
5953 $invoice_date = $this->date;
5955 $is_last_of_same_type = $invoice_date >= $last_date;
5956 if ($allow_validated_drafts) {
5960 return array($is_last_of_same_type, $last_date);
5983 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
5985 $return =
'<div class="box-flex-item box-flex-grow-zero">';
5986 $return .=
'<div class="info-box info-box-sm">';
5987 $return .=
'<span class="info-box-icon bg-infobox-action">';
5989 $return .=
'</span>';
5990 $return .=
'<div class="info-box-content">';
5991 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl(1) : $this->ref).
'</span>';
5992 if ($selected >= 0) {
5993 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
5995 if (!empty($arraydata[
'thirdparty'])) {
5996 $return .=
'<br><span class="info-box-label">'.$arraydata[
'thirdparty'].
'</span>';
5998 if (property_exists($this,
'date')) {
5999 $return .=
'<br><span class="info-box-label">'.dol_print_date($this->date,
'day').
'</span>';
6001 if (property_exists($this,
'total_ht')) {
6002 $return .=
' <span class="info-box-label amount" title="'.dol_escape_htmltag($langs->trans(
"AmountHT")).
'">'.
price($this->total_ht);
6003 $return .=
' '.$langs->trans(
"HT");
6004 $return .=
'</span>';
6006 if (method_exists($this,
'getLibStatut')) {
6007 $alreadypaid = (empty($arraydata[
'alreadypaid']) ? 0 : $arraydata[
'alreadypaid']);
6008 $return .=
'<br><div class="info-box-status">'.$this->getLibStatut(3, $alreadypaid).
'</div>';
6010 $return .=
'</div>';
6011 $return .=
'</div>';
6012 $return .=
'</div>';
6026 public $element =
'facturedet';
6031 public $table_element =
'facturedet';
6048 public $localtax1_type;
6049 public $localtax2_type;
6050 public $fk_remise_except;
6053 public $fk_fournprice;
6063 public $remise_percent;
6081 public $fk_warehouse;
6090 public $fk_code_ventilation = 0;
6096 public $skip_update_total;
6101 public $situation_percent;
6126 $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,';
6127 $sql .=
' fd.localtax1_tx, fd. localtax2_tx, fd.remise, fd.remise_percent, fd.fk_remise_except, fd.subprice, fd.ref_ext,';
6128 $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,';
6129 $sql .=
' fd.info_bits, fd.special_code, fd.total_ht, fd.total_tva, fd.total_ttc, fd.total_localtax1, fd.total_localtax2, fd.rang,';
6130 $sql .=
' fd.fk_code_ventilation,';
6131 $sql .=
' fd.fk_unit, fd.fk_user_author, fd.fk_user_modif,';
6132 $sql .=
' fd.situation_percent, fd.fk_prev_id,';
6133 $sql .=
' fd.multicurrency_subprice,';
6134 $sql .=
' fd.multicurrency_total_ht,';
6135 $sql .=
' fd.multicurrency_total_tva,';
6136 $sql .=
' fd.multicurrency_total_ttc,';
6137 $sql .=
' p.ref as product_ref, p.label as product_label, p.description as product_desc';
6138 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facturedet as fd';
6139 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON fd.fk_product = p.rowid';
6140 $sql .=
' WHERE fd.rowid = '.((int) $rowid);
6142 $result = $this->db->query($sql);
6144 $objp = $this->db->fetch_object($result);
6147 $this->error =
'InvoiceLine with id '. $rowid .
' not found sql='.$sql;
6151 $this->
rowid = $objp->rowid;
6152 $this->
id = $objp->rowid;
6153 $this->fk_facture = $objp->fk_facture;
6154 $this->fk_parent_line = $objp->fk_parent_line;
6155 $this->label = $objp->custom_label;
6156 $this->desc = $objp->description;
6157 $this->qty = $objp->qty;
6158 $this->subprice = $objp->subprice;
6159 $this->ref_ext = $objp->ref_ext;
6160 $this->vat_src_code = $objp->vat_src_code;
6161 $this->tva_tx = $objp->tva_tx;
6162 $this->localtax1_tx = $objp->localtax1_tx;
6163 $this->localtax2_tx = $objp->localtax2_tx;
6164 $this->remise_percent = $objp->remise_percent;
6165 $this->fk_remise_except = $objp->fk_remise_except;
6166 $this->fk_product = $objp->fk_product;
6167 $this->product_type = $objp->product_type;
6168 $this->date_start = $this->db->jdate($objp->date_start);
6169 $this->date_end = $this->db->jdate($objp->date_end);
6170 $this->info_bits = $objp->info_bits;
6171 $this->tva_npr = ($objp->info_bits & 1 == 1) ? 1 : 0;
6172 $this->special_code = $objp->special_code;
6173 $this->total_ht = $objp->total_ht;
6174 $this->total_tva = $objp->total_tva;
6175 $this->total_localtax1 = $objp->total_localtax1;
6176 $this->total_localtax2 = $objp->total_localtax2;
6177 $this->total_ttc = $objp->total_ttc;
6178 $this->fk_code_ventilation = $objp->fk_code_ventilation;
6179 $this->rang = $objp->rang;
6180 $this->fk_fournprice = $objp->fk_fournprice;
6181 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $this->fk_fournprice, $objp->pa_ht);
6182 $this->pa_ht = $marginInfos[0];
6183 $this->marge_tx = $marginInfos[1];
6184 $this->marque_tx = $marginInfos[2];
6186 $this->
ref = $objp->product_ref;
6188 $this->product_ref = $objp->product_ref;
6189 $this->product_label = $objp->product_label;
6190 $this->product_desc = $objp->product_desc;
6192 $this->fk_unit = $objp->fk_unit;
6193 $this->fk_user_modif = $objp->fk_user_modif;
6194 $this->fk_user_author = $objp->fk_user_author;
6196 $this->situation_percent = $objp->situation_percent;
6197 $this->fk_prev_id = $objp->fk_prev_id;
6199 $this->multicurrency_subprice = $objp->multicurrency_subprice;
6200 $this->multicurrency_total_ht = $objp->multicurrency_total_ht;
6201 $this->multicurrency_total_tva = $objp->multicurrency_total_tva;
6202 $this->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
6206 $this->db->free($result);
6210 $this->error = $this->db->lasterror();
6222 public function insert($notrigger = 0, $noerrorifdiscountalreadylinked = 0)
6224 global $langs, $user, $conf;
6228 $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht ==
'');
6230 dol_syslog(get_class($this).
"::insert rang=".$this->rang, LOG_DEBUG);
6233 $this->desc = trim($this->desc);
6234 if (empty($this->tva_tx)) {
6237 if (empty($this->localtax1_tx)) {
6238 $this->localtax1_tx = 0;
6240 if (empty($this->localtax2_tx)) {
6241 $this->localtax2_tx = 0;
6243 if (empty($this->localtax1_type)) {
6244 $this->localtax1_type = 0;
6246 if (empty($this->localtax2_type)) {
6247 $this->localtax2_type = 0;
6249 if (empty($this->total_localtax1)) {
6250 $this->total_localtax1 = 0;
6252 if (empty($this->total_localtax2)) {
6253 $this->total_localtax2 = 0;
6255 if (empty($this->rang)) {
6258 if (empty($this->remise_percent)) {
6259 $this->remise_percent = 0;
6261 if (empty($this->info_bits)) {
6262 $this->info_bits = 0;
6264 if (empty($this->subprice)) {
6265 $this->subprice = 0;
6267 if (empty($this->ref_ext)) {
6268 $this->ref_ext =
'';
6270 if (empty($this->special_code)) {
6271 $this->special_code = 0;
6273 if (empty($this->fk_parent_line)) {
6274 $this->fk_parent_line = 0;
6276 if (empty($this->fk_prev_id)) {
6277 $this->fk_prev_id = 0;
6279 if (!isset($this->situation_percent) || $this->situation_percent > 100 || (
string) $this->situation_percent ==
'') {
6280 $this->situation_percent = 100;
6283 if (empty($this->pa_ht)) {
6286 if (empty($this->multicurrency_subprice)) {
6287 $this->multicurrency_subprice = 0;
6289 if (empty($this->multicurrency_total_ht)) {
6290 $this->multicurrency_total_ht = 0;
6292 if (empty($this->multicurrency_total_tva)) {
6293 $this->multicurrency_total_tva = 0;
6295 if (empty($this->multicurrency_total_ttc)) {
6296 $this->multicurrency_total_ttc = 0;
6300 if ($this->pa_ht == 0 && $pa_ht_isemptystring) {
6301 if (($result = $this->
defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0) {
6304 $this->pa_ht = $result;
6309 if ($this->product_type < 0) {
6310 $this->error =
'ErrorProductTypeMustBe0orMore';
6313 if (!empty($this->fk_product) && $this->fk_product > 0) {
6317 $this->error =
'ErrorProductIdDoesNotExists';
6318 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6326 $sql =
'INSERT INTO '.MAIN_DB_PREFIX.
'facturedet';
6327 $sql .=
' (fk_facture, fk_parent_line, label, description, qty,';
6328 $sql .=
' vat_src_code, tva_tx, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type,';
6329 $sql .=
' fk_product, product_type, remise_percent, subprice, ref_ext, fk_remise_except,';
6330 $sql .=
' date_start, date_end, fk_code_ventilation, ';
6331 $sql .=
' rang, special_code, fk_product_fournisseur_price, buy_price_ht,';
6332 $sql .=
' info_bits, total_ht, total_tva, total_ttc, total_localtax1, total_localtax2,';
6333 $sql .=
' situation_percent, fk_prev_id,';
6334 $sql .=
' fk_unit, fk_user_author, fk_user_modif,';
6335 $sql .=
' fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc';
6337 $sql .=
" VALUES (".$this->fk_facture.
",";
6338 $sql .=
" ".($this->fk_parent_line > 0 ? $this->fk_parent_line :
"null").
",";
6339 $sql .=
" ".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null").
",";
6340 $sql .=
" '".$this->db->escape($this->desc).
"',";
6341 $sql .=
" ".price2num($this->qty).
",";
6342 $sql .=
" ".(empty($this->vat_src_code) ?
"''" :
"'".$this->db->escape($this->vat_src_code).
"'").
",";
6343 $sql .=
" ".price2num($this->tva_tx).
",";
6344 $sql .=
" ".price2num($this->localtax1_tx).
",";
6345 $sql .=
" ".price2num($this->localtax2_tx).
",";
6346 $sql .=
" '".$this->db->escape($this->localtax1_type).
"',";
6347 $sql .=
" '".$this->db->escape($this->localtax2_type).
"',";
6348 $sql .=
' '.((!empty($this->fk_product) && $this->fk_product > 0) ? $this->fk_product :
"null").
',';
6349 $sql .=
" ".((int) $this->product_type).
",";
6350 $sql .=
" ".price2num($this->remise_percent).
",";
6351 $sql .=
" ".price2num($this->subprice).
",";
6352 $sql .=
" '".$this->db->escape($this->ref_ext).
"',";
6353 $sql .=
' '.(!empty($this->fk_remise_except) ? $this->fk_remise_except :
"null").
',';
6354 $sql .=
" ".(!empty($this->date_start) ?
"'".$this->db->idate($this->date_start).
"'" :
"null").
",";
6355 $sql .=
" ".(!empty($this->date_end) ?
"'".$this->db->idate($this->date_end).
"'" :
"null").
",";
6356 $sql .=
' '.((int) $this->fk_code_ventilation).
',';
6357 $sql .=
' '.((int) $this->rang).
',';
6358 $sql .=
' '.((int) $this->special_code).
',';
6359 $sql .=
' '.(!empty($this->fk_fournprice) ? $this->fk_fournprice :
"null").
',';
6360 $sql .=
' '.price2num($this->pa_ht).
',';
6361 $sql .=
" '".$this->db->escape($this->info_bits).
"',";
6362 $sql .=
" ".price2num($this->total_ht).
",";
6363 $sql .=
" ".price2num($this->total_tva).
",";
6364 $sql .=
" ".price2num($this->total_ttc).
",";
6365 $sql .=
" ".price2num($this->total_localtax1).
",";
6366 $sql .=
" ".price2num($this->total_localtax2);
6367 $sql .=
", ".((float) $this->situation_percent);
6368 $sql .=
", ".(!empty($this->fk_prev_id) ? $this->fk_prev_id :
"null");
6369 $sql .=
", ".(!$this->fk_unit ?
'NULL' : $this->fk_unit);
6370 $sql .=
", ".((int) $user->id);
6371 $sql .=
", ".((int) $user->id);
6372 $sql .=
", ".(int) $this->fk_multicurrency;
6373 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
6374 $sql .=
", ".price2num($this->multicurrency_subprice);
6375 $sql .=
", ".price2num($this->multicurrency_total_ht);
6376 $sql .=
", ".price2num($this->multicurrency_total_tva);
6377 $sql .=
", ".price2num($this->multicurrency_total_ttc);
6380 dol_syslog(get_class($this).
"::insert", LOG_DEBUG);
6381 $resql = $this->db->query($sql);
6383 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
'facturedet');
6384 $this->
rowid = $this->id;
6395 if ($this->fk_remise_except) {
6397 $result = $discount->fetch($this->fk_remise_except);
6402 if ($discount->fk_facture_line > 0) {
6403 if (empty($noerrorifdiscountalreadylinked)) {
6404 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed", $discount->id);
6405 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6406 $this->db->rollback();
6410 $result = $discount->link_to_invoice($this->
rowid, 0);
6412 $this->error = $discount->error;
6413 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6414 $this->db->rollback();
6419 $this->error = $langs->trans(
"ErrorADiscountThatHasBeenRemovedIsIncluded");
6420 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6421 $this->db->rollback();
6425 $this->error = $discount->error;
6426 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6427 $this->db->rollback();
6434 $result = $this->
call_trigger(
'LINEBILL_INSERT', $user);
6436 $this->db->rollback();
6442 $this->db->commit();
6445 $this->error = $this->db->lasterror();
6446 $this->db->rollback();
6458 public function update($user =
null, $notrigger = 0)
6460 global $user, $conf;
6464 $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht ==
'');
6467 $this->desc = trim($this->desc);
6468 if (empty($this->ref_ext)) {
6469 $this->ref_ext =
'';
6471 if (empty($this->tva_tx)) {
6474 if (empty($this->localtax1_tx)) {
6475 $this->localtax1_tx = 0;
6477 if (empty($this->localtax2_tx)) {
6478 $this->localtax2_tx = 0;
6480 if (empty($this->localtax1_type)) {
6481 $this->localtax1_type = 0;
6483 if (empty($this->localtax2_type)) {
6484 $this->localtax2_type = 0;
6486 if (empty($this->total_localtax1)) {
6487 $this->total_localtax1 = 0;
6489 if (empty($this->total_localtax2)) {
6490 $this->total_localtax2 = 0;
6492 if (empty($this->remise_percent)) {
6493 $this->remise_percent = 0;
6495 if (empty($this->info_bits)) {
6496 $this->info_bits = 0;
6498 if (empty($this->special_code)) {
6499 $this->special_code = 0;
6501 if (empty($this->product_type)) {
6502 $this->product_type = 0;
6504 if (empty($this->fk_parent_line)) {
6505 $this->fk_parent_line = 0;
6507 if (!isset($this->situation_percent) || $this->situation_percent > 100 || (
string) $this->situation_percent ==
'') {
6508 $this->situation_percent = 100;
6510 if (empty($this->pa_ht)) {
6514 if (empty($this->multicurrency_subprice)) {
6515 $this->multicurrency_subprice = 0;
6517 if (empty($this->multicurrency_total_ht)) {
6518 $this->multicurrency_total_ht = 0;
6520 if (empty($this->multicurrency_total_tva)) {
6521 $this->multicurrency_total_tva = 0;
6523 if (empty($this->multicurrency_total_ttc)) {
6524 $this->multicurrency_total_ttc = 0;
6528 if ($this->product_type < 0) {
6533 if ($this->pa_ht == 0 && $pa_ht_isemptystring) {
6535 $result = $this->
defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product);
6539 $this->pa_ht = $result;
6546 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facturedet SET";
6547 $sql .=
" description='".$this->db->escape($this->desc).
"'";
6548 $sql .=
", ref_ext='".$this->db->escape($this->ref_ext).
"'";
6549 $sql .=
", label=".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null");
6550 $sql .=
", subprice=".price2num($this->subprice);
6551 $sql .=
", remise_percent=".price2num($this->remise_percent);
6552 if ($this->fk_remise_except) {
6553 $sql .=
", fk_remise_except=".$this->fk_remise_except;
6555 $sql .=
", fk_remise_except=null";
6557 $sql .=
", vat_src_code = '".(empty($this->vat_src_code) ?
'' : $this->db->escape($this->vat_src_code)).
"'";
6558 $sql .=
", tva_tx=".price2num($this->tva_tx);
6559 $sql .=
", localtax1_tx=".price2num($this->localtax1_tx);
6560 $sql .=
", localtax2_tx=".price2num($this->localtax2_tx);
6561 $sql .=
", localtax1_type='".$this->db->escape($this->localtax1_type).
"'";
6562 $sql .=
", localtax2_type='".$this->db->escape($this->localtax2_type).
"'";
6563 $sql .=
", qty=".price2num($this->qty);
6564 $sql .=
", date_start=".(!empty($this->date_start) ?
"'".$this->db->idate($this->date_start).
"'" :
"null");
6565 $sql .=
", date_end=".(!empty($this->date_end) ?
"'".$this->db->idate($this->date_end).
"'" :
"null");
6566 $sql .=
", product_type=".$this->product_type;
6567 $sql .=
", info_bits='".$this->db->escape($this->info_bits).
"'";
6568 $sql .=
", special_code='".$this->db->escape($this->special_code).
"'";
6569 if (empty($this->skip_update_total)) {
6570 $sql .=
", total_ht=".price2num($this->total_ht);
6571 $sql .=
", total_tva=".price2num($this->total_tva);
6572 $sql .=
", total_ttc=".price2num($this->total_ttc);
6573 $sql .=
", total_localtax1=".price2num($this->total_localtax1);
6574 $sql .=
", total_localtax2=".price2num($this->total_localtax2);
6576 $sql .=
", fk_product_fournisseur_price=".(!empty($this->fk_fournprice) ?
"'".$this->db->escape($this->fk_fournprice).
"'" :
"null");
6577 $sql .=
", buy_price_ht=".(($this->pa_ht || (string) $this->pa_ht ===
'0') ?
price2num($this->pa_ht) :
"null");
6578 $sql .=
", fk_parent_line=".($this->fk_parent_line > 0 ? $this->fk_parent_line :
"null");
6579 if (!empty($this->rang)) {
6580 $sql .=
", rang=".((int) $this->rang);
6582 $sql .=
", situation_percent = ".((float) $this->situation_percent);
6583 $sql .=
", fk_unit = ".(!$this->fk_unit ?
'NULL' : $this->fk_unit);
6584 $sql .=
", fk_user_modif = ".((int) $user->id);
6587 $sql .=
", multicurrency_subprice=".price2num($this->multicurrency_subprice);
6588 $sql .=
", multicurrency_total_ht=".price2num($this->multicurrency_total_ht);
6589 $sql .=
", multicurrency_total_tva=".price2num($this->multicurrency_total_tva);
6590 $sql .=
", multicurrency_total_ttc=".price2num($this->multicurrency_total_ttc);
6592 $sql .=
" WHERE rowid = ".((int) $this->
rowid);
6594 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
6595 $resql = $this->db->query($sql);
6598 $this->
id = $this->rowid;
6605 if (!$error && !$notrigger) {
6607 $result = $this->
call_trigger(
'LINEBILL_MODIFY', $user);
6609 $this->db->rollback();
6614 $this->db->commit();
6617 $this->error = $this->db->error();
6618 $this->db->rollback();
6630 public function delete($tmpuser =
null, $notrigger =
false)
6637 if (empty($notrigger)) {
6638 $result = $this->
call_trigger(
'LINEBILL_DELETE', $user);
6640 $this->db->rollback();
6649 $this->db->rollback();
6654 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
6655 $sql .=
' SET fk_facture_line = NULL';
6656 $sql .=
' WHERE fk_facture_line = '.((int) $this->
id);
6658 dol_syslog(get_class($this).
"::deleteline", LOG_DEBUG);
6659 $result = $this->db->query($sql);
6661 $this->error = $this->db->error();
6662 $this->errors[] = $this->error;
6663 $this->db->rollback();
6667 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'element_time';
6668 $sql .=
' SET invoice_id = NULL, invoice_line_id = NULL';
6669 $sql .=
' WHERE invoice_line_id = '.((int) $this->
id);
6670 if (!$this->db->query($sql)) {
6671 $this->error = $this->db->error().
" sql=".$sql;
6672 $this->errors[] = $this->error;
6673 $this->db->rollback();
6677 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"facturedet WHERE rowid = ".((int) $this->
id);
6679 if ($this->db->query($sql)) {
6680 $this->db->commit();
6683 $this->error = $this->db->error().
" sql=".$sql;
6684 $this->errors[] = $this->error;
6685 $this->db->rollback();
6701 dol_syslog(get_class($this).
"::update_total", LOG_DEBUG);
6704 if (empty($this->total_localtax1)) {
6705 $this->total_localtax1 = 0;
6707 if (empty($this->total_localtax2)) {
6708 $this->total_localtax2 = 0;
6712 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facturedet SET";
6713 $sql .=
" total_ht=".price2num($this->total_ht);
6714 $sql .=
",total_tva=".price2num($this->total_tva);
6715 $sql .=
",total_localtax1=".price2num($this->total_localtax1);
6716 $sql .=
",total_localtax2=".price2num($this->total_localtax2);
6717 $sql .=
",total_ttc=".price2num($this->total_ttc);
6718 $sql .=
" WHERE rowid = ".((int) $this->
rowid);
6720 dol_syslog(get_class($this).
"::update_total", LOG_DEBUG);
6722 $resql = $this->db->query($sql);
6724 $this->db->commit();
6727 $this->error = $this->db->error();
6728 $this->db->rollback();
6745 global $invoicecache;
6747 if (is_null($this->fk_prev_id) || empty($this->fk_prev_id) || $this->fk_prev_id ==
"") {
6751 if (!isset($invoicecache[$invoiceid])) {
6752 $invoicecache[$invoiceid] =
new Facture($this->db);
6753 $invoicecache[$invoiceid]->fetch($invoiceid);
6759 $sql =
"SELECT situation_percent FROM ".MAIN_DB_PREFIX.
"facturedet WHERE rowid = ".((int) $this->fk_prev_id);
6760 $resql = $this->db->query($sql);
6761 if ($resql && $this->db->num_rows($resql) > 0) {
6762 $res = $this->db->fetch_array($resql);
6764 $returnPercent = (float) $res[
'situation_percent'];
6766 if ($include_credit_note) {
6767 $sql =
'SELECT fd.situation_percent FROM '.MAIN_DB_PREFIX.
'facturedet fd';
6768 $sql .=
' JOIN '.MAIN_DB_PREFIX.
'facture f ON (f.rowid = fd.fk_facture) ';
6769 $sql .=
" WHERE fd.fk_prev_id = ".((int) $this->fk_prev_id);
6770 $sql .=
" AND f.situation_cycle_ref = ".((int) $invoicecache[$invoiceid]->situation_cycle_ref);
6771 $sql .=
" AND f.type = ".Facture::TYPE_CREDIT_NOTE;
6773 $res = $this->db->query($sql);
6775 while ($obj = $this->db->fetch_object($res)) {
6776 $returnPercent = $returnPercent + (float) $obj->situation_percent;
6783 return $returnPercent;
6785 $this->error = $this->db->error();
6786 dol_syslog(get_class($this).
"::select Error ".$this->error, LOG_ERR);
6787 $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