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 $fk_element =
'fk_facture';
86 public $picto =
'bill';
92 public $ismultientitymanaged = 1;
97 public $isextrafieldmanaged = 1;
103 public $restrictiononfksoc = 1;
122 public $fk_user_author;
134 public $fk_user_valid;
139 public $fk_user_modif;
146 public $delivery_date;
158 public $ref_customer;
162 public $total_localtax1;
163 public $total_localtax2;
165 public $revenuestamp;
182 public $linked_objects = array();
192 public $lines = array();
198 public $extraparams = array();
205 public $date_pointoftax;
211 public $situation_cycle_ref;
216 public $situation_counter;
221 public $situation_final;
226 public $tab_previous_situation_invoice = array();
231 public $tab_next_situation_invoice = array();
241 public $retained_warranty;
246 public $retained_warranty_date_limit;
251 public $retained_warranty_fk_cond_reglement;
256 public $availability_id;
258 public $date_closing;
268 public $remise_percent;
299 public $fields = array(
300 'rowid' =>array(
'type'=>
'integer',
'label'=>
'TechnicalID',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>1),
301 'ref' =>array(
'type'=>
'varchar(30)',
'label'=>
'Ref',
'enabled'=>1,
'visible'=>1,
'notnull'=>1,
'showoncombobox'=>1,
'position'=>5),
302 'entity' =>array(
'type'=>
'integer',
'label'=>
'Entity',
'default'=>1,
'enabled'=>1,
'visible'=>-2,
'notnull'=>1,
'position'=>20,
'index'=>1),
303 'ref_client' =>array(
'type'=>
'varchar(255)',
'label'=>
'RefCustomer',
'enabled'=>1,
'visible'=>-1,
'position'=>10),
304 'ref_ext' =>array(
'type'=>
'varchar(255)',
'label'=>
'Ref ext',
'enabled'=>1,
'visible'=>0,
'position'=>12),
305 'type' =>array(
'type'=>
'smallint(6)',
'label'=>
'Type',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>15),
306 'subtype' =>array(
'type'=>
'smallint(6)',
'label'=>
'InvoiceSubtype',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>15),
308 'fk_soc' =>array(
'type'=>
'integer:Societe:societe/class/societe.class.php',
'label'=>
'ThirdParty',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>50),
309 'datef' =>array(
'type'=>
'date',
'label'=>
'DateInvoice',
'enabled'=>1,
'visible'=>1,
'position'=>20),
310 'date_valid' =>array(
'type'=>
'date',
'label'=>
'DateValidation',
'enabled'=>1,
'visible'=>-1,
'position'=>22),
311 'date_lim_reglement' =>array(
'type'=>
'date',
'label'=>
'DateDue',
'enabled'=>1,
'visible'=>1,
'position'=>25),
312 'date_closing' =>array(
'type'=>
'datetime',
'label'=>
'Date closing',
'enabled'=>1,
'visible'=>-1,
'position'=>30),
313 'paye' =>array(
'type'=>
'smallint(6)',
'label'=>
'InvoicePaidCompletely',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>80),
318 'close_code' =>array(
'type'=>
'varchar(16)',
'label'=>
'EarlyClosingReason',
'enabled'=>1,
'visible'=>-1,
'position'=>92),
319 'close_note' =>array(
'type'=>
'varchar(128)',
'label'=>
'EarlyClosingComment',
'enabled'=>1,
'visible'=>-1,
'position'=>93),
320 'total_ht' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountHT',
'enabled'=>1,
'visible'=>1,
'position'=>95,
'isameasure'=>1),
321 'total_tva' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountVAT',
'enabled'=>1,
'visible'=>-1,
'position'=>100,
'isameasure'=>1),
322 'localtax1' =>array(
'type'=>
'double(24,8)',
'label'=>
'LT1',
'enabled'=>1,
'visible'=>-1,
'position'=>110,
'isameasure'=>1),
323 'localtax2' =>array(
'type'=>
'double(24,8)',
'label'=>
'LT2',
'enabled'=>1,
'visible'=>-1,
'position'=>120,
'isameasure'=>1),
324 'revenuestamp' =>array(
'type'=>
'double(24,8)',
'label'=>
'RevenueStamp',
'enabled'=>1,
'visible'=>-1,
'position'=>115,
'isameasure'=>1),
325 'total_ttc' =>array(
'type'=>
'double(24,8)',
'label'=>
'AmountTTC',
'enabled'=>1,
'visible'=>1,
'position'=>130,
'isameasure'=>1),
326 'fk_facture_source' =>array(
'type'=>
'integer',
'label'=>
'SourceInvoice',
'enabled'=>1,
'visible'=>-1,
'position'=>170),
327 'fk_projet' =>array(
'type'=>
'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)',
'label'=>
'Project',
'enabled'=>1,
'visible'=>-1,
'position'=>175),
328 'fk_account' =>array(
'type'=>
'integer',
'label'=>
'Fk account',
'enabled'=>1,
'visible'=>-1,
'position'=>180),
329 'fk_currency' =>array(
'type'=>
'varchar(3)',
'label'=>
'CurrencyCode',
'enabled'=>1,
'visible'=>-1,
'position'=>185),
330 'fk_cond_reglement' =>array(
'type'=>
'integer',
'label'=>
'PaymentTerm',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>190),
331 'fk_mode_reglement' =>array(
'type'=>
'integer',
'label'=>
'PaymentMode',
'enabled'=>1,
'visible'=>-1,
'position'=>195),
332 'note_private' =>array(
'type'=>
'html',
'label'=>
'NotePrivate',
'enabled'=>1,
'visible'=>0,
'position'=>205),
333 'note_public' =>array(
'type'=>
'html',
'label'=>
'NotePublic',
'enabled'=>1,
'visible'=>0,
'position'=>210),
334 'model_pdf' =>array(
'type'=>
'varchar(255)',
'label'=>
'Model pdf',
'enabled'=>1,
'visible'=>0,
'position'=>215),
335 'extraparams' =>array(
'type'=>
'varchar(255)',
'label'=>
'Extraparams',
'enabled'=>1,
'visible'=>-1,
'position'=>225),
336 'situation_cycle_ref' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation cycle ref',
'enabled'=>
'$conf->global->INVOICE_USE_SITUATION',
'visible'=>-1,
'position'=>230),
337 'situation_counter' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation counter',
'enabled'=>
'$conf->global->INVOICE_USE_SITUATION',
'visible'=>-1,
'position'=>235),
338 'situation_final' =>array(
'type'=>
'smallint(6)',
'label'=>
'Situation final',
'enabled'=>
'empty($conf->global->INVOICE_USE_SITUATION) ? 0 : 1',
'visible'=>-1,
'position'=>240),
339 'retained_warranty' =>array(
'type'=>
'double',
'label'=>
'Retained warranty',
'enabled'=>
'$conf->global->INVOICE_USE_RETAINED_WARRANTY',
'visible'=>-1,
'position'=>245),
340 'retained_warranty_date_limit' =>array(
'type'=>
'date',
'label'=>
'Retained warranty date limit',
'enabled'=>
'$conf->global->INVOICE_USE_RETAINED_WARRANTY',
'visible'=>-1,
'position'=>250),
341 '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),
342 'fk_incoterms' =>array(
'type'=>
'integer',
'label'=>
'IncotermCode',
'enabled'=>
'$conf->incoterm->enabled',
'visible'=>-1,
'position'=>260),
343 'location_incoterms' =>array(
'type'=>
'varchar(255)',
'label'=>
'IncotermLabel',
'enabled'=>
'$conf->incoterm->enabled',
'visible'=>-1,
'position'=>265),
344 'date_pointoftax' =>array(
'type'=>
'date',
'label'=>
'DatePointOfTax',
'enabled'=>
'$conf->global->INVOICE_POINTOFTAX_DATE',
'visible'=>-1,
'position'=>270),
345 'fk_multicurrency' =>array(
'type'=>
'integer',
'label'=>
'MulticurrencyID',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>275),
346 'multicurrency_code' =>array(
'type'=>
'varchar(255)',
'label'=>
'Currency',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>280),
347 'multicurrency_tx' =>array(
'type'=>
'double(24,8)',
'label'=>
'CurrencyRate',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>285,
'isameasure'=>1),
348 'multicurrency_total_ht' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountHT',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>290,
'isameasure'=>1),
349 'multicurrency_total_tva' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountVAT',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>291,
'isameasure'=>1),
350 'multicurrency_total_ttc' =>array(
'type'=>
'double(24,8)',
'label'=>
'MulticurrencyAmountTTC',
'enabled'=>
'isModEnabled("multicurrency")',
'visible'=>-1,
'position'=>292,
'isameasure'=>1),
351 'fk_fac_rec_source' =>array(
'type'=>
'integer',
'label'=>
'RecurringInvoiceSource',
'enabled'=>1,
'visible'=>-1,
'position'=>305),
352 'last_main_doc' =>array(
'type'=>
'varchar(255)',
'label'=>
'LastMainDoc',
'enabled'=>1,
'visible'=>-1,
'position'=>310),
353 'module_source' =>array(
'type'=>
'varchar(32)',
'label'=>
'POSModule',
'enabled'=>
"(isModEnabled('cashdesk') || isModEnabled('takepos') || getDolGlobalInt('INVOICE_SHOW_POS'))",
'visible'=>-1,
'position'=>315),
354 'pos_source' =>array(
'type'=>
'varchar(32)',
'label'=>
'POSTerminal',
'enabled'=>
"(isModEnabled('cashdesk') || isModEnabled('takepos') || getDolGlobalInt('INVOICE_SHOW_POS'))",
'visible'=>-1,
'position'=>320),
355 'datec' =>array(
'type'=>
'datetime',
'label'=>
'DateCreation',
'enabled'=>1,
'visible'=>-1,
'position'=>500),
356 'tms' =>array(
'type'=>
'timestamp',
'label'=>
'DateModificationShort',
'enabled'=>1,
'visible'=>-1,
'notnull'=>1,
'position'=>502),
357 'fk_user_author' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserAuthor',
'enabled'=>1,
'visible'=>-1,
'position'=>506),
358 'fk_user_modif' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserModif',
'enabled'=>1,
'visible'=>-1,
'notnull'=>-1,
'position'=>508),
359 'fk_user_valid' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserValidation',
'enabled'=>1,
'visible'=>-1,
'position'=>510),
360 'fk_user_closing' =>array(
'type'=>
'integer:User:user/class/user.class.php',
'label'=>
'UserClosing',
'enabled'=>1,
'visible'=>-1,
'position'=>512),
361 'import_key' =>array(
'type'=>
'varchar(14)',
'label'=>
'ImportId',
'enabled'=>1,
'visible'=>-2,
'position'=>900),
362 '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')),
424 const CLOSECODE_DISCOUNTVAT =
'discount_vat';
425 const CLOSECODE_BADDEBT =
'badcustomer';
426 const CLOSECODE_BANKCHARGE =
'bankcharge';
427 const CLOSECODE_OTHER =
'other';
429 const CLOSECODE_ABANDONED =
'abandon';
430 const CLOSECODE_REPLACED =
'replaced';
453 public function create(
User $user, $notrigger = 0, $forceduedate = 0)
455 global $langs, $conf, $mysoc, $hookmanager;
459 if (empty($this->
type)) {
463 $this->ref_client = trim($this->ref_client);
465 $this->note = (isset($this->note) ? trim($this->note) : trim($this->note_private));
466 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note_private));
467 $this->note_public = trim($this->note_public);
468 if (!$this->cond_reglement_id) {
469 $this->cond_reglement_id = 0;
471 if (!$this->mode_reglement_id) {
472 $this->mode_reglement_id = 0;
477 if (!empty($this->multicurrency_code)) {
479 if (empty($this->multicurrency_tx)) {
487 $this->fk_multicurrency = 0;
489 if (empty($this->fk_multicurrency)) {
490 $this->multicurrency_code = $conf->currency;
491 $this->fk_multicurrency = 0;
492 $this->multicurrency_tx = 1;
495 dol_syslog(get_class($this).
"::create user=".$user->id.
" date=".$this->date);
498 if (empty($this->date)) {
499 $this->error =
"Try to create an invoice with an empty parameter (date)";
500 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
504 $result = $soc->fetch($this->socid);
506 $this->error =
"Failed to fetch company: ".$soc->error;
507 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
512 $this->date_creation = $now;
516 $originaldatewhen =
null;
517 $nextdatewhen =
null;
518 $previousdaynextdatewhen =
null;
521 if ($this->fac_rec > 0) {
522 $this->fk_fac_rec_source = $this->fac_rec;
524 require_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture-rec.class.php';
526 $result = $_facrec->fetch($this->fac_rec);
527 $result = $_facrec->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 0);
530 $originaldatewhen = $_facrec->date_when;
531 $nextdatewhen =
null;
532 $previousdaynextdatewhen =
null;
533 if ($originaldatewhen) {
534 $nextdatewhen =
dol_time_plus_duree($originaldatewhen, $_facrec->frequency, $_facrec->unit_frequency);
538 if (!empty($_facrec->frequency)) {
539 $this->socid = $_facrec->socid;
541 $this->entity = $_facrec->entity;
544 $this->fk_project =
GETPOST(
'projectid',
'int') > 0 ? ((int)
GETPOST(
'projectid',
'int')) : $_facrec->fk_project;
545 $this->note_public = GETPOSTISSET(
'note_public') ?
GETPOST(
'note_public',
'restricthtml') : $_facrec->note_public;
546 $this->note_private = GETPOSTISSET(
'note_private') ?
GETPOST(
'note_private',
'restricthtml') : $_facrec->note_private;
547 $this->model_pdf = GETPOSTISSET(
'model') ?
GETPOST(
'model',
'alpha') : $_facrec->model_pdf;
548 $this->cond_reglement_id =
GETPOST(
'cond_reglement_id',
'int') > 0 ? ((int)
GETPOST(
'cond_reglement_id',
'int')) : $_facrec->cond_reglement_id;
549 $this->mode_reglement_id =
GETPOST(
'mode_reglement_id',
'int') > 0 ? ((int)
GETPOST(
'mode_reglement_id',
'int')) : $_facrec->mode_reglement_id;
550 $this->fk_account =
GETPOST(
'fk_account') > 0 ? ((int)
GETPOST(
'fk_account')) : $_facrec->fk_account;
553 $this->total_ht = $_facrec->total_ht;
554 $this->total_ttc = $_facrec->total_ttc;
559 $this->fk_incoterms = $_facrec->fk_incoterms;
560 $this->location_incoterms = $_facrec->location_incoterms;
566 $this->ref_client = trim($this->ref_client);
567 $this->ref_customer = trim($this->ref_customer);
568 $this->note_public = trim($this->note_public);
569 $this->note_private = trim($this->note_private);
570 $this->note_private =
dol_concatdesc($this->note_private, $langs->trans(
"GeneratedFromRecurringInvoice", $_facrec->ref));
572 $this->array_options = $_facrec->array_options;
574 if (!$this->mode_reglement_id) {
575 $this->mode_reglement_id = 0;
580 $this->linked_objects = $_facrec->linkedObjectsIds;
585 if ($_facrec->frequency > 0) {
586 dol_syslog(
"This is a recurring invoice so we set date_last_gen and next date_when");
587 if (empty($_facrec->date_when)) {
588 $_facrec->date_when = $now;
590 $next_date = $_facrec->getNextDate();
591 $result = $_facrec->setValueFrom(
'date_last_gen', $now,
'',
null,
'date',
'', $user,
'');
593 $result = $_facrec->setNextDate($next_date, 1);
597 $outputlangs = $langs;
600 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && empty($newlang) && isset($this->thirdparty->default_lang)) {
601 $newlang = $this->thirdparty->default_lang;
603 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && empty($newlang) && isset($this->default_lang)) {
604 $newlang = $this->default_lang;
606 if (!empty($newlang)) {
608 $outputlangs->setDefaultLang($newlang);
614 $substitutionarray[
'__INVOICE_MONTH__'] =
dol_print_date($this->date,
'%m');
617 $substitutionarray[
'__INVOICE_MONTH_TEXT__'] =
dol_print_date($this->date,
'%B');
620 $substitutionarray[
'__INVOICE_YEAR__'] =
dol_print_date($this->date,
'%Y');
623 $substitutionarray[
'__INVOICE_DATE_NEXT_INVOICE_BEFORE_GEN__'] = (isset($originaldatewhen) ?
dol_print_date($originaldatewhen,
'dayhour') :
'');
624 $substitutionarray[
'__INVOICE_DATE_NEXT_INVOICE_AFTER_GEN__'] = (isset($nextdatewhen) ?
dol_print_date($nextdatewhen,
'dayhour') :
'');
625 $substitutionarray[
'__INVOICE_PREVIOUS_DATE_NEXT_INVOICE_AFTER_GEN__'] = (isset($previousdaynextdatewhen) ?
dol_print_date($previousdaynextdatewhen,
'dayhour') :
'');
626 $substitutionarray[
'__INVOICE_COUNTER_CURRENT__'] = $_facrec->nb_gen_done;
627 $substitutionarray[
'__INVOICE_COUNTER_MAX__'] = $_facrec->nb_gen_max;
638 if (empty($forceduedate)) {
644 $this->date_lim_reglement = $duedate;
646 $this->date_lim_reglement = $forceduedate;
650 $socid = $this->socid;
652 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"facture (";
661 $sql .=
", date_pointoftax";
662 $sql .=
", note_private";
663 $sql .=
", note_public";
664 $sql .=
", ref_client";
665 $sql .=
", fk_account";
666 $sql .=
", module_source, pos_source, fk_fac_rec_source, fk_facture_source, fk_user_author, fk_projet";
667 $sql .=
", fk_cond_reglement, fk_mode_reglement, date_lim_reglement, model_pdf";
668 $sql .=
", situation_cycle_ref, situation_counter, situation_final";
669 $sql .=
", fk_incoterms, location_incoterms";
670 $sql .=
", fk_multicurrency";
671 $sql .=
", multicurrency_code";
672 $sql .=
", multicurrency_tx";
673 $sql .=
", retained_warranty";
674 $sql .=
", retained_warranty_date_limit";
675 $sql .=
", retained_warranty_fk_cond_reglement";
679 $sql .=
", ".setEntity($this);
680 $sql .=
", ".($this->ref_ext ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null");
681 $sql .=
", '".$this->db->escape($this->
type).
"'";
682 $sql .=
", ".($this->subtype ?
"'".$this->db->escape($this->subtype).
"'" :
"null");
683 $sql .=
", ".((int) $socid);
684 $sql .=
", '".$this->db->idate($this->date_creation).
"'";
685 $sql .=
", '".$this->db->idate($this->date).
"'";
686 $sql .=
", ".(empty($this->date_pointoftax) ?
"null" :
"'".$this->db->idate($this->date_pointoftax).
"'");
687 $sql .=
", ".($this->note_private ?
"'".$this->db->escape($this->note_private).
"'" :
"null");
688 $sql .=
", ".($this->note_public ?
"'".$this->db->escape($this->note_public).
"'" :
"null");
689 $sql .=
", ".($this->ref_customer ?
"'".$this->db->escape($this->ref_customer).
"'" : ($this->ref_client ?
"'".$this->db->escape($this->ref_client).
"'" :
"null"));
690 $sql .=
", ".($this->fk_account > 0 ? $this->fk_account :
'NULL');
691 $sql .=
", ".($this->module_source ?
"'".$this->db->escape($this->module_source).
"'" :
"null");
692 $sql .=
", ".($this->pos_source !=
'' ?
"'".$this->db->escape($this->pos_source).
"'" :
"null");
693 $sql .=
", ".($this->fk_fac_rec_source ?
"'".$this->db->escape($this->fk_fac_rec_source).
"'" :
"null");
694 $sql .=
", ".($this->fk_facture_source ?
"'".$this->db->escape($this->fk_facture_source).
"'" :
"null");
695 $sql .=
", ".($user->id > 0 ? (int) $user->id :
"null");
696 $sql .=
", ".($this->fk_project ? $this->fk_project :
"null");
697 $sql .=
", ".((int) $this->cond_reglement_id);
698 $sql .=
", ".((int) $this->mode_reglement_id);
699 $sql .=
", '".$this->db->idate($this->date_lim_reglement).
"'";
700 $sql .=
", ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null");
701 $sql .=
", ".($this->situation_cycle_ref ?
"'".$this->db->escape($this->situation_cycle_ref).
"'" :
"null");
702 $sql .=
", ".($this->situation_counter ?
"'".$this->db->escape($this->situation_counter).
"'" :
"null");
703 $sql .=
", ".($this->situation_final ? $this->situation_final : 0);
704 $sql .=
", ".(int) $this->fk_incoterms;
705 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
706 $sql .=
", ".(int) $this->fk_multicurrency;
707 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
708 $sql .=
", ".(float) $this->multicurrency_tx;
709 $sql .=
", ".(empty($this->retained_warranty) ?
"0" : $this->db->escape($this->retained_warranty));
710 $sql .=
", ".(!empty($this->retained_warranty_date_limit) ?
"'".$this->db->idate($this->retained_warranty_date_limit).
"'" :
'NULL');
711 $sql .=
", ".(int) $this->retained_warranty_fk_cond_reglement;
714 $resql = $this->db->query($sql);
716 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
'facture');
719 $this->
ref =
'(PROV'.$this->id.
')';
720 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"facture SET ref='".$this->db->escape($this->
ref).
"' WHERE rowid=".((int) $this->
id);
722 $resql = $this->db->query($sql);
727 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {
728 $this->linked_objects = $this->linkedObjectsIds;
732 if (!$error && $this->
id && !empty($this->linked_objects) && is_array($this->linked_objects)) {
733 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
734 if (is_array($tmp_origin_id)) {
735 foreach ($tmp_origin_id as $origin_id) {
738 $this->error = $this->db->lasterror();
743 $origin_id = $tmp_origin_id;
746 $this->error = $this->db->lasterror();
754 if (!$error && $this->
id &&
getDolGlobalString(
'MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN') && !empty($this->origin) && !empty($this->origin_id)) {
755 $originforcontact = $this->origin;
756 $originidforcontact = $this->origin_id;
757 if ($originforcontact ==
'shipping') {
758 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expedition.class.php';
760 $exp->fetch($this->origin_id);
761 $exp->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 0);
762 if (count($exp->linkedObjectsIds[
'commande']) > 0) {
763 foreach ($exp->linkedObjectsIds[
'commande'] as $key => $value) {
764 $originforcontact =
'commande';
765 if (is_object($value)) {
766 $originidforcontact = $value->id;
768 $originidforcontact = $value;
775 $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";
776 $sqlcontact .=
" WHERE element_id = ".((int) $originidforcontact).
" AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$this->db->escape($originforcontact).
"'";
778 $resqlcontact = $this->db->query($sqlcontact);
780 while ($objcontact = $this->db->fetch_object($resqlcontact)) {
782 $this->
add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source);
792 if (!$error && empty($this->fac_rec) && count($this->lines) && is_object($this->lines[0])) {
795 dol_syslog(
"There is ".count($this->lines).
" lines into ->lines that are InvoiceLines");
796 foreach ($this->lines as $i => $val) {
797 $newinvoiceline = $this->lines[$i];
799 $newinvoiceline->context = $this->context;
801 $newinvoiceline->fk_facture = $this->id;
803 $newinvoiceline->origin = $this->lines[$i]->element;
804 $newinvoiceline->origin_id = $this->lines[$i]->id;
807 if ($this->lines[$i]->date_start_fill == 1 && $originaldatewhen) {
808 $newinvoiceline->date_start = $originaldatewhen;
810 if ($this->lines[$i]->date_end_fill == 1 && $previousdaynextdatewhen) {
811 $newinvoiceline->date_end = $previousdaynextdatewhen;
816 if (($newinvoiceline->product_type != 9 && empty($newinvoiceline->fk_parent_line)) || $newinvoiceline->product_type == 9) {
821 $vatrate = $newinvoiceline->tva_tx;
822 if ($newinvoiceline->vat_src_code && ! preg_match(
'/\(.*\)/', $vatrate)) {
823 $vatrate.=
' ('.$newinvoiceline->vat_src_code.
')';
826 $newinvoiceline->fk_parent_line = $fk_parent_line;
830 $discount->fetch($newinvoiceline->fk_remise_except);
832 $discountId = $soc->set_remise_except($discount->amount_ht, $user, $discount->description, $discount->tva_tx);
833 $newinvoiceline->fk_remise_except = $discountId;
837 $newinvoiceline->desc,
838 $newinvoiceline->subprice,
839 $newinvoiceline->qty,
841 $newinvoiceline->localtax1_tx,
842 $newinvoiceline->localtax2_tx,
843 $newinvoiceline->fk_product,
844 $newinvoiceline->remise_percent,
845 $newinvoiceline->date_start,
846 $newinvoiceline->date_end,
847 $newinvoiceline->fk_code_ventilation,
848 $newinvoiceline->info_bits,
849 $newinvoiceline->fk_remise_except,
852 $newinvoiceline->product_type,
853 $newinvoiceline->rang,
854 $newinvoiceline->special_code,
855 $newinvoiceline->element,
858 $newinvoiceline->fk_fournprice,
859 $newinvoiceline->pa_ht,
860 $newinvoiceline->label,
861 $newinvoiceline->array_options,
862 $newinvoiceline->situation_percent,
863 $newinvoiceline->fk_prev_id,
864 $newinvoiceline->fk_unit,
865 $newinvoiceline->multicurrency_subprice,
866 $newinvoiceline->ref_ext,
871 if ($result > 0 && $newinvoiceline->product_type == 9) {
872 $fk_parent_line = $result;
876 $this->error = $newinvoiceline->error;
877 $this->errors = $newinvoiceline->errors;
882 } elseif (!$error && empty($this->fac_rec)) {
885 dol_syslog(
"There is ".count($this->lines).
" lines into ->lines as a simple array");
887 foreach ($this->lines as $i => $val) {
888 $line = $this->lines[$i];
892 if (!is_object($line)) {
893 $line = (object) $line;
898 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
903 $vatrate = $line->tva_tx;
904 if ($line->vat_src_code && !preg_match(
'/\(.*\)/', $vatrate)) {
905 $vatrate .=
' ('.$line->vat_src_code.
')';
909 $originid = $line->origin_id;
910 $origintype = $line->origin;
912 $originid = $line->id;
913 $origintype = $this->element;
917 if (empty($line->ref_ext)) {
929 $line->remise_percent,
932 $line->fk_code_ventilation,
934 $line->fk_remise_except,
943 $line->fk_fournprice,
946 $line->array_options,
947 $line->situation_percent,
950 $line->multicurrency_subprice,
955 $this->error = $this->db->lasterror();
957 $this->db->rollback();
962 if ($result > 0 && $line->product_type == 9) {
963 $fk_parent_line = $result;
972 if (!$error && $this->fac_rec > 0) {
973 dol_syslog(
"There is ".count($_facrec->lines).
" lines from recurring invoice");
976 foreach ($_facrec->lines as $i => $val) {
977 if ($_facrec->lines[$i]->fk_product) {
978 $prod =
new Product($this->db);
979 $res = $prod->fetch($_facrec->lines[$i]->fk_product);
983 if (($_facrec->lines[$i]->product_type != 9 && empty($_facrec->lines[$i]->fk_parent_line)) || $_facrec->lines[$i]->product_type == 9) {
995 $tva_tx = $_facrec->lines[$i]->tva_tx.($_facrec->lines[$i]->vat_src_code ?
'('.$_facrec->lines[$i]->vat_src_code.
')' :
'');
996 $tva_npr = $_facrec->lines[$i]->info_bits;
997 if (empty($tva_tx)) {
1000 $localtax1_tx = $_facrec->lines[$i]->localtax1_tx;
1001 $localtax2_tx = $_facrec->lines[$i]->localtax2_tx;
1003 $fk_product_fournisseur_price = empty($_facrec->lines[$i]->fk_product_fournisseur_price) ? null : $_facrec->lines[$i]->fk_product_fournisseur_price;
1004 $buyprice = empty($_facrec->lines[$i]->buyprice) ? 0 : $_facrec->lines[$i]->buyprice;
1007 if (!$buyprice && $_facrec->lines[$i]->fk_product > 0) {
1008 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
1010 $producttmp->fetch($_facrec->lines[$i]->fk_product);
1015 if (
getDolGlobalString(
'MARGIN_TYPE') ==
'costprice' && !empty($producttmp->cost_price)) {
1016 $buyprice = $producttmp->cost_price;
1018 $buyprice = $producttmp->pmp;
1020 if ($producttmp->find_min_price_product_fournisseur($_facrec->lines[$i]->fk_product) > 0) {
1021 if ($producttmp->product_fourn_price_id > 0) {
1022 $buyprice =
price2num($producttmp->fourn_unitprice * (1 - $producttmp->fourn_remise_percent / 100) + $producttmp->fourn_remise,
'MU');
1028 $result_insert = $this->
addline(
1029 $_facrec->lines[$i]->desc,
1030 $_facrec->lines[$i]->subprice,
1031 $_facrec->lines[$i]->qty,
1035 $_facrec->lines[$i]->fk_product,
1036 $_facrec->lines[$i]->remise_percent,
1037 ($_facrec->lines[$i]->date_start_fill == 1 && $originaldatewhen) ? $originaldatewhen :
'',
1038 ($_facrec->lines[$i]->date_end_fill == 1 && $previousdaynextdatewhen) ? $previousdaynextdatewhen :
'',
1044 $_facrec->lines[$i]->product_type,
1045 $_facrec->lines[$i]->rang,
1046 $_facrec->lines[$i]->special_code,
1050 $fk_product_fournisseur_price,
1052 $_facrec->lines[$i]->label,
1053 empty($_facrec->lines[$i]->array_options) ? null : $_facrec->lines[$i]->array_options,
1056 $_facrec->lines[$i]->fk_unit,
1057 $_facrec->lines[$i]->multicurrency_subprice,
1058 $_facrec->lines[$i]->ref_ext,
1063 if ($result_insert > 0 && $_facrec->lines[$i]->product_type == 9) {
1064 $fk_parent_line = $result_insert;
1067 if ($result_insert < 0) {
1069 $this->error = $this->db->error();
1088 if (!$error && !$notrigger) {
1098 $this->db->commit();
1101 $this->db->rollback();
1105 $this->error = $langs->trans(
'FailedToUpdatePrice');
1106 $this->db->rollback();
1110 dol_syslog(get_class($this).
"::create error ".$this->error, LOG_ERR);
1111 $this->db->rollback();
1115 $this->error = $this->db->error();
1116 $this->db->rollback();
1134 $facture =
new Facture($this->db);
1140 if (!empty($this->array_options)) {
1141 $facture->array_options = $this->array_options;
1144 foreach ($this->lines as &$line) {
1145 $line->fetch_optionals();
1149 $facture->type = $this->type;
1150 $facture->subtype = $this->subtype;
1151 $facture->socid = $this->socid;
1152 $facture->date = $this->date;
1153 $facture->date_pointoftax = $this->date_pointoftax;
1154 $facture->note_public = $this->note_public;
1155 $facture->note_private = $this->note_private;
1156 $facture->ref_client = $this->ref_client;
1157 $facture->model_pdf = $this->model_pdf;
1158 $facture->fk_project = $this->fk_project;
1159 $facture->cond_reglement_id = $this->cond_reglement_id;
1160 $facture->mode_reglement_id = $this->mode_reglement_id;
1164 $facture->origin = $this->origin;
1165 $facture->origin_id = $this->origin_id;
1166 $facture->fk_account = $this->fk_account;
1168 $facture->lines = $this->lines;
1169 $facture->situation_counter = $this->situation_counter;
1170 $facture->situation_cycle_ref = $this->situation_cycle_ref;
1171 $facture->situation_final = $this->situation_final;
1173 $facture->retained_warranty = $this->retained_warranty;
1174 $facture->retained_warranty_fk_cond_reglement = $this->retained_warranty_fk_cond_reglement;
1175 $facture->retained_warranty_date_limit = $this->retained_warranty_date_limit;
1177 $facture->fk_user_author = $user->id;
1181 foreach ($facture->lines as $i => $tmpline) {
1182 $facture->lines[$i]->fk_prev_id = $this->lines[$i]->rowid;
1183 if ($invertdetail) {
1184 $facture->lines[$i]->subprice = -$facture->lines[$i]->subprice;
1185 $facture->lines[$i]->total_ht = -$facture->lines[$i]->total_ht;
1186 $facture->lines[$i]->total_tva = -$facture->lines[$i]->total_tva;
1187 $facture->lines[$i]->total_localtax1 = -$facture->lines[$i]->total_localtax1;
1188 $facture->lines[$i]->total_localtax2 = -$facture->lines[$i]->total_localtax2;
1189 $facture->lines[$i]->total_ttc = -$facture->lines[$i]->total_ttc;
1190 $facture->lines[$i]->ref_ext =
'';
1194 dol_syslog(get_class($this).
"::createFromCurrent invertdetail=".$invertdetail.
" socid=".$this->socid.
" nboflines=".count($facture->lines));
1196 $facid = $facture->create($user);
1198 $this->error = $facture->error;
1199 $this->errors = $facture->errors;
1203 foreach ($this->linkedObjectsIds as $typeObject => $Tfk_object) {
1204 foreach ($Tfk_object as $fk_object) {
1205 $facture->add_object_linked($typeObject, $fk_object);
1209 $facture->add_object_linked(
'facture', $this->fk_facture_source);
1225 global $conf, $hookmanager;
1229 $object =
new Facture($this->db);
1233 $object->fetch($fromid);
1236 $objFrom = clone $object;
1239 if (!empty($this->socid) && $this->socid != $object->socid) {
1240 $objsoc =
new Societe($this->db);
1242 if ($objsoc->fetch($this->socid) > 0) {
1243 $object->socid = $objsoc->id;
1244 $object->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1245 $object->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1246 $object->fk_project =
'';
1247 $object->fk_delivery_address =
'';
1258 $object->date = (empty($this->date) ?
dol_now() : $this->date);
1259 $object->user_creation_id = $user->id;
1260 $object->user_validation_id =
null;
1261 $object->fk_user_author = $user->id;
1262 $object->fk_user_valid =
null;
1263 $object->fk_facture_source = 0;
1264 $object->date_creation =
'';
1265 $object->date_modification =
'';
1266 $object->date_validation =
'';
1267 $object->ref_client =
'';
1268 $object->close_code =
'';
1269 $object->close_note =
'';
1271 $object->note_private =
'';
1272 $object->note_public =
'';
1276 foreach ($object->lines as $i => $line) {
1277 if (($object->lines[$i]->info_bits & 0x02) == 0x02) {
1278 unset($object->lines[$i]);
1284 if (
getDolGlobalString(
'INVOICE_AUTO_NEXT_MONTH_ON_LINES') && !empty($line->date_start) && !empty($line->date_end)) {
1296 if (
dol_mktime(0, 0, 0, $start[
'mon'], $start[
'mday'], $start[
'year'],
'gmt') == $first
1297 &&
dol_mktime(23, 59, 59, $end[
'mon'], $end[
'mday'], $end[
'year'],
'gmt') == $last) {
1301 $object->lines[$i]->date_start = $newFirst;
1302 $object->lines[$i]->date_end = $newLast;
1306 $object->lines[$i]->ref_ext =
'';
1310 $object->context[
'createfromclone'] =
'createfromclone';
1311 $result = $object->create($user);
1314 $this->error = $object->error;
1315 $this->errors = $object->errors;
1318 if ($object->copy_linked_contact($objFrom,
'internal') < 0) {
1320 $this->error = $object->error;
1321 $this->errors = $object->errors;
1322 } elseif ($object->socid == $objFrom->socid) {
1324 if ($object->copy_linked_contact($objFrom,
'external') < 0) {
1326 $this->error = $object->error;
1327 $this->errors = $object->errors;
1334 if (is_object($hookmanager)) {
1335 $parameters = array(
'objFrom'=>$objFrom);
1337 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $object, $action);
1345 unset($object->context[
'createfromclone']);
1349 $this->db->commit();
1352 $this->db->rollback();
1366 global $conf, $hookmanager;
1374 $num = count($object->lines);
1375 for ($i = 0; $i < $num; $i++) {
1378 $line->libelle = $object->lines[$i]->libelle;
1379 $line->label = $object->lines[$i]->label;
1380 $line->desc = $object->lines[$i]->desc;
1381 $line->subprice = $object->lines[$i]->subprice;
1382 $line->total_ht = $object->lines[$i]->total_ht;
1383 $line->total_tva = $object->lines[$i]->total_tva;
1384 $line->total_localtax1 = $object->lines[$i]->total_localtax1;
1385 $line->total_localtax2 = $object->lines[$i]->total_localtax2;
1386 $line->total_ttc = $object->lines[$i]->total_ttc;
1387 $line->vat_src_code = $object->lines[$i]->vat_src_code;
1388 $line->tva_tx = $object->lines[$i]->tva_tx;
1389 $line->localtax1_tx = $object->lines[$i]->localtax1_tx;
1390 $line->localtax2_tx = $object->lines[$i]->localtax2_tx;
1391 $line->qty = $object->lines[$i]->qty;
1392 $line->fk_remise_except = $object->lines[$i]->fk_remise_except;
1393 $line->remise_percent = $object->lines[$i]->remise_percent;
1394 $line->fk_product = $object->lines[$i]->fk_product;
1395 $line->info_bits = $object->lines[$i]->info_bits;
1396 $line->product_type = $object->lines[$i]->product_type;
1397 $line->rang = $object->lines[$i]->rang;
1398 $line->special_code = $object->lines[$i]->special_code;
1399 $line->fk_parent_line = $object->lines[$i]->fk_parent_line;
1400 $line->fk_unit = $object->lines[$i]->fk_unit;
1401 $line->date_start = $object->lines[$i]->date_start;
1402 $line->date_end = $object->lines[$i]->date_end;
1405 $line->fk_multicurrency = $object->lines[$i]->fk_multicurrency;
1406 $line->multicurrency_code = $object->lines[$i]->multicurrency_code;
1407 $line->multicurrency_subprice = $object->lines[$i]->multicurrency_subprice;
1408 $line->multicurrency_total_ht = $object->lines[$i]->multicurrency_total_ht;
1409 $line->multicurrency_total_tva = $object->lines[$i]->multicurrency_total_tva;
1410 $line->multicurrency_total_ttc = $object->lines[$i]->multicurrency_total_ttc;
1412 $line->fk_fournprice = $object->lines[$i]->fk_fournprice;
1413 $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);
1414 $line->pa_ht = $marginInfos[0];
1417 $object->lines[$i]->fetch_optionals();
1418 foreach ($object->lines[$i]->array_options as $options_key => $value) {
1419 $line->array_options[$options_key] = $value;
1422 $this->lines[$i] = $line;
1425 $this->socid = $object->socid;
1426 $this->fk_project = $object->fk_project;
1427 $this->fk_account = $object->fk_account;
1428 $this->cond_reglement_id = $object->cond_reglement_id;
1429 $this->mode_reglement_id = $object->mode_reglement_id;
1430 $this->availability_id = $object->availability_id;
1431 $this->demand_reason_id = $object->demand_reason_id;
1432 $this->delivery_date = $object->delivery_date;
1433 $this->fk_delivery_address = $object->fk_delivery_address;
1434 $this->contact_id = $object->contact_id;
1435 $this->ref_client = $object->ref_client;
1438 $this->note_private = $object->note_private;
1439 $this->note_public = $object->note_public;
1442 $this->module_source = $object->module_source;
1443 $this->pos_source = $object->pos_source;
1445 $this->origin = $object->element;
1446 $this->origin_id = $object->id;
1448 $this->fk_user_author = $user->id;
1451 $object->fetch_optionals();
1452 foreach ($object->array_options as $options_key => $value) {
1453 $this->array_options[$options_key] = $value;
1457 $this->linked_objects[$this->origin] = $this->origin_id;
1458 if (!empty($object->other_linked_objects) && is_array($object->other_linked_objects)) {
1459 $this->linked_objects = array_merge($this->linked_objects, $object->other_linked_objects);
1462 $ret = $this->
create($user);
1466 $hookmanager->initHooks(array(
'invoicedao'));
1468 $parameters = array(
'objFrom'=>$object);
1470 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $this, $action);
1496 global $conf, $hookmanager;
1504 $use_all_lines = empty($lines);
1505 $num = count($object->lines);
1506 for ($i = 0; $i < $num; $i++) {
1507 if (!$use_all_lines && !in_array($object->lines[$i]->id, $lines)) {
1513 $line->libelle = $object->lines[$i]->libelle;
1514 $line->label = $object->lines[$i]->label;
1515 $line->desc = $object->lines[$i]->desc;
1516 $line->subprice = $object->lines[$i]->subprice;
1517 $line->total_ht = $object->lines[$i]->total_ht;
1518 $line->total_tva = $object->lines[$i]->total_tva;
1519 $line->total_localtax1 = $object->lines[$i]->total_localtax1;
1520 $line->total_localtax2 = $object->lines[$i]->total_localtax2;
1521 $line->total_ttc = $object->lines[$i]->total_ttc;
1522 $line->vat_src_code = $object->lines[$i]->vat_src_code;
1523 $line->tva_tx = $object->lines[$i]->tva_tx;
1524 $line->localtax1_tx = $object->lines[$i]->localtax1_tx;
1525 $line->localtax2_tx = $object->lines[$i]->localtax2_tx;
1526 $line->qty = $object->lines[$i]->qty;
1527 $line->fk_remise_except = $object->lines[$i]->fk_remise_except;
1528 $line->remise_percent = $object->lines[$i]->remise_percent;
1529 $line->fk_product = $object->lines[$i]->fk_product;
1530 $line->info_bits = $object->lines[$i]->info_bits;
1531 $line->product_type = $object->lines[$i]->product_type;
1532 $line->rang = $object->lines[$i]->rang;
1533 $line->special_code = $object->lines[$i]->special_code;
1534 $line->fk_parent_line = $object->lines[$i]->fk_parent_line;
1535 $line->fk_unit = $object->lines[$i]->fk_unit;
1536 $line->date_start = $object->lines[$i]->date_start;
1537 $line->date_end = $object->lines[$i]->date_end;
1540 $line->fk_multicurrency = $object->lines[$i]->fk_multicurrency;
1541 $line->multicurrency_code = $object->lines[$i]->multicurrency_code;
1542 $line->multicurrency_subprice = $object->lines[$i]->multicurrency_subprice;
1543 $line->multicurrency_total_ht = $object->lines[$i]->multicurrency_total_ht;
1544 $line->multicurrency_total_tva = $object->lines[$i]->multicurrency_total_tva;
1545 $line->multicurrency_total_ttc = $object->lines[$i]->multicurrency_total_ttc;
1547 $line->fk_fournprice = $object->lines[$i]->fk_fournprice;
1548 $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);
1549 $line->pa_ht = $marginInfos[0];
1552 $object->lines[$i]->fetch_optionals();
1553 foreach ($object->lines[$i]->array_options as $options_key => $value) {
1554 $line->array_options[$options_key] = $value;
1557 $this->lines[$i] = $line;
1560 $this->socid = $object->socid;
1561 $this->fk_project = $object->fk_project;
1562 $this->fk_account = $object->fk_account;
1563 $this->cond_reglement_id = $object->cond_reglement_id;
1564 $this->mode_reglement_id = $object->mode_reglement_id;
1565 $this->availability_id = $object->availability_id;
1566 $this->demand_reason_id = $object->demand_reason_id;
1567 $this->delivery_date = $object->delivery_date;
1568 $this->fk_delivery_address = $object->fk_delivery_address;
1569 $this->contact_id = $object->contact_id;
1570 $this->ref_client = $object->ref_client;
1573 $this->note_private = $object->note_private;
1574 $this->note_public = $object->note_public;
1577 $this->module_source = $object->module_source;
1578 $this->pos_source = $object->pos_source;
1580 $this->origin = $object->element;
1581 $this->origin_id = $object->id;
1583 $this->fk_user_author = $user->id;
1586 $object->fetch_optionals();
1587 foreach ($object->array_options as $options_key => $value) {
1588 $this->array_options[$options_key] = $value;
1592 $this->linked_objects[$this->origin] = $this->origin_id;
1593 if (!empty($object->other_linked_objects) && is_array($object->other_linked_objects)) {
1594 $this->linked_objects = array_merge($this->linked_objects, $object->other_linked_objects);
1597 $ret = $this->
create($user);
1601 $hookmanager->initHooks(array(
'invoicedao'));
1603 $parameters = array(
'objFrom'=>$object);
1605 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $this, $action);
1635 global $conf, $langs, $hookmanager, $action;
1637 if (! in_array($origin->element, array(
'propal',
'commande'))) {
1638 $origin->error =
'ErrorCanOnlyAutomaticallyGenerateADepositFromProposalOrOrder';
1643 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'DateInvoice'));
1647 require_once DOL_DOCUMENT_ROOT .
'/core/lib/date.lib.php';
1650 $origin->error =
'ErrorDateIsInFuture';
1654 if ($payment_terms_id <= 0) {
1655 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'PaymentConditionsShort'));
1659 $payment_conditions_deposit_percent =
getDictionaryValue(
'c_payment_term',
'deposit_percent', $origin->cond_reglement_id);
1661 if (empty($payment_conditions_deposit_percent)) {
1662 $origin->error =
'ErrorPaymentConditionsNotEligibleToDepositCreation';
1666 if (empty($origin->deposit_percent)) {
1667 $origin->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentities(
'DepositPercent'));
1671 $deposit =
new self($origin->db);
1672 $deposit->socid = $origin->socid;
1674 $deposit->fk_project = $origin->fk_project;
1675 $deposit->ref_client = $origin->ref_client;
1676 $deposit->date = $date;
1677 $deposit->mode_reglement_id = $origin->mode_reglement_id;
1678 $deposit->cond_reglement_id = $payment_terms_id;
1679 $deposit->availability_id = $origin->availability_id;
1680 $deposit->demand_reason_id = $origin->demand_reason_id;
1681 $deposit->fk_account = $origin->fk_account;
1682 $deposit->fk_incoterms = $origin->fk_incoterms;
1683 $deposit->location_incoterms = $origin->location_incoterms;
1684 $deposit->fk_multicurrency = $origin->fk_multicurrency;
1685 $deposit->multicurrency_code = $origin->multicurrency_code;
1686 $deposit->multicurrency_tx = $origin->multicurrency_tx;
1687 $deposit->module_source = $origin->module_source;
1688 $deposit->pos_source = $origin->pos_source;
1689 $deposit->model_pdf =
'crabe';
1691 $modelByTypeConfName =
'FACTURE_ADDON_PDF_' . $deposit->type;
1700 $deposit->note_private = $origin->note_private;
1701 $deposit->note_public = $origin->note_public;
1704 $deposit->origin = $origin->element;
1705 $deposit->origin_id = $origin->id;
1707 $origin->fetch_optionals();
1709 foreach ($origin->array_options as $extrakey => $value) {
1710 $deposit->array_options[$extrakey] = $value;
1713 $deposit->linked_objects[$deposit->origin] = $deposit->origin_id;
1715 foreach ($overrideFields as $key => $value) {
1716 $deposit->$key = $value;
1719 $deposit->context[
'createdepositfromorigin'] =
'createdepositfromorigin';
1721 $origin->db->begin();
1724 $createReturn = $deposit->create($user, $notrigger);
1726 if ($createReturn <= 0) {
1727 $origin->db->rollback();
1728 $origin->error = $deposit->error;
1729 $origin->errors = $deposit->errors;
1733 $amount_ttc_diff = 0;
1734 $amountdeposit = array();
1735 $descriptions = array();
1738 $amount = $origin->total_ttc * ($origin->deposit_percent / 100);
1740 $TTotalByTva = array();
1741 foreach ($origin->lines as &$line) {
1742 if (!empty($line->special_code)) {
1745 $TTotalByTva[$line->tva_tx] += $line->total_ttc;
1746 $descriptions[$line->tva_tx] .=
'<li>' . (!empty($line->product_ref) ? $line->product_ref .
' - ' :
'');
1747 $descriptions[$line->tva_tx] .= (!empty($line->product_label) ? $line->product_label .
' - ' :
'');
1748 $descriptions[$line->tva_tx] .= $langs->trans(
'Qty') .
' : ' . $line->qty;
1749 $descriptions[$line->tva_tx] .=
' - ' . $langs->trans(
'TotalHT') .
' : ' .
price($line->total_ht) .
'</li>';
1752 foreach ($TTotalByTva as $tva => &$total) {
1753 $coef = $total / $origin->total_ttc;
1754 $am = $amount * $coef;
1755 $amount_ttc_diff += $am;
1756 $amountdeposit[$tva] += $am / (1 + $tva / 100);
1760 $lines = $origin->lines;
1761 $numlines = count($lines);
1762 for ($i = 0; $i < $numlines; $i++) {
1763 if (empty($lines[$i]->qty)) {
1766 if (!empty($lines[$i]->special_code)) {
1770 $totalamount += $lines[$i]->total_ht;
1771 $tva_tx = $lines[$i]->tva_tx;
1772 $amountdeposit[$tva_tx] += ($lines[$i]->total_ht * $origin->deposit_percent) / 100;
1773 $descriptions[$tva_tx] .=
'<li>' . (!empty($lines[$i]->product_ref) ? $lines[$i]->product_ref .
' - ' :
'');
1774 $descriptions[$tva_tx] .= (!empty($lines[$i]->product_label) ? $lines[$i]->product_label .
' - ' :
'');
1775 $descriptions[$tva_tx] .= $langs->trans(
'Qty') .
' : ' . $lines[$i]->qty;
1776 $descriptions[$tva_tx] .=
' - ' . $langs->trans(
'TotalHT') .
' : ' .
price($lines[$i]->total_ht) .
'</li>';
1779 if ($totalamount == 0) {
1780 $amountdeposit[0] = 0;
1783 $amount_ttc_diff = $amountdeposit[0];
1786 foreach ($amountdeposit as $tva => $amount) {
1787 if (empty($amount)) {
1791 $descline =
'(DEPOSIT) ('. $origin->deposit_percent .
'%) - '.$origin->ref;
1794 if (
getDolGlobalString(
'INVOICE_DEPOSIT_VARIABLE_MODE_DETAIL_LINES_IN_DESCRIPTION') && !empty($descriptions[$tva])) {
1795 $descline .=
'<ul>' . $descriptions[$tva] .
'</ul>';
1798 $addlineResult = $deposit->addline(
1805 (!
getDolGlobalString(
'INVOICE_PRODUCTID_DEPOSIT') ? 0 : $conf->global->INVOICE_PRODUCTID_DEPOSIT),
1825 if ($addlineResult < 0) {
1826 $origin->db->rollback();
1827 $origin->error = $deposit->error;
1828 $origin->errors = $deposit->errors;
1833 $diff = $deposit->total_ttc - $amount_ttc_diff;
1836 $deposit->fetch_lines();
1837 $subprice_diff = $deposit->lines[0]->subprice - $diff / (1 + $deposit->lines[0]->tva_tx / 100);
1839 $updatelineResult = $deposit->updateline(
1840 $deposit->lines[0]->id,
1841 $deposit->lines[0]->desc,
1843 $deposit->lines[0]->qty,
1844 $deposit->lines[0]->remise_percent,
1845 $deposit->lines[0]->date_start,
1846 $deposit->lines[0]->date_end,
1847 $deposit->lines[0]->tva_tx,
1851 $deposit->lines[0]->info_bits,
1852 $deposit->lines[0]->product_type,
1856 $deposit->lines[0]->pa_ht,
1857 $deposit->lines[0]->label,
1863 if ($updatelineResult < 0) {
1864 $origin->db->rollback();
1865 $origin->error = $deposit->error;
1866 $origin->errors = $deposit->errors;
1871 $hookmanager->initHooks(array(
'invoicedao'));
1873 $parameters = array(
'objFrom' => $origin);
1874 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $deposit, $action);
1877 $origin->db->rollback();
1878 $origin->error = $hookmanager->error;
1879 $origin->errors = $hookmanager->errors;
1883 if (!empty($autoValidateDeposit)) {
1884 $validateReturn = $deposit->validate($user,
'', 0, $notrigger);
1886 if ($validateReturn < 0) {
1887 $origin->db->rollback();
1888 $origin->error = $deposit->error;
1889 $origin->errors = $deposit->errors;
1894 unset($deposit->context[
'createdepositfromorigin']);
1896 $origin->db->commit();
1910 global $conf, $langs, $mysoc, $user;
1912 $langs->load(
'bills');
1915 $moretitle = $params[
'moretitle'] ??
'';
1916 $picto = $this->picto;
1917 if ($this->
type == self::TYPE_REPLACEMENT) {
1920 if ($this->
type == self::TYPE_CREDIT_NOTE) {
1923 if ($this->
type == self::TYPE_DEPOSIT) {
1927 if ($user->hasRight(
"facture",
"read")) {
1928 $datas[
'picto'] =
img_picto(
'', $picto).
' <u class="paddingrightonly">'.$langs->trans(
"Invoice").
'</u>';
1930 $datas[
'picto'] .=
' '.$this->getLibType(1);
1933 if (!empty($params[
'fromajaxtooltip']) && !isset($this->alreadypaid)) {
1937 if (isset($this->
status) && isset($this->alreadypaid)) {
1938 $datas[
'picto'] .=
' '.$this->getLibStatut(5, $this->alreadypaid);
1941 $datas[
'picto'] .=
' - '.$moretitle;
1943 if (!empty($this->
ref)) {
1944 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
1946 if (!empty($this->ref_customer)) {
1947 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.$this->ref_customer;
1949 if (!empty($this->date)) {
1950 $datas[
'date'] =
'<br><b>'.$langs->trans(
'Date').
':</b> '.
dol_print_date($this->date,
'day');
1952 if (!empty($this->total_ht)) {
1953 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
1955 if (!empty($this->total_tva)) {
1956 $datas[
'amountvat'] =
'<br><b>'.$langs->trans(
'AmountVAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
1958 if (!empty($this->revenuestamp) && $this->revenuestamp != 0) {
1959 $datas[
'amountrevenustamp'] =
'<br><b>'.$langs->trans(
'RevenueStamp').
':</b> '.
price($this->revenuestamp, 0, $langs, 0, -1, -1, $conf->currency);
1961 if (!empty($this->total_localtax1) && $this->total_localtax1 != 0) {
1963 $datas[
'amountlt1'] =
'<br><b>'.$langs->transcountry(
'AmountLT1', $mysoc->country_code).
':</b> '.
price($this->total_localtax1, 0, $langs, 0, -1, -1, $conf->currency);
1965 if (!empty($this->total_localtax2) && $this->total_localtax2 != 0) {
1966 $datas[
'amountlt2'] =
'<br><b>'.$langs->transcountry(
'AmountLT2', $mysoc->country_code).
':</b> '.
price($this->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency);
1968 if (!empty($this->total_ttc)) {
1969 $datas[
'amountttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
1990 public function getNomUrl($withpicto = 0, $option =
'', $max = 0, $short = 0, $moretitle =
'', $notooltip = 0, $addlinktonotes = 0, $save_lastsearch_value = -1, $target =
'')
1992 global $langs, $conf, $user, $mysoc;
1994 if (!empty($conf->dol_no_mouse_hover)) {
2000 if ($option ==
'withdraw') {
2001 $url = DOL_URL_ROOT.
'/compta/facture/prelevement.php?facid='.$this->id;
2003 $url = DOL_URL_ROOT.
'/compta/facture/card.php?facid='.$this->id;
2006 if (!$user->hasRight(
"facture",
"read")) {
2010 if ($option !==
'nolink') {
2012 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2013 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
2014 $add_save_lastsearch_values = 1;
2016 if ($add_save_lastsearch_values) {
2017 $url .=
'&save_lastsearch_values=1';
2025 $picto = $this->picto;
2026 if ($this->
type == self::TYPE_REPLACEMENT) {
2029 if ($this->
type == self::TYPE_CREDIT_NOTE) {
2032 if ($this->
type == self::TYPE_DEPOSIT) {
2037 'objecttype' => $this->element,
2038 'moretitle' => $moretitle,
2039 'option' => $option,
2041 $classfortooltip =
'classfortooltip';
2044 $classfortooltip =
'classforajaxtooltip';
2045 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
2051 $linkclose = ($target ?
' target="'.$target.
'"' :
'');
2052 if (empty($notooltip) && $user->hasRight(
"facture",
"read")) {
2054 $label = $langs->trans(
"Invoice");
2055 $linkclose .=
' alt="'.dol_escape_htmltag($label, 1).
'"';
2057 $linkclose .= ($label ?
' title="'.dol_escape_htmltag($label, 1).
'"' :
' title="tocomplete"');
2058 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
2061 $linkstart =
'<a href="'.$url.
'"';
2062 $linkstart .= $linkclose.
'>';
2065 if ($option ==
'nolink') {
2070 $result .= $linkstart;
2072 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), ($notooltip ? (($withpicto != 2) ?
'class="paddingright"' :
'') :
'class="'.(($withpicto != 2) ?
'paddingright ' :
'').
'"'), 0, 0, $notooltip ? 0 : 1);
2074 if ($withpicto != 2) {
2075 $result .= ($max ?
dol_trunc($this->
ref, $max) : $this->ref);
2077 $result .= $linkend;
2079 if ($addlinktonotes) {
2080 $txttoshow = ($user->socid > 0 ? $this->note_public : $this->note_private);
2083 $notetoshow = $langs->trans(
"ViewPrivateNote").
':<br>'.$txttoshow;
2084 $result .=
' <span class="note inline-block">';
2085 $result .=
'<a href="'.DOL_URL_ROOT.
'/compta/facture/note.php?id='.$this->
id.
'" class="classfortooltip" title="'.
dol_escape_htmltag($notetoshow, 1, 1).
'">';
2090 $result .=
'</span>';
2094 global $action, $hookmanager;
2095 $hookmanager->initHooks(array(
'invoicedao'));
2096 $parameters = array(
'id'=>$this->
id,
'getnomurl' => &$result,
'notooltip' => $notooltip,
'addlinktonotes' => $addlinktonotes,
'save_lastsearch_value'=> $save_lastsearch_value,
'target' => $target);
2097 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
2099 $result = $hookmanager->resPrint;
2101 $result .= $hookmanager->resPrint;
2117 public function fetch($rowid, $ref =
'', $ref_ext =
'', $notused = 0, $fetch_situation =
false)
2119 if (empty($rowid) && empty($ref) && empty($ref_ext)) {
2123 $sql =
'SELECT f.rowid, f.entity, f.ref, f.ref_client, f.ref_ext, f.type, f.subtype, f.fk_soc';
2124 $sql .=
', f.total_tva, f.localtax1, f.localtax2, f.total_ht, f.total_ttc, f.revenuestamp';
2125 $sql .=
', f.datef as df, f.date_pointoftax';
2126 $sql .=
', f.date_lim_reglement as dlr';
2127 $sql .=
', f.datec as datec';
2128 $sql .=
', f.date_valid as datev';
2129 $sql .=
', f.tms as datem';
2130 $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';
2131 $sql .=
', f.fk_facture_source, f.fk_fac_rec_source';
2132 $sql .=
', f.fk_mode_reglement, f.fk_cond_reglement, f.fk_projet as fk_project, f.extraparams';
2133 $sql .=
', f.situation_cycle_ref, f.situation_counter, f.situation_final';
2134 $sql .=
', f.fk_account';
2135 $sql .=
", f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc";
2136 $sql .=
', p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
2137 $sql .=
', c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_doc';
2138 $sql .=
', f.fk_incoterms, f.location_incoterms';
2139 $sql .=
', f.module_source, f.pos_source';
2140 $sql .=
", i.libelle as label_incoterms";
2141 $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";
2142 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facture as f';
2143 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_payment_term as c ON f.fk_cond_reglement = c.rowid';
2144 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_paiement as p ON f.fk_mode_reglement = p.id';
2145 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON f.fk_incoterms = i.rowid';
2148 $sql .=
" WHERE f.rowid = ".((int) $rowid);
2150 $sql .=
' WHERE f.entity IN ('.getEntity(
'invoice').
')';
2152 $sql .=
" AND f.ref = '".$this->db->escape($ref).
"'";
2155 $sql .=
" AND f.ref_ext = '".$this->db->escape($ref_ext).
"'";
2159 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
2160 $resql = $this->db->query($sql);
2162 if ($this->db->num_rows($resql)) {
2163 $obj = $this->db->fetch_object($resql);
2165 $this->
id = $obj->rowid;
2166 $this->entity = $obj->entity;
2168 $this->
ref = $obj->ref;
2169 $this->ref_client = $obj->ref_client;
2170 $this->ref_customer = $obj->ref_client;
2171 $this->ref_ext = $obj->ref_ext;
2172 $this->
type = $obj->type;
2173 $this->subtype = $obj->subtype;
2174 $this->date = $this->db->jdate($obj->df);
2175 $this->date_pointoftax = $this->db->jdate($obj->date_pointoftax);
2176 $this->date_creation = $this->db->jdate($obj->datec);
2177 $this->date_validation = $this->db->jdate($obj->datev);
2178 $this->date_modification = $this->db->jdate($obj->datem);
2179 $this->datem = $this->db->jdate($obj->datem);
2180 $this->total_ht = $obj->total_ht;
2181 $this->total_tva = $obj->total_tva;
2182 $this->total_localtax1 = $obj->localtax1;
2183 $this->total_localtax2 = $obj->localtax2;
2184 $this->total_ttc = $obj->total_ttc;
2185 $this->revenuestamp = $obj->revenuestamp;
2186 $this->paye = $obj->paye;
2187 $this->close_code = $obj->close_code;
2188 $this->close_note = $obj->close_note;
2190 $this->socid = $obj->fk_soc;
2191 $this->thirdparty =
null;
2193 $this->fk_project = $obj->fk_project;
2194 $this->project =
null;
2196 $this->
statut = $obj->status;
2197 $this->
status = $obj->status;
2199 $this->date_lim_reglement = $this->db->jdate($obj->dlr);
2200 $this->mode_reglement_id = $obj->fk_mode_reglement;
2201 $this->mode_reglement_code = $obj->mode_reglement_code;
2202 $this->mode_reglement = $obj->mode_reglement_libelle;
2203 $this->cond_reglement_id = $obj->fk_cond_reglement;
2204 $this->cond_reglement_code = $obj->cond_reglement_code;
2205 $this->cond_reglement = $obj->cond_reglement_libelle;
2206 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
2207 $this->fk_account = ($obj->fk_account > 0) ? $obj->fk_account :
null;
2208 $this->fk_facture_source = $obj->fk_facture_source;
2209 $this->fk_fac_rec_source = $obj->fk_fac_rec_source;
2210 $this->note = $obj->note_private;
2211 $this->note_private = $obj->note_private;
2212 $this->note_public = $obj->note_public;
2213 $this->user_creation_id = $obj->fk_user_author;
2214 $this->user_validation_id = $obj->fk_user_valid;
2215 $this->user_modification_id = $obj->fk_user_modif;
2216 $this->fk_user_author = $obj->fk_user_author;
2217 $this->fk_user_valid = $obj->fk_user_valid;
2218 $this->fk_user_modif = $obj->fk_user_modif;
2219 $this->model_pdf = $obj->model_pdf;
2220 $this->last_main_doc = $obj->last_main_doc;
2221 $this->situation_cycle_ref = $obj->situation_cycle_ref;
2222 $this->situation_counter = $obj->situation_counter;
2223 $this->situation_final = $obj->situation_final;
2224 $this->retained_warranty = $obj->retained_warranty;
2225 $this->retained_warranty_date_limit = $this->db->jdate($obj->retained_warranty_date_limit);
2226 $this->retained_warranty_fk_cond_reglement = $obj->retained_warranty_fk_cond_reglement;
2228 $this->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
2231 $this->fk_incoterms = $obj->fk_incoterms;
2232 $this->location_incoterms = $obj->location_incoterms;
2233 $this->label_incoterms = $obj->label_incoterms;
2235 $this->module_source = $obj->module_source;
2236 $this->pos_source = $obj->pos_source;
2239 $this->fk_multicurrency = $obj->fk_multicurrency;
2240 $this->multicurrency_code = $obj->multicurrency_code;
2241 $this->multicurrency_tx = $obj->multicurrency_tx;
2242 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
2243 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
2244 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
2246 if (($this->
type == self::TYPE_SITUATION || ($this->
type == self::TYPE_CREDIT_NOTE && $this->situation_cycle_ref > 0)) && $fetch_situation) {
2255 $this->lines = array();
2259 $this->error = $this->db->error();
2263 $this->db->free($resql);
2267 $this->error =
'Invoice with id='.$rowid.
' or ref='.$ref.
' or ref_ext='.$ref_ext.
' not found';
2269 dol_syslog(__METHOD__.$this->error, LOG_WARNING);
2273 $this->error = $this->db->lasterror();
2288 public function fetch_lines($only_product = 0, $loadalsotranslation = 0)
2291 $this->lines = array();
2293 $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,';
2294 $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,';
2295 $sql .=
' l.situation_percent, l.fk_prev_id,';
2296 $sql .=
' l.rang, l.special_code, l.batch, l.fk_warehouse,';
2297 $sql .=
' l.date_start as date_start, l.date_end as date_end,';
2298 $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,';
2299 $sql .=
' l.fk_unit,';
2300 $sql .=
' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
2301 $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';
2302 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facturedet as l';
2303 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON l.fk_product = p.rowid';
2304 $sql .=
' WHERE l.fk_facture = '.((int) $this->
id);
2305 $sql .=
' ORDER BY l.rang, l.rowid';
2307 dol_syslog(get_class($this).
'::fetch_lines', LOG_DEBUG);
2308 $result = $this->db->query($sql);
2310 $num = $this->db->num_rows($result);
2313 $objp = $this->db->fetch_object($result);
2316 $line->id = $objp->rowid;
2317 $line->rowid = $objp->rowid;
2318 $line->fk_facture = $objp->fk_facture;
2319 $line->label = $objp->custom_label;
2320 $line->desc = $objp->description;
2321 $line->description = $objp->description;
2322 $line->product_type = $objp->product_type;
2323 $line->ref = $objp->product_ref;
2324 $line->product_ref = $objp->product_ref;
2325 $line->libelle = $objp->product_label;
2326 $line->product_label = $objp->product_label;
2327 $line->product_barcode = $objp->product_barcode;
2328 $line->product_desc = $objp->product_desc;
2329 $line->fk_product_type = $objp->fk_product_type;
2330 $line->qty = $objp->qty;
2331 $line->subprice = $objp->subprice;
2332 $line->ref_ext = $objp->ref_ext;
2334 $line->vat_src_code = $objp->vat_src_code;
2335 $line->tva_tx = $objp->tva_tx;
2336 $line->localtax1_tx = $objp->localtax1_tx;
2337 $line->localtax2_tx = $objp->localtax2_tx;
2338 $line->localtax1_type = $objp->localtax1_type;
2339 $line->localtax2_type = $objp->localtax2_type;
2340 $line->remise_percent = $objp->remise_percent;
2341 $line->fk_remise_except = $objp->fk_remise_except;
2342 $line->fk_product = $objp->fk_product;
2343 $line->date_start = $this->db->jdate($objp->date_start);
2344 $line->date_end = $this->db->jdate($objp->date_end);
2345 $line->info_bits = $objp->info_bits;
2346 $line->total_ht = $objp->total_ht;
2347 $line->total_tva = $objp->total_tva;
2348 $line->total_localtax1 = $objp->total_localtax1;
2349 $line->total_localtax2 = $objp->total_localtax2;
2350 $line->total_ttc = $objp->total_ttc;
2352 $line->code_ventilation = $objp->fk_code_ventilation;
2353 $line->fk_fournprice = $objp->fk_fournprice;
2354 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
2355 $line->pa_ht = $marginInfos[0];
2356 $line->marge_tx = $marginInfos[1];
2357 $line->marque_tx = $marginInfos[2];
2358 $line->rang = $objp->rang;
2359 $line->special_code = $objp->special_code;
2360 $line->fk_parent_line = $objp->fk_parent_line;
2361 $line->situation_percent = $objp->situation_percent;
2362 $line->fk_prev_id = $objp->fk_prev_id;
2363 $line->fk_unit = $objp->fk_unit;
2365 $line->batch = $objp->batch;
2366 $line->fk_warehouse = $objp->fk_warehouse;
2369 $line->fk_accounting_account = $objp->fk_code_ventilation;
2372 $line->fk_multicurrency = $objp->fk_multicurrency;
2373 $line->multicurrency_code = $objp->multicurrency_code;
2374 $line->multicurrency_subprice = $objp->multicurrency_subprice;
2375 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
2376 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
2377 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
2379 $line->fetch_optionals();
2382 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
2383 $tmpproduct =
new Product($this->db);
2384 $tmpproduct->fetch($objp->fk_product);
2385 $tmpproduct->getMultiLangs();
2387 $line->multilangs = $tmpproduct->multilangs;
2390 $this->lines[$i] = $line;
2394 $this->db->free($result);
2397 $this->error = $this->db->error();
2412 $this->tab_previous_situation_invoice = array();
2413 $this->tab_next_situation_invoice = array();
2415 $sql =
'SELECT rowid, type, situation_cycle_ref, situation_counter FROM '.MAIN_DB_PREFIX.
'facture';
2416 $sql .=
" WHERE rowid <> ".((int) $this->
id);
2417 $sql .=
' AND entity = '.((int) $this->entity);
2418 $sql .=
' AND situation_cycle_ref = '.(int) $this->situation_cycle_ref;
2419 $sql .=
' ORDER BY situation_counter ASC';
2421 dol_syslog(get_class($this).
'::fetchPreviousNextSituationInvoice ', LOG_DEBUG);
2422 $result = $this->db->query($sql);
2423 if ($result && $this->db->num_rows($result) > 0) {
2424 while ($objp = $this->db->fetch_object($result)) {
2425 $invoice =
new Facture($this->db);
2426 if ($invoice->fetch($objp->rowid) > 0) {
2427 if ($objp->situation_counter < $this->situation_counter
2428 || ($objp->situation_counter == $this->situation_counter && $objp->rowid < $this->id)
2430 $this->tab_previous_situation_invoice[] = $invoice;
2432 $this->tab_next_situation_invoice[] = $invoice;
2451 if (empty($this->
type)) {
2454 if (isset($this->subtype)) {
2455 $this->subtype = trim($this->subtype);
2457 if (isset($this->
ref)) {
2458 $this->
ref = trim($this->
ref);
2460 if (isset($this->ref_ext)) {
2461 $this->ref_ext = trim($this->ref_ext);
2463 if (isset($this->ref_client)) {
2464 $this->ref_client = trim($this->ref_client);
2466 if (isset($this->increment)) {
2467 $this->increment = trim($this->increment);
2469 if (isset($this->close_code)) {
2470 $this->close_code = trim($this->close_code);
2472 if (isset($this->close_note)) {
2473 $this->close_note = trim($this->close_note);
2475 if (isset($this->note) || isset($this->note_private)) {
2476 $this->note = (isset($this->note) ? trim($this->note) : trim($this->note_private));
2478 if (isset($this->note) || isset($this->note_private)) {
2479 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note));
2481 if (isset($this->note_public)) {
2482 $this->note_public = trim($this->note_public);
2484 if (isset($this->model_pdf)) {
2485 $this->model_pdf = trim($this->model_pdf);
2487 if (isset($this->import_key)) {
2488 $this->import_key = trim($this->import_key);
2490 if (isset($this->retained_warranty)) {
2491 $this->retained_warranty = (float) $this->retained_warranty;
2499 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facture SET";
2500 $sql .=
" ref=".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
2501 $sql .=
" ref_ext=".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
2502 $sql .=
" type=".(isset($this->
type) ? $this->db->escape($this->
type) :
"null").
",";
2503 $sql .=
" subtype=".(isset($this->subtype) ? $this->db->escape($this->subtype) :
"null").
",";
2504 $sql .=
" ref_client=".(isset($this->ref_client) ?
"'".$this->db->escape($this->ref_client).
"'" :
"null").
",";
2505 $sql .=
" increment=".(isset($this->increment) ?
"'".$this->db->escape($this->increment).
"'" :
"null").
",";
2506 $sql .=
" fk_soc=".(isset($this->socid) ? $this->db->escape($this->socid) :
"null").
",";
2507 $sql .=
" datec=".(strval($this->date_creation) !=
'' ?
"'".$this->db->idate($this->date_creation).
"'" :
'null').
",";
2508 $sql .=
" datef=".(strval($this->date) !=
'' ?
"'".$this->db->idate($this->date).
"'" :
'null').
",";
2509 $sql .=
" date_pointoftax=".(strval($this->date_pointoftax) !=
'' ?
"'".$this->db->idate($this->date_pointoftax).
"'" :
'null').
",";
2510 $sql .=
" date_valid=".(strval($this->date_validation) !=
'' ?
"'".$this->db->idate($this->date_validation).
"'" :
'null').
",";
2511 $sql .=
" paye=".(isset($this->paye) ? $this->db->escape($this->paye) : 0).
",";
2512 $sql .=
" close_code=".(isset($this->close_code) ?
"'".$this->db->escape($this->close_code).
"'" :
"null").
",";
2513 $sql .=
" close_note=".(isset($this->close_note) ?
"'".$this->db->escape($this->close_note).
"'" :
"null").
",";
2514 $sql .=
" total_tva=".(isset($this->total_tva) ? $this->total_tva :
"null").
",";
2515 $sql .=
" localtax1=".(isset($this->total_localtax1) ? $this->total_localtax1 :
"null").
",";
2516 $sql .=
" localtax2=".(isset($this->total_localtax2) ? $this->total_localtax2 :
"null").
",";
2517 $sql .=
" total_ht=".(isset($this->total_ht) ? $this->total_ht :
"null").
",";
2518 $sql .=
" total_ttc=".(isset($this->total_ttc) ? $this->total_ttc :
"null").
",";
2519 $sql .=
" revenuestamp=".((isset($this->revenuestamp) && $this->revenuestamp !=
'') ? $this->db->escape($this->revenuestamp) :
"null").
",";
2520 $sql .=
" fk_statut=".(isset($this->
status) ? $this->db->escape($this->
status) :
"null").
",";
2521 $sql .=
" fk_user_author=".(isset($this->user_author) ? $this->db->escape($this->user_author) :
"null").
",";
2522 $sql .=
" fk_user_valid=".(isset($this->fk_user_valid) ? $this->db->escape($this->fk_user_valid) :
"null").
",";
2523 $sql .=
" fk_facture_source=".(isset($this->fk_facture_source) ? $this->db->escape($this->fk_facture_source) :
"null").
",";
2524 $sql .=
" fk_projet=".(isset($this->fk_project) ? $this->db->escape($this->fk_project) :
"null").
",";
2525 $sql .=
" fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->db->escape($this->cond_reglement_id) :
"null").
",";
2526 $sql .=
" fk_mode_reglement=".(isset($this->mode_reglement_id) ? $this->db->escape($this->mode_reglement_id) :
"null").
",";
2527 $sql .=
" date_lim_reglement=".(strval($this->date_lim_reglement) !=
'' ?
"'".$this->db->idate($this->date_lim_reglement).
"'" :
'null').
",";
2528 $sql .=
" note_private=".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
2529 $sql .=
" note_public=".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
2530 $sql .=
" model_pdf=".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
2531 $sql .=
" import_key=".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null").
",";
2532 $sql .=
" situation_cycle_ref=".(empty($this->situation_cycle_ref) ?
"null" : $this->db->escape($this->situation_cycle_ref)).
",";
2533 $sql .=
" situation_counter=".(empty($this->situation_counter) ?
"null" : $this->db->escape($this->situation_counter)).
",";
2534 $sql .=
" situation_final=".(empty($this->situation_final) ?
"0" : $this->db->escape($this->situation_final)).
",";
2535 $sql .=
" retained_warranty=".(empty($this->retained_warranty) ?
"0" : $this->db->escape($this->retained_warranty)).
",";
2536 $sql .=
" retained_warranty_date_limit=".(strval($this->retained_warranty_date_limit) !=
'' ?
"'".$this->db->idate($this->retained_warranty_date_limit).
"'" :
'null').
",";
2537 $sql .=
" retained_warranty_fk_cond_reglement=".(isset($this->retained_warranty_fk_cond_reglement) ? intval($this->retained_warranty_fk_cond_reglement) :
"null");
2538 $sql .=
" WHERE rowid=".((int) $this->
id);
2542 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
2543 $resql = $this->db->query($sql);
2546 $this->errors[] =
"Error ".$this->db->lasterror();
2556 if (!$error && !$notrigger) {
2567 foreach ($this->errors as $errmsg) {
2568 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
2569 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2571 $this->db->rollback();
2574 $this->db->commit();
2590 global $conf, $langs;
2592 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
2593 include_once DOL_DOCUMENT_ROOT.
'/core/class/discount.class.php';
2598 $result = $remise->fetch($idremise);
2601 if ($remise->fk_facture) {
2602 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed");
2603 $this->db->rollback();
2608 $facligne->fk_facture = $this->id;
2609 $facligne->fk_remise_except = $remise->id;
2610 $facligne->desc = $remise->description;
2611 $facligne->vat_src_code = $remise->vat_src_code;
2612 $facligne->tva_tx = $remise->tva_tx;
2613 $facligne->subprice = -$remise->amount_ht;
2614 $facligne->fk_product = 0;
2616 $facligne->remise_percent = 0;
2617 $facligne->rang = -1;
2618 $facligne->info_bits = 2;
2621 $facligne->rang = 1;
2622 $linecount = count($this->lines);
2623 for ($ii = 1; $ii <= $linecount; $ii++) {
2629 if ($remise->fk_facture_source > 0) {
2630 $srcinvoice =
new Facture($this->db);
2631 $srcinvoice->fetch($remise->fk_facture_source);
2632 include_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmargin.class.php';
2634 $arraytmp = $formmargin->getMarginInfosArray($srcinvoice,
false);
2635 $facligne->pa_ht = $arraytmp[
'pa_total'];
2638 $facligne->total_ht = -$remise->amount_ht;
2639 $facligne->total_tva = -$remise->amount_tva;
2640 $facligne->total_ttc = -$remise->amount_ttc;
2642 $facligne->multicurrency_subprice = -$remise->multicurrency_subprice;
2643 $facligne->multicurrency_total_ht = -$remise->multicurrency_amount_ht;
2644 $facligne->multicurrency_total_tva = -$remise->multicurrency_amount_tva;
2645 $facligne->multicurrency_total_ttc = -$remise->multicurrency_amount_ttc;
2647 $lineid = $facligne->insert();
2652 $result = $remise->link_to_invoice($lineid, 0);
2654 $this->error = $remise->error;
2655 $this->db->rollback();
2659 $this->db->commit();
2662 $this->error = $facligne->error;
2663 $this->db->rollback();
2667 $this->error = $facligne->error;
2668 $this->db->rollback();
2672 $this->db->rollback();
2694 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
2695 if (empty($ref_client)) {
2696 $sql .=
' SET ref_client = NULL';
2698 $sql .=
' SET ref_client = \''.$this->db->escape($ref_client).
'\'';
2700 $sql .=
" WHERE rowid = ".((int) $this->
id);
2702 dol_syslog(__METHOD__.
' this->id='.$this->id.
', ref_client='.$ref_client, LOG_DEBUG);
2703 $resql = $this->db->query($sql);
2705 $this->errors[] = $this->db->error();
2710 $this->ref_client = $ref_client;
2713 if (!$notrigger && empty($error)) {
2723 $this->ref_client = $ref_client;
2725 $this->db->commit();
2728 foreach ($this->errors as $errmsg) {
2729 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2730 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2732 $this->db->rollback();
2745 public function delete($user, $notrigger = 0, $idwarehouse = -1)
2747 global $langs, $conf;
2748 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
2752 dol_syslog(get_class($this).
"::delete rowid=".$rowid.
", ref=".$this->ref.
", thirdparty=".(empty($this->thirdparty) ?
'' : $this->thirdparty->name), LOG_DEBUG);
2765 if (!$error && !$notrigger) {
2779 dol_syslog(get_class($this).
"::delete error deleteExtraFields ".$this->error, LOG_ERR);
2793 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'societe_remise_except';
2794 $sql .=
' WHERE fk_facture_source = '.((int) $rowid);
2795 $sql .=
' AND fk_facture_line IS NULL';
2796 $resql = $this->db->query($sql);
2800 $list_rowid_det = array();
2801 foreach ($this->lines as $key => $invoiceline) {
2802 $list_rowid_det[] = $invoiceline->id;
2806 if (count($list_rowid_det)) {
2807 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
2808 $sql .=
' SET fk_facture = NULL, fk_facture_line = NULL';
2809 $sql .=
' WHERE fk_facture_line IN ('.$this->db->sanitize(join(
',', $list_rowid_det)).
')';
2811 if (!$this->db->query($sql)) {
2812 $this->error = $this->db->error().
" sql=".$sql;
2813 $this->errors[] = $this->error;
2814 $this->db->rollback();
2821 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'eventorganization_conferenceorboothattendee';
2822 $sql .=
' SET fk_invoice = NULL';
2823 $sql .=
' WHERE fk_invoice = '.((int) $rowid);
2825 if (!$this->db->query($sql)) {
2826 $this->error = $this->db->error().
" sql=".$sql;
2827 $this->errors[] = $this->error;
2828 $this->db->rollback();
2832 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'element_time';
2833 $sql .=
' SET invoice_id = NULL, invoice_line_id = NULL';
2834 $sql .=
' WHERE invoice_id = '.((int) $rowid);
2836 if (!$this->db->query($sql)) {
2837 $this->error = $this->db->error().
" sql=".$sql;
2838 $this->errors[] = $this->error;
2839 $this->db->rollback();
2844 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL') && $idwarehouse != -1) {
2845 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
2846 $langs->load(
"agenda");
2848 $num = count($this->lines);
2849 for ($i = 0; $i < $num; $i++) {
2850 if ($this->lines[$i]->fk_product > 0) {
2852 $mouvP->origin = &$this;
2853 $mouvP->setOrigin($this->element, $this->
id);
2855 if ($this->
type == self::TYPE_CREDIT_NOTE) {
2856 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceDeleteDolibarr", $this->ref));
2858 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceDeleteDolibarr", $this->ref));
2865 $main = MAIN_DB_PREFIX.
'facturedet';
2866 $ef = $main.
"_extrafields";
2867 $sqlef =
"DELETE FROM ".$ef.
" WHERE fk_object IN (SELECT rowid FROM ".$main.
" WHERE fk_facture = ".((int) $rowid).
")";
2869 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'facturedet WHERE fk_facture = '.((int) $rowid);
2872 $sql =
'DELETE FROM '.MAIN_DB_PREFIX.
'facture WHERE rowid = '.((int) $rowid);
2874 $resql = $this->db->query($sql);
2882 if ($conf->facture->dir_output && !empty($this->
ref)) {
2883 $dir = $conf->facture->dir_output.
"/".$ref;
2884 $file = $conf->facture->dir_output.
"/".$ref.
"/".$ref.
".pdf";
2885 if (file_exists($file)) {
2889 $langs->load(
"errors");
2890 $this->error = $langs->trans(
"ErrorFailToDeleteFile", $file);
2891 $this->errors[] = $this->error;
2892 $this->db->rollback();
2896 if (file_exists($dir)) {
2898 $langs->load(
"errors");
2899 $this->error = $langs->trans(
"ErrorFailToDeleteDir", $dir);
2900 $this->errors[] = $this->error;
2901 $this->db->rollback();
2907 $this->db->commit();
2910 $this->error = $this->db->lasterror().
" sql=".$sql;
2911 $this->errors[] = $this->error;
2912 $this->db->rollback();
2916 $this->error = $this->db->lasterror().
" sql=".$sql;
2917 $this->errors[] = $this->error;
2918 $this->db->rollback();
2922 $this->db->rollback();
2939 public function set_paid($user, $close_code =
'', $close_note =
'')
2942 dol_syslog(get_class($this).
"::set_paid is deprecated, use setPaid instead", LOG_NOTICE);
2943 return $this->
setPaid($user, $close_code, $close_note);
2956 public function setPaid($user, $close_code =
'', $close_note =
'')
2960 if ($this->paye != 1) {
2965 dol_syslog(get_class($this).
"::setPaid rowid=".((
int) $this->
id), LOG_DEBUG);
2967 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET';
2968 $sql .=
' fk_statut='.self::STATUS_CLOSED;
2973 $sql .=
", close_code='".$this->db->escape($close_code).
"'";
2976 $sql .=
", close_note='".$this->db->escape($close_note).
"'";
2978 $sql .=
', fk_user_closing = '.((int) $user->id);
2979 $sql .=
", date_closing = '".$this->db->idate($now).
"'";
2980 $sql .=
" WHERE rowid = ".((int) $this->
id);
2982 $resql = $this->db->query($sql);
2992 $this->error = $this->db->lasterror();
2996 $this->db->commit();
2999 $this->db->rollback();
3022 dol_syslog(get_class($this).
"::set_unpaid is deprecated, use setUnpaid instead", LOG_NOTICE);
3040 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
3041 $sql .=
' SET paye=0, fk_statut='.self::STATUS_VALIDATED.
', close_code=null, close_note=null,';
3042 $sql .=
' date_closing=null,';
3043 $sql .=
' fk_user_closing=null';
3044 $sql .=
" WHERE rowid = ".((int) $this->
id);
3046 dol_syslog(get_class($this).
"::setUnpaid", LOG_DEBUG);
3047 $resql = $this->db->query($sql);
3057 $this->error = $this->db->error();
3062 $this->db->commit();
3065 $this->db->rollback();
3087 dol_syslog(get_class($this).
"::set_canceled is deprecated, use setCanceled instead", LOG_NOTICE);
3088 return $this->
setCanceled($user, $close_code, $close_note);
3101 public function setCanceled($user, $close_code =
'', $close_note =
'')
3103 dol_syslog(get_class($this).
"::setCanceled rowid=".((
int) $this->
id), LOG_DEBUG);
3108 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET';
3109 $sql .=
' fk_statut='.self::STATUS_ABANDONED;
3111 $sql .=
", close_code='".$this->db->escape($close_code).
"'";
3114 $sql .=
", close_note='".$this->db->escape($close_note).
"'";
3116 $sql .=
', fk_user_closing = '.((int) $user->id);
3117 $sql .=
", date_closing = '".$this->db->idate($now).
"'";
3118 $sql .=
" WHERE rowid = ".((int) $this->
id);
3120 $resql = $this->db->query($sql);
3124 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
3125 $sql .=
' SET fk_facture = NULL';
3126 $sql .=
' WHERE fk_facture = '.((int) $this->
id);
3128 $resql = $this->db->query($sql);
3133 $this->db->rollback();
3138 $this->db->commit();
3141 $this->error = $this->db->error().
" sql=".$sql;
3142 $this->db->rollback();
3146 $this->error = $this->db->error().
" sql=".$sql;
3147 $this->db->rollback();
3163 public function validate($user, $force_number =
'', $idwarehouse = 0, $notrigger = 0, $batch_rule = 0)
3165 global $conf, $langs, $mysoc;
3166 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
3168 $productStatic =
null;
3169 $warehouseStatic =
null;
3170 if ($batch_rule > 0) {
3171 require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
3172 require_once DOL_DOCUMENT_ROOT.
'/product/class/productbatch.class.php';
3173 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
3174 $productStatic =
new Product($this->db);
3175 $warehouseStatic =
new Entrepot($this->db);
3182 dol_syslog(get_class($this).
'::validate user='.$user->id.
', force_number='.$force_number.
', idwarehouse='.$idwarehouse);
3189 if ($this->
status != self::STATUS_DRAFT) {
3190 dol_syslog(get_class($this).
"::validate Current status is not draft. operation canceled.", LOG_WARNING);
3193 if (count($this->lines) <= 0) {
3194 $langs->load(
"errors");
3195 $this->error = $langs->trans(
"ErrorObjectMustHaveLinesToBeValidated", $this->
ref);
3199 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && !$user->hasRight(
'facture',
'invoice_advance',
'validate'))) {
3200 $this->error =
'Permission denied';
3201 dol_syslog(get_class($this).
"::validate ".$this->error.
' MAIN_USE_ADVANCED_PERMS=' .
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS'), LOG_ERR);
3204 if ((preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) &&
3212 if (!$last_of_type[0]) {
3213 $this->error = $langs->transnoentities(
"ErrorInvoiceIsNotLastOfSameType", $this->
ref,
dol_print_date($this->date,
'day'),
dol_print_date($last_of_type[1],
'day'));
3219 if (!empty($this->thirdparty) && is_object($this->thirdparty)) {
3220 $array_to_check = array(
'IDPROF1',
'IDPROF2',
'IDPROF3',
'IDPROF4',
'IDPROF5',
'IDPROF6',
'EMAIL',
'ACCOUNTANCY_CODE_CUSTOMER');
3221 foreach ($array_to_check as $key) {
3222 $keymin = strtolower($key);
3223 if (!property_exists($this->thirdparty, $keymin)) {
3226 $vallabel = $this->thirdparty->$keymin;
3228 $i = (int) preg_replace(
'/[^0-9]/',
'', $key);
3230 if ($this->thirdparty->isACompany()) {
3232 if ($mysoc->country_id > 0 && $this->thirdparty->country_id == $mysoc->country_id) {
3233 $idprof_mandatory =
'SOCIETE_'.$key.
'_INVOICE_MANDATORY';
3234 if (!$vallabel && !empty($conf->global->$idprof_mandatory)) {
3235 $langs->load(
"errors");
3236 $this->error = $langs->trans(
'ErrorProdIdIsMandatory', $langs->transcountry(
'ProfId'.$i, $this->thirdparty->country_code)).
' ('.$langs->trans(
"ForbiddenBySetupRules").
') ['.$langs->trans(
'Company').
' : '.$this->thirdparty->name.
']';
3237 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3243 if ($key ==
'EMAIL') {
3245 if (
getDolGlobalString(
'SOCIETE_EMAIL_INVOICE_MANDATORY') && !isValidEMail($this->thirdparty->email)) {
3246 $langs->load(
"errors");
3247 $this->error = $langs->trans(
"ErrorBadEMail", $this->thirdparty->email).
' ('.$langs->trans(
"ForbiddenBySetupRules").
') ['.$langs->trans(
'Company').
' : '.$this->thirdparty->name.
']';
3248 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3252 if ($key ==
'ACCOUNTANCY_CODE_CUSTOMER') {
3254 if (
getDolGlobalString(
'SOCIETE_ACCOUNTANCY_CODE_CUSTOMER_INVOICE_MANDATORY') && empty($this->thirdparty->code_compta)) {
3255 $langs->load(
"errors");
3256 $this->error = $langs->trans(
"ErrorAccountancyCodeCustomerIsMandatory", $this->thirdparty->name).
' ('.$langs->trans(
"ForbiddenBySetupRules").
')';
3257 dol_syslog(__METHOD__.
' '.$this->error, LOG_ERR);
3266 $array_to_check = array(
'REF_CLIENT'=>
'RefCustomer');
3267 foreach ($array_to_check as $key => $val) {
3268 $keymin = strtolower($key);
3269 $vallabel = $this->$keymin;
3272 $keymandatory =
'INVOICE_'.$key.
'_MANDATORY_FOR_VALIDATION';
3274 $langs->load(
"errors");
3276 setEventMessages($langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv($val)),
null,
'errors');
3283 if ($this->
type == self::TYPE_REPLACEMENT) {
3285 if ($this->fk_facture_source <= 0) {
3286 $this->error = $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"InvoiceReplacement"));
3287 $this->db->rollback();
3292 $facreplaced =
new Facture($this->db);
3293 $result = $facreplaced->fetch($this->fk_facture_source);
3295 $this->error = $langs->trans(
"ErrorBadInvoice");
3296 $this->db->rollback();
3301 $idreplacement = $facreplaced->getIdReplacingInvoice(
'validated');
3302 if ($idreplacement && $idreplacement != $this->
id) {
3303 $facreplacement =
new Facture($this->db);
3304 $facreplacement->fetch($idreplacement);
3305 $this->error = $langs->trans(
"ErrorInvoiceAlreadyReplaced", $facreplaced->ref, $facreplacement->ref);
3306 $this->db->rollback();
3310 $result = $facreplaced->setCanceled($user, self::CLOSECODE_REPLACED,
'');
3312 $this->error = $facreplaced->error;
3313 $this->db->rollback();
3319 if ($force_number) {
3320 $num = $force_number;
3321 } elseif (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
3337 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
3338 $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).
"'";
3340 $sql .=
", datef='".$this->db->idate($this->date).
"'";
3341 $sql .=
", date_lim_reglement='".$this->db->idate($this->date_lim_reglement).
"'";
3343 $sql .=
" WHERE rowid = ".((int) $this->
id);
3345 dol_syslog(get_class($this).
"::validate", LOG_DEBUG);
3346 $resql = $this->db->query($sql);
3353 if (!$error && (preg_match(
'/^[\(]?PROV/i', $this->
ref))) {
3359 $result = $this->thirdparty->setAsCustomer();
3362 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL') && $idwarehouse > 0) {
3363 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3364 $langs->load(
"agenda");
3367 $cpt = count($this->lines);
3368 for ($i = 0; $i < $cpt; $i++) {
3369 if ($this->lines[$i]->fk_product > 0) {
3371 $mouvP->origin = &$this;
3372 $mouvP->setOrigin($this->element, $this->
id);
3378 if ($this->
type == self::TYPE_CREDIT_NOTE) {
3379 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceValidatedInDolibarr", $num));
3382 $this->error = $mouvP->error;
3385 $is_batch_line =
false;
3386 if ($batch_rule > 0) {
3387 $productStatic->fetch($this->lines[$i]->fk_product);
3388 if ($productStatic->hasbatch()) {
3389 $is_batch_line =
true;
3390 $product_qty_remain = $this->lines[$i]->qty;
3396 $sortfield =
'pl.sellby,pl.eatby,pb.qty,pl.rowid';
3397 $sortorder =
'ASC,ASC,ASC,ASC';
3400 $resBatchList = $productbatch->findAllForProduct($productStatic->id, $idwarehouse, (
getDolGlobalInt(
'STOCK_ALLOW_NEGATIVE_TRANSFER') ?
null : 0), $sortfield, $sortorder);
3401 if (!is_array($resBatchList)) {
3403 $this->error = $this->db->lasterror();
3407 $batchList = $resBatchList;
3408 if (empty($batchList)) {
3410 $langs->load(
'errors');
3411 $warehouseStatic->fetch($idwarehouse);
3412 $this->error = $langs->trans(
'ErrorBatchNoFoundForProductInWarehouse', $productStatic->label, $warehouseStatic->ref);
3413 dol_syslog(__METHOD__.
' Error: '.$langs->transnoentitiesnoconv(
'ErrorBatchNoFoundForProductInWarehouse', $productStatic->label, $warehouseStatic->ref), LOG_ERR);
3416 foreach ($batchList as $batch) {
3417 if ($batch->qty <= 0) {
3422 if ($batch->qty >= $product_qty_remain) {
3423 $product_batch_qty = $product_qty_remain;
3426 $product_batch_qty = $batch->qty;
3428 $result = $mouvP->livraison($user, $productStatic->id, $idwarehouse, $product_batch_qty, $this->lines[$i]->subprice, $langs->trans(
'InvoiceValidatedInDolibarr', $num),
'',
'',
'', $batch->batch);
3431 $this->error = $mouvP->error;
3432 $this->errors = $mouvP->errors;
3436 $product_qty_remain -= $product_batch_qty;
3438 if ($product_qty_remain <= 0) {
3443 if (!$error && $product_qty_remain > 0) {
3446 $batch = $batchList[0];
3447 $result = $mouvP->livraison($user, $productStatic->id, $idwarehouse, $product_qty_remain, $this->lines[$i]->subprice, $langs->trans(
'InvoiceValidatedInDolibarr', $num),
'',
'',
'', $batch->batch);
3450 $this->error = $mouvP->error;
3451 $this->errors = $mouvP->errors;
3455 $langs->load(
'errors');
3456 $warehouseStatic->fetch($idwarehouse);
3457 $this->error = $langs->trans(
'ErrorBatchNoFoundEnoughQuantityForProductInWarehouse', $productStatic->label, $warehouseStatic->ref);
3458 dol_syslog(__METHOD__.
' Error: '.$langs->transnoentitiesnoconv(
'ErrorBatchNoFoundEnoughQuantityForProductInWarehouse', $productStatic->label, $warehouseStatic->ref), LOG_ERR);
3465 if (!$is_batch_line) {
3466 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceValidatedInDolibarr", $num));
3469 $this->error = $mouvP->error;
3470 $this->errors = $mouvP->errors;
3483 if (!$error && $this->
type == self::TYPE_CREDIT_NOTE && $this->fk_facture_source > 0) {
3484 $invoice_situation =
new Facture($this->db);
3485 $result = $invoice_situation->fetch($this->fk_facture_source);
3486 if ($result > 0 && $invoice_situation->type == self::TYPE_SITUATION && $invoice_situation->situation_final == 1) {
3487 $invoice_situation->situation_final = 0;
3489 $result = $invoice_situation->setFinal($user, 1);
3492 $this->error = $invoice_situation->error;
3493 $this->errors = $invoice_situation->errors;
3499 if (!$error && !$notrigger) {
3509 $this->oldref = $this->ref;
3512 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
3514 $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).
"'";
3515 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'facture/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
3516 $resql = $this->db->query($sql);
3519 $this->error = $this->db->lasterror();
3521 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'facture/".$this->db->escape($this->newref).
"'";
3522 $sql .=
" WHERE filepath = 'facture/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
3523 $resql = $this->db->query($sql);
3526 $this->error = $this->db->lasterror();
3532 $dirsource = $conf->facture->dir_output.
'/'.$oldref;
3533 $dirdest = $conf->facture->dir_output.
'/'.$newref;
3534 if (!$error && file_exists($dirsource)) {
3535 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
3537 if (@rename($dirsource, $dirdest)) {
3540 $listoffiles =
dol_dir_list($conf->facture->dir_output.
'/'.$newref,
'files', 1,
'^'.preg_quote($oldref,
'/'));
3541 foreach ($listoffiles as $fileentry) {
3542 $dirsource = $fileentry[
'name'];
3543 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
3544 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
3545 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
3546 @rename($dirsource, $dirdest);
3564 $this->date_validation = $now;
3569 $nboflines = count($this->lines);
3570 while (($i < $nboflines) && $final) {
3571 $final = ($this->lines[$i]->situation_percent == 100);
3575 if (empty($final)) {
3576 $this->situation_final = 0;
3578 $this->situation_final = 1;
3589 $this->db->commit();
3592 $this->db->rollback();
3605 foreach ($this->tab_next_situation_invoice as $next_invoice) {
3606 $is_last = $next_invoice->is_last_in_cycle();
3608 if ($next_invoice->status == self::STATUS_DRAFT && $is_last != 1) {
3609 $this->error = $langs->trans(
'updatePriceNextInvoiceErrorUpdateline', $next_invoice->ref);
3613 foreach ($next_invoice->lines as $line) {
3614 $result = $next_invoice->updateline(
3619 $line->remise_percent,
3623 $line->localtax1_tx,
3624 $line->localtax2_tx,
3627 $line->product_type,
3628 $line->fk_parent_line,
3630 $line->fk_fournprice,
3633 $line->special_code,
3634 $line->array_options,
3635 $line->situation_percent,
3640 $this->error = $langs->trans(
'updatePriceNextInvoiceErrorUpdateline', $next_invoice->ref);
3661 global $conf, $langs;
3665 if ($this->
status == self::STATUS_DRAFT) {
3666 dol_syslog(__METHOD__.
" already draft status", LOG_WARNING);
3674 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facture";
3675 $sql .=
" SET fk_statut = ".self::STATUS_DRAFT;
3676 $sql .=
" WHERE rowid = ".((int) $this->
id);
3678 $result = $this->db->query($sql);
3681 $this->oldcopy = clone $this;
3685 if ($this->
type != self::TYPE_DEPOSIT && $result >= 0 && isModEnabled(
'stock') &&
getDolGlobalString(
'STOCK_CALCULATE_ON_BILL')) {
3686 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
3687 $langs->load(
"agenda");
3689 $num = count($this->lines);
3690 for ($i = 0; $i < $num; $i++) {
3691 if ($this->lines[$i]->fk_product > 0) {
3693 $mouvP->origin = &$this;
3694 $mouvP->setOrigin($this->element, $this->
id);
3696 if ($this->
type == self::TYPE_CREDIT_NOTE) {
3697 $result = $mouvP->livraison($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, $this->lines[$i]->subprice, $langs->trans(
"InvoiceBackToDraftInDolibarr", $this->ref));
3699 $result = $mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans(
"InvoiceBackToDraftInDolibarr", $this->ref));
3706 $old_statut = $this->status;
3711 $result = $this->
call_trigger(
'BILL_UNVALIDATE', $user);
3714 $this->
statut = $old_statut;
3715 $this->
status = $old_statut;
3719 $this->db->rollback();
3724 $this->db->commit();
3727 $this->db->rollback();
3731 $this->error = $this->db->error();
3732 $this->db->rollback();
3787 $remise_percent = 0,
3792 $fk_remise_except = 0,
3793 $price_base_type =
'HT',
3800 $fk_parent_line = 0,
3801 $fk_fournprice =
null,
3804 $array_options = array(),
3805 $situation_percent = 100,
3810 $noupdateafterinsertline = 0
3814 dol_syslog(__METHOD__.
": using line label is deprecated", LOG_WARNING);
3818 global $mysoc, $conf, $langs;
3820 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);
3822 if ($this->
status == self::STATUS_DRAFT) {
3823 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
3826 if (empty($remise_percent)) {
3827 $remise_percent = 0;
3832 if (empty($info_bits)) {
3838 if (empty($ventil)) {
3841 if (empty($txtva)) {
3844 if (empty($txlocaltax1)) {
3847 if (empty($txlocaltax2)) {
3850 if (empty($fk_parent_line) || $fk_parent_line < 0) {
3851 $fk_parent_line = 0;
3853 if (empty($fk_prev_id)) {
3854 $fk_prev_id =
'null';
3856 if (!isset($situation_percent) || $situation_percent > 100 || (
string) $situation_percent ==
'') {
3857 $situation_percent = 100;
3859 if (empty($ref_ext)) {
3863 $remise_percent =
price2num($remise_percent);
3866 $pu_ht_devise =
price2num($pu_ht_devise);
3869 if (!preg_match(
'/\((.*)\)/', $txtva)) {
3875 if ($price_base_type ==
'HT') {
3886 if ($date_start && $date_end && $date_start > $date_end) {
3887 $langs->load(
"errors");
3888 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
3894 $product_type = $type;
3895 if (!empty($fk_product) && $fk_product > 0) {
3896 $product =
new Product($this->db);
3897 $result = $product->fetch($fk_product);
3898 $product_type = $product->type;
3900 if (
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_INVOICE') && $product_type == 0 && $product->stock_reel < $qty) {
3901 $langs->load(
"errors");
3902 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnInvoice', $product->ref);
3903 $this->db->rollback();
3913 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
3914 $vat_src_code = $reg[1];
3915 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
3923 $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);
3925 $total_ht = $tabprice[0];
3926 $total_tva = $tabprice[1];
3927 $total_ttc = $tabprice[2];
3928 $total_localtax1 = $tabprice[9];
3929 $total_localtax2 = $tabprice[10];
3930 $pu_ht = $tabprice[3];
3933 $multicurrency_total_ht = $tabprice[16];
3934 $multicurrency_total_tva = $tabprice[17];
3935 $multicurrency_total_ttc = $tabprice[18];
3936 $pu_ht_devise = $tabprice[19];
3940 if ($ranktouse == -1) {
3941 $rangmax = $this->
line_max($fk_parent_line);
3942 $ranktouse = $rangmax + 1;
3948 $this->line->context = $this->context;
3950 $this->line->fk_facture = $this->id;
3951 $this->line->label = $label;
3952 $this->line->desc = $desc;
3953 $this->line->ref_ext = $ref_ext;
3955 $this->line->qty = ($this->
type == self::TYPE_CREDIT_NOTE ? abs($qty) : $qty);
3956 $this->line->subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht) : $pu_ht);
3958 $this->line->vat_src_code = $vat_src_code;
3959 $this->line->tva_tx = $txtva;
3960 $this->line->localtax1_tx = ($total_localtax1 ? $localtaxes_type[1] : 0);
3961 $this->line->localtax2_tx = ($total_localtax2 ? $localtaxes_type[3] : 0);
3962 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
3963 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
3965 $this->line->total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ht) : $total_ht);
3966 $this->line->total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ttc) : $total_ttc);
3967 $this->line->total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_tva) : $total_tva);
3968 $this->line->total_localtax1 = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_localtax1) : $total_localtax1);
3969 $this->line->total_localtax2 = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_localtax2) : $total_localtax2);
3971 $this->line->fk_product = $fk_product;
3972 $this->line->product_type = $product_type;
3973 $this->line->remise_percent = $remise_percent;
3974 $this->line->date_start = $date_start;
3975 $this->line->date_end = $date_end;
3976 $this->line->ventil = $ventil;
3977 $this->line->rang = $ranktouse;
3978 $this->line->info_bits = $info_bits;
3979 $this->line->fk_remise_except = $fk_remise_except;
3981 $this->line->special_code = $special_code;
3982 $this->line->fk_parent_line = $fk_parent_line;
3983 $this->line->origin = $origin;
3984 $this->line->origin_id = $origin_id;
3985 $this->line->situation_percent = $situation_percent;
3986 $this->line->fk_prev_id = $fk_prev_id;
3987 $this->line->fk_unit = $fk_unit;
3990 $this->line->fk_fournprice = $fk_fournprice;
3991 $this->line->pa_ht = $pa_ht;
3994 $this->line->fk_multicurrency = $this->fk_multicurrency;
3995 $this->line->multicurrency_code = $this->multicurrency_code;
3996 $this->line->multicurrency_subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht_devise) : $pu_ht_devise);
3998 $this->line->multicurrency_total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ht) : $multicurrency_total_ht);
3999 $this->line->multicurrency_total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_tva) : $multicurrency_total_tva);
4000 $this->line->multicurrency_total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ttc) : $multicurrency_total_ttc);
4002 if (is_array($array_options) && count($array_options) > 0) {
4003 $this->line->array_options = $array_options;
4006 $result = $this->line->insert();
4009 if (!empty($fk_parent_line)) {
4011 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
4012 $linecount = count($this->lines);
4013 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
4019 if (empty($noupdateafterinsertline)) {
4024 $this->db->commit();
4025 return $this->line->id;
4027 $this->error = $this->db->lasterror();
4028 $this->db->rollback();
4032 $this->error = $this->line->error;
4033 $this->errors = $this->line->errors;
4034 $this->db->rollback();
4038 $this->errors[] =
'status of invoice must be Draft to allow use of ->addline()';
4039 dol_syslog(get_class($this).
"::addline status of invoice must be Draft to allow use of ->addline()", LOG_ERR);
4075 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)
4077 global $conf, $user;
4080 dol_syslog(__METHOD__.
": using line label is deprecated", LOG_WARNING);
4083 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
4085 global $mysoc, $langs;
4087 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);
4089 if ($this->
status == self::STATUS_DRAFT) {
4092 if (!$this->error) {
4093 $this->error = $langs->trans(
'invoiceLineProgressError');
4099 if ($date_start && $date_end && $date_start > $date_end) {
4100 $langs->load(
"errors");
4101 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
4111 if (empty($fk_parent_line) || $fk_parent_line < 0) {
4112 $fk_parent_line = 0;
4114 if (empty($special_code) || $special_code == 3) {
4117 if (!isset($situation_percent) || $situation_percent > 100 || (
string) $situation_percent ==
'') {
4118 $situation_percent = 100;
4120 if (empty($ref_ext)) {
4124 $remise_percent =
price2num($remise_percent);
4127 $pu_ht_devise =
price2num($pu_ht_devise);
4129 if (!preg_match(
'/\((.*)\)/', $txtva)) {
4149 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
4150 $vat_src_code = $reg[1];
4151 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
4154 $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);
4156 $total_ht = $tabprice[0];
4157 $total_tva = $tabprice[1];
4158 $total_ttc = $tabprice[2];
4159 $total_localtax1 = $tabprice[9];
4160 $total_localtax2 = $tabprice[10];
4161 $pu_ht = $tabprice[3];
4162 $pu_tva = $tabprice[4];
4163 $pu_ttc = $tabprice[5];
4166 $multicurrency_total_ht = $tabprice[16];
4167 $multicurrency_total_tva = $tabprice[17];
4168 $multicurrency_total_ttc = $tabprice[18];
4169 $pu_ht_devise = $tabprice[19];
4174 if ($remise_percent > 0) {
4175 $remise = round(((
float) $pu * (
float) $remise_percent / 100), 2);
4176 $price = ((float) $pu - $remise);
4182 $line->fetch($rowid);
4183 $line->fetch_optionals();
4185 if (!empty($line->fk_product)) {
4186 $product =
new Product($this->db);
4187 $result = $product->fetch($line->fk_product);
4188 $product_type = $product->type;
4190 if (
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_INVOICE') && $product_type == 0 && $product->stock_reel < $qty) {
4191 $langs->load(
"errors");
4192 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnInvoice', $product->ref);
4193 $this->db->rollback();
4198 $staticline = clone $line;
4200 $line->oldline = $staticline;
4201 $this->line = $line;
4202 $this->line->context = $this->context;
4203 $this->line->rang = $rang;
4206 if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
4207 $rangmax = $this->
line_max($fk_parent_line);
4208 $this->line->rang = $rangmax + 1;
4211 $this->line->id = $rowid;
4212 $this->line->rowid = $rowid;
4213 $this->line->label = $label;
4214 $this->line->desc = $desc;
4215 $this->line->ref_ext = $ref_ext;
4216 $this->line->qty = ($this->
type == self::TYPE_CREDIT_NOTE ? abs($qty) : $qty);
4218 $this->line->vat_src_code = $vat_src_code;
4219 $this->line->tva_tx = $txtva;
4220 $this->line->localtax1_tx = $txlocaltax1;
4221 $this->line->localtax2_tx = $txlocaltax2;
4222 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
4223 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
4225 $this->line->remise_percent = $remise_percent;
4226 $this->line->subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht) : $pu_ht);
4227 $this->line->date_start = $date_start;
4228 $this->line->date_end = $date_end;
4229 $this->line->total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ht) : $total_ht);
4230 $this->line->total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_tva) : $total_tva);
4231 $this->line->total_localtax1 = $total_localtax1;
4232 $this->line->total_localtax2 = $total_localtax2;
4233 $this->line->total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($total_ttc) : $total_ttc);
4234 $this->line->info_bits = $info_bits;
4235 $this->line->special_code = $special_code;
4236 $this->line->product_type = $type;
4237 $this->line->fk_parent_line = $fk_parent_line;
4238 $this->line->skip_update_total = $skip_update_total;
4239 $this->line->situation_percent = $situation_percent;
4240 $this->line->fk_unit = $fk_unit;
4242 $this->line->fk_fournprice = $fk_fournprice;
4243 $this->line->pa_ht = $pa_ht;
4246 $this->line->multicurrency_subprice = ($this->
type == self::TYPE_CREDIT_NOTE ? -abs($pu_ht_devise) : $pu_ht_devise);
4247 $this->line->multicurrency_total_ht = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ht) : $multicurrency_total_ht);
4248 $this->line->multicurrency_total_tva = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_tva) : $multicurrency_total_tva);
4249 $this->line->multicurrency_total_ttc = (($this->
type == self::TYPE_CREDIT_NOTE || $qty < 0) ? -abs($multicurrency_total_ttc) : $multicurrency_total_ttc);
4251 if (is_array($array_options) && count($array_options) > 0) {
4253 foreach ($array_options as $key => $value) {
4254 $this->line->array_options[$key] = $array_options[$key];
4258 $result = $this->line->update($user, $notrigger);
4261 if (!empty($fk_parent_line)) {
4267 $this->db->commit();
4270 $this->error = $this->line->error;
4271 $this->db->rollback();
4275 $this->error =
"Invoice statut makes operation forbidden";
4289 $sql =
'SELECT fd.situation_percent FROM '.MAIN_DB_PREFIX.
'facturedet fd
4290 INNER JOIN '.MAIN_DB_PREFIX.
'facture f ON (fd.fk_facture = f.rowid)
4291 WHERE fd.fk_prev_id = '.((int) $idline).
' AND f.fk_statut <> 0';
4293 $result = $this->db->query($sql);
4295 $this->error = $this->db->error();
4299 $obj = $this->db->fetch_object($result);
4301 if ($obj ===
null) {
4304 return ($situation_percent < $obj->situation_percent);
4320 global $mysoc, $user;
4323 if (($line->info_bits & 2) == 2) {
4327 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
4330 if ($percent > 100) {
4333 $line->situation_percent = $percent;
4334 $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);
4335 $line->total_ht = $tabprice[0];
4336 $line->total_tva = $tabprice[1];
4337 $line->total_ttc = $tabprice[2];
4338 $line->total_localtax1 = $tabprice[9];
4339 $line->total_localtax2 = $tabprice[10];
4340 $line->multicurrency_total_ht = $tabprice[16];
4341 $line->multicurrency_total_tva = $tabprice[17];
4342 $line->multicurrency_total_ttc = $tabprice[18];
4343 $line->update($user);
4346 if ($update_price) {
4362 dol_syslog(get_class($this).
"::deleteline rowid=".((
int) $rowid), LOG_DEBUG);
4364 if ($this->
status != self::STATUS_DRAFT) {
4365 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
4371 $line->context = $this->context;
4374 $result = $line->fetch($rowid);
4375 if (!($result > 0)) {
4380 if ($id > 0 && $line->fk_facture != $id) {
4381 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
4388 $staticline = clone $line;
4389 $line->oldline = $staticline;
4391 if ($line->delete($user) > 0) {
4395 $this->db->commit();
4398 $this->db->rollback();
4399 $this->error = $this->db->lasterror();
4403 $this->db->rollback();
4404 $this->error = $line->error;
4423 dol_syslog(get_class($this).
"::set_remise is deprecated, use setDiscount instead", LOG_NOTICE);
4424 return $this->
setDiscount($user, $remise, $notrigger);
4439 if (empty($remise)) {
4443 if ($user->hasRight(
'facture',
'creer')) {
4450 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture';
4451 $sql .=
' SET remise_percent = '.((float) $remise);
4452 $sql .=
" WHERE rowid = ".((int) $this->
id);
4453 $sql .=
' AND fk_statut = '.self::STATUS_DRAFT;
4456 $resql = $this->db->query($sql);
4458 $this->errors[] = $this->db->error();
4462 if (!$notrigger && empty($error)) {
4472 $this->remise_percent = $remise;
4475 $this->db->commit();
4478 foreach ($this->errors as $errmsg) {
4479 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
4480 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
4482 $this->db->rollback();
4569 global $conf, $langs;
4571 if ($this->module_source ==
'takepos') {
4572 $langs->load(
'cashdesk');
4574 $moduleName =
'takepos';
4575 $moduleSourceName =
'Takepos';
4576 $addonConstName =
'TAKEPOS_REF_ADDON';
4580 $conf->global->TAKEPOS_REF_ADDON =
'mod_takepos_ref_simple';
4583 $addon = $conf->global->TAKEPOS_REF_ADDON;
4585 $langs->load(
'bills');
4587 $moduleName =
'facture';
4588 $moduleSourceName =
'Invoice';
4589 $addonConstName =
'FACTURE_ADDON';
4593 $conf->global->FACTURE_ADDON =
'mod_facture_terre';
4595 $conf->global->FACTURE_ADDON =
'mod_facture_terre';
4597 $conf->global->FACTURE_ADDON =
'mod_facture_mercure';
4600 $addon = $conf->global->FACTURE_ADDON;
4603 if (!empty($addon)) {
4604 dol_syslog(
"Call getNextNumRef with ".$addonConstName.
" = " .
getDolGlobalString(
'FACTURE_ADDON').
", thirdparty=".$soc->name.
", type=".$soc->typent_code.
", mode=".$mode, LOG_DEBUG);
4608 $file = $addon.
'.php';
4609 $classname = $addon;
4613 $dirmodels = array_merge(array(
'/'), (array) $conf->modules_parts[
'models']);
4614 foreach ($dirmodels as $reldir) {
4615 $dir =
dol_buildpath($reldir.
'core/modules/'.$moduleName.
'/');
4618 if (is_file($dir.$file) && is_readable($dir.$file)) {
4619 $mybool |= include_once $dir.$file;
4625 $file = $addon.
'/'.$addon.
'.modules.php';
4626 $classname =
'mod_'.$moduleName.
'_'.$addon;
4627 $classname = preg_replace(
'/\-.*$/',
'', $classname);
4629 foreach ($conf->file->dol_document_root as $dirroot) {
4630 $dir = $dirroot.
'/core/modules/'.$moduleName.
'/';
4633 if (is_file($dir.$file) && is_readable($dir.$file)) {
4634 $mybool |= include_once $dir.$file;
4644 $obj =
new $classname();
4646 $numref = $obj->getNextValue($soc, $this, $mode);
4653 if ($mode !=
'last' && !$numref) {
4654 $this->error = $obj->error;
4660 $langs->load(
'errors');
4661 print $langs->trans(
'Error').
' '.$langs->trans(
'ErrorModuleSetupNotComplete', $langs->transnoentitiesnoconv($moduleSourceName));
4674 $sql =
'SELECT c.rowid, datec, date_valid as datev, tms as datem,';
4675 $sql .=
' date_closing as dateclosing,';
4676 $sql .=
' fk_user_author, fk_user_valid, fk_user_closing';
4677 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facture as c';
4678 $sql .=
' WHERE c.rowid = '.((int) $id);
4680 $result = $this->db->query($sql);
4682 if ($this->db->num_rows($result)) {
4683 $obj = $this->db->fetch_object($result);
4685 $this->
id = $obj->rowid;
4686 $this->user_creation_id = $obj->fk_user_author;
4687 $this->user_validation_id = $obj->fk_user_valid;
4688 $this->user_closing_id = $obj->fk_user_closing;
4690 $this->date_creation = $this->db->jdate($obj->datec);
4691 $this->date_modification = $this->db->jdate($obj->datem);
4692 $this->date_validation = $this->db->jdate($obj->datev);
4693 $this->date_closing = $this->db->jdate($obj->dateclosing);
4695 $this->db->free($result);
4716 public function liste_array($shortlist = 0, $draft = 0, $excluser =
null, $socid = 0, $limit = 0, $offset = 0, $sortfield =
'f.datef,f.rowid', $sortorder =
'DESC')
4719 global $conf, $user;
4723 $sql =
"SELECT s.rowid, s.nom as name, s.client,";
4724 $sql .=
" f.rowid as fid, f.ref as ref, f.datef as df";
4725 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4726 $sql .=
", sc.fk_soc, sc.fk_user";
4728 $sql .=
" FROM ".MAIN_DB_PREFIX.
"societe as s, ".MAIN_DB_PREFIX.
"facture as f";
4729 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4730 $sql .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
4732 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice').
")";
4733 $sql .=
" AND f.fk_soc = s.rowid";
4734 if (!$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
4735 $sql .=
" AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
4738 $sql .=
" AND s.rowid = ".((int) $socid);
4741 $sql .=
" AND f.fk_statut = ".self::STATUS_DRAFT;
4743 if (is_object($excluser)) {
4744 $sql .=
" AND f.fk_user_author <> ".((int) $excluser->id);
4746 $sql .= $this->db->order($sortfield, $sortorder);
4747 $sql .= $this->db->plimit($limit, $offset);
4749 $result = $this->db->query($sql);
4751 $numc = $this->db->num_rows($result);
4754 while ($i < $numc) {
4755 $obj = $this->db->fetch_object($result);
4757 if ($shortlist == 1) {
4758 $ga[$obj->fid] = $obj->ref;
4759 } elseif ($shortlist == 2) {
4760 $ga[$obj->fid] = $obj->ref.
' ('.$obj->name.
')';
4762 $ga[$i][
'id'] = $obj->fid;
4763 $ga[$i][
'ref'] = $obj->ref;
4764 $ga[$i][
'name'] = $obj->name;
4793 $sql =
"SELECT f.rowid as rowid, f.ref, f.fk_statut as status, f.paye as paid,";
4794 $sql .=
" ff.rowid as rowidnext";
4796 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4797 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"paiement_facture as pf ON f.rowid = pf.fk_facture";
4798 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facture as ff ON f.rowid = ff.fk_facture_source";
4799 $sql .=
" WHERE (f.fk_statut = ".self::STATUS_VALIDATED.
" OR (f.fk_statut = ".self::STATUS_ABANDONED.
" AND f.close_code = '".self::CLOSECODE_ABANDONED.
"'))";
4800 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4801 $sql .=
" AND f.paye = 0";
4802 $sql .=
" AND pf.fk_paiement IS NULL";
4803 $sql .=
" AND ff.fk_statut IS NULL";
4805 $sql .=
" AND f.fk_soc = ".((int) $socid);
4808 $sql .=
" ORDER BY f.ref";
4810 dol_syslog(get_class($this).
"::list_replacable_invoices", LOG_DEBUG);
4811 $resql = $this->db->query($sql);
4813 while ($obj = $this->db->fetch_object($resql)) {
4814 $return[$obj->rowid] = array(
4815 'id' => $obj->rowid,
4817 'status' => $obj->status,
4818 'paid' => $obj->paid,
4825 $this->error = $this->db->error();
4848 $sql =
"SELECT f.rowid as rowid, f.ref, f.fk_statut, f.type, f.subtype, f.paye, pf.fk_paiement";
4849 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4850 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"paiement_facture as pf ON f.rowid = pf.fk_facture";
4851 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facture as ff ON (f.rowid = ff.fk_facture_source AND ff.type=".self::TYPE_REPLACEMENT.
")";
4852 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice').
")";
4853 $sql .=
" AND f.fk_statut in (".self::STATUS_VALIDATED.
",".self::STATUS_CLOSED.
")";
4857 $sql .=
" AND ff.type IS NULL";
4858 $sql .=
" AND f.type <> ".self::TYPE_CREDIT_NOTE;
4862 $sql .=
" AND (f.type <> ".self::TYPE_SITUATION.
" OR f.rowid IN ";
4863 $sql .=
'(SELECT MAX(fs.rowid)';
4864 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as fs";
4865 $sql .=
" WHERE fs.entity IN (".getEntity(
'invoice').
")";
4866 $sql .=
" AND fs.type = ".self::TYPE_SITUATION;
4867 $sql .=
" AND fs.fk_statut IN (".self::STATUS_VALIDATED.
",".self::STATUS_CLOSED.
")";
4869 $sql .=
" AND fs.fk_soc = ".((int) $socid);
4871 $sql .=
" GROUP BY fs.situation_cycle_ref)";
4874 $sql .=
" AND f.type <> ".self::TYPE_SITUATION;
4878 $sql .=
" AND f.fk_soc = ".((int) $socid);
4880 $sql .=
" ORDER BY f.ref";
4882 dol_syslog(get_class($this).
"::list_qualified_avoir_invoices", LOG_DEBUG);
4883 $resql = $this->db->query($sql);
4885 while ($obj = $this->db->fetch_object($resql)) {
4887 if ($obj->fk_statut == self::STATUS_VALIDATED) {
4890 if ($obj->fk_statut == self::STATUS_CLOSED) {
4895 $paymentornot = ($obj->fk_paiement ? 1 : 0);
4896 $return[$obj->rowid] = array(
'ref'=>$obj->ref,
'status'=>$obj->fk_statut,
'type'=>$obj->type,
'paye'=>$obj->paye,
'paymentornot'=>$paymentornot);
4902 $this->error = $this->db->error();
4918 global $conf, $langs;
4922 $sql =
"SELECT f.rowid, f.date_lim_reglement as datefin, f.fk_statut as status, f.total_ht";
4923 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
4924 if (!$user->hasRight(
'societe',
'client',
'voir') && !$user->socid) {
4925 $sql .=
" JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON f.fk_soc = sc.fk_soc";
4926 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
4929 $sql .= $clause.
" f.paye=0";
4930 $sql .=
" AND f.entity IN (".getEntity(
'invoice').
")";
4931 $sql .=
" AND f.fk_statut = ".self::STATUS_VALIDATED;
4933 $sql .=
" AND f.fk_soc = ".((int) $user->socid);
4936 $resql = $this->db->query($sql);
4938 $langs->load(
"bills");
4942 $response->warning_delay = $conf->facture->client->warning_delay / 60 / 60 / 24;
4943 $response->label = $langs->trans(
"CustomerBillsUnpaid");
4944 $response->labelShort = $langs->trans(
"Unpaid");
4945 $response->url = DOL_URL_ROOT.
'/compta/facture/list.php?search_status=1&mainmenu=billing&leftmenu=customers_bills';
4948 $generic_facture =
new Facture($this->db);
4950 while ($obj = $this->db->fetch_object($resql)) {
4951 $generic_facture->date_lim_reglement = $this->db->jdate($obj->datefin);
4952 $generic_facture->statut = $obj->status;
4953 $generic_facture->status = $obj->status;
4955 $response->nbtodo++;
4956 $response->total += $obj->total_ht;
4958 if ($generic_facture->hasDelay()) {
4959 $response->nbtodolate++;
4960 $response->url_late = DOL_URL_ROOT.
'/compta/facture/list.php?search_option=late&mainmenu=billing&leftmenu=customers_bills';
4964 $this->db->free($resql);
4968 $this->error = $this->db->error();
5007 global $conf, $langs, $user;
5011 $nownotime =
dol_mktime(0, 0, 0, $arraynow[
'mon'], $arraynow[
'mday'], $arraynow[
'year']);
5016 $sql =
"SELECT rowid";
5017 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
5018 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
5019 $sql .= $this->db->plimit(100);
5021 $resql = $this->db->query($sql);
5023 $num_prods = $this->db->num_rows($resql);
5025 while ($i < $num_prods) {
5027 $row = $this->db->fetch_row($resql);
5028 $prodids[$i] = $row[0];
5032 if (empty($num_prods)) {
5039 $this->
ref =
'SPECIMEN';
5040 $this->specimen = 1;
5042 $this->date = $nownotime;
5043 $this->date_lim_reglement = $nownotime + 3600 * 24 * 30;
5044 $this->cond_reglement_id = 1;
5045 $this->cond_reglement_code =
'RECEP';
5047 $this->mode_reglement_id = 0;
5048 $this->mode_reglement_code =
'';
5050 $this->note_public =
'This is a comment (public)';
5051 $this->note_private =
'This is a comment (private)';
5052 $this->note =
'This is a comment (private)';
5054 $this->fk_user_author = $user->id;
5056 $this->multicurrency_tx = 1;
5057 $this->multicurrency_code = $conf->currency;
5059 $this->fk_incoterms = 0;
5060 $this->location_incoterms =
'';
5062 if (empty($option) || $option !=
'nolines') {
5066 while ($xnbp < $nbp) {
5068 $line->desc = $langs->trans(
"Description").
" ".$xnbp;
5070 $line->subprice = 100;
5071 $line->tva_tx = 19.6;
5072 $line->localtax1_tx = 0;
5073 $line->localtax2_tx = 0;
5074 $line->remise_percent = 0;
5076 $prodid = mt_rand(1, $num_prods);
5077 $line->fk_product = $prodids[$prodid];
5079 $line->total_ht = -100;
5080 $line->total_ttc = -119.6;
5081 $line->total_tva = -19.6;
5082 $line->multicurrency_total_ht = -200;
5083 $line->multicurrency_total_ttc = -239.2;
5084 $line->multicurrency_total_tva = -39.2;
5085 } elseif ($xnbp == 2) {
5086 $line->subprice = -100;
5087 $line->total_ht = -100;
5088 $line->total_ttc = -119.6;
5089 $line->total_tva = -19.6;
5090 $line->remise_percent = 0;
5091 $line->multicurrency_total_ht = -200;
5092 $line->multicurrency_total_ttc = -239.2;
5093 $line->multicurrency_total_tva = -39.2;
5094 } elseif ($xnbp == 3) {
5095 $prodid = mt_rand(1, $num_prods);
5096 $line->fk_product = $prodids[$prodid];
5097 $line->total_ht = 50;
5098 $line->total_ttc = 59.8;
5099 $line->total_tva = 9.8;
5100 $line->multicurrency_total_ht = 100;
5101 $line->multicurrency_total_ttc = 119.6;
5102 $line->multicurrency_total_tva = 19.6;
5103 $line->remise_percent = 50;
5105 $prodid = mt_rand(1, $num_prods);
5106 $line->fk_product = $prodids[$prodid];
5107 $line->total_ht = 100;
5108 $line->total_ttc = 119.6;
5109 $line->total_tva = 19.6;
5110 $line->multicurrency_total_ht = 200;
5111 $line->multicurrency_total_ttc = 239.2;
5112 $line->multicurrency_total_tva = 39.2;
5113 $line->remise_percent = 0;
5116 $this->lines[$xnbp] = $line;
5119 $this->total_ht += $line->total_ht;
5120 $this->total_tva += $line->total_tva;
5121 $this->total_ttc += $line->total_ttc;
5123 $this->multicurrency_total_ht += $line->multicurrency_total_ht;
5124 $this->multicurrency_total_tva += $line->multicurrency_total_tva;
5125 $this->multicurrency_total_ttc += $line->multicurrency_total_ttc;
5129 $this->revenuestamp = 0;
5133 $line->desc = $langs->trans(
"Description").
" (offered line)";
5135 $line->subprice = 100;
5136 $line->tva_tx = 19.6;
5137 $line->localtax1_tx = 0;
5138 $line->localtax2_tx = 0;
5139 $line->remise_percent = 100;
5140 $line->total_ht = 0;
5141 $line->total_ttc = 0;
5142 $line->total_tva = 0;
5143 $line->multicurrency_total_ht = 0;
5144 $line->multicurrency_total_ttc = 0;
5145 $line->multicurrency_total_tva = 0;
5146 $prodid = mt_rand(1, $num_prods);
5147 $line->fk_product = $prodids[$prodid];
5149 $this->lines[$xnbp] = $line;
5163 global $conf, $user;
5165 $this->nb = array();
5169 $sql =
"SELECT count(f.rowid) as nb";
5170 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture as f";
5171 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON f.fk_soc = s.rowid";
5172 if (!$user->hasRight(
'societe',
'client',
'voir') && !$user->socid) {
5173 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON s.rowid = sc.fk_soc";
5174 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
5177 $sql .=
" ".$clause.
" f.entity IN (".
getEntity(
'invoice').
")";
5179 $resql = $this->db->query($sql);
5181 while ($obj = $this->db->fetch_object($resql)) {
5182 $this->nb[
"invoices"] = $obj->nb;
5184 $this->db->free($resql);
5188 $this->error = $this->db->error();
5214 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
5216 global $conf, $langs;
5218 $outputlangs->loadLangs(array(
"bills",
"products"));
5222 $thisTypeConfName =
'FACTURE_ADDON_PDF_'.$this->type;
5224 if (!empty($this->model_pdf)) {
5225 $modele = $this->model_pdf;
5229 $modele = $conf->global->FACTURE_ADDON_PDF;
5233 $modelpath =
"core/modules/facture/doc/";
5235 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
5245 $sql =
'SELECT max(situation_cycle_ref) FROM '.MAIN_DB_PREFIX.
'facture as f';
5246 $sql .=
" WHERE f.entity IN (".getEntity(
'invoice', 0).
")";
5247 $resql = $this->db->query($sql);
5249 if ($this->db->num_rows($resql) > 0) {
5250 $res = $this->db->fetch_array($resql);
5251 $ref = $res[
'max(situation_cycle_ref)'];
5256 $this->db->free($resql);
5259 $this->error = $this->db->lasterror();
5260 dol_syslog(
"Error sql=".$sql.
", error=".$this->error, LOG_ERR);
5274 return ($this->situation_counter == 1);
5288 $sql =
'SELECT rowid FROM '.MAIN_DB_PREFIX.
'facture';
5289 $sql .=
' WHERE situation_cycle_ref = '.((int) $this->situation_cycle_ref);
5290 $sql .=
' AND situation_counter < '.((int) $this->situation_counter);
5291 $sql .=
' AND entity = '.($this->entity > 0 ? $this->entity : $conf->entity);
5292 $resql = $this->db->query($sql);
5294 if ($resql && $this->db->num_rows($resql) > 0) {
5295 while ($row = $this->db->fetch_object($resql)) {
5297 $situation =
new Facture($this->db);
5298 $situation->fetch($id);
5299 $res[] = $situation;
5302 $this->error = $this->db->error();
5303 dol_syslog(
"Error sql=".$sql.
", error=".$this->error, LOG_ERR);
5323 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'facture SET situation_final = '.((int) $this->situation_final).
' WHERE rowid = '.((int) $this->
id);
5326 $resql = $this->db->query($sql);
5328 $this->errors[] = $this->db->error();
5332 if (!$notrigger && empty($error)) {
5342 $this->db->commit();
5345 foreach ($this->errors as $errmsg) {
5346 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
5347 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
5349 $this->db->rollback();
5365 if (!empty($this->situation_cycle_ref)) {
5367 $sql =
'SELECT max(situation_counter) FROM '.MAIN_DB_PREFIX.
'facture';
5368 $sql .=
' WHERE situation_cycle_ref = '.((int) $this->situation_cycle_ref);
5369 $sql .=
' AND entity = '.($this->entity > 0 ? $this->entity : $conf->entity);
5370 $resql = $this->db->query($sql);
5372 if ($resql && $this->db->num_rows($resql) > 0) {
5373 $res = $this->db->fetch_array($resql);
5374 $last = $res[
'max(situation_counter)'];
5375 return ($last == $this->situation_counter);
5377 $this->error = $this->db->lasterror();
5378 dol_syslog(get_class($this).
"::select Error ".$this->error, LOG_ERR);
5436 $hasDelay = $this->date_lim_reglement < ($now - $conf->facture->client->warning_delay);
5437 if ($hasDelay && !empty($this->retained_warranty) && !empty($this->retained_warranty_date_limit)) {
5439 $totalpaid = (float) $totalpaid;
5441 if ($totalpaid >= 0 && $RetainedWarrantyAmount >= 0) {
5442 if (($totalpaid < $this->total_ttc - $RetainedWarrantyAmount) && $this->date_lim_reglement < ($now - $conf->facture->client->warning_delay)) {
5444 } elseif ($totalpaid < $this->total_ttc && $this->retained_warranty_date_limit < ($now - $conf->facture->client->warning_delay)) {
5467 $displayWarranty =
false;
5468 if (!empty($this->retained_warranty)) {
5469 $displayWarranty =
true;
5473 $displayWarranty =
false;
5474 if (!empty($this->situation_final)) {
5475 $displayWarranty =
true;
5478 $displayWarranty =
true;
5480 foreach ($this->lines as $i => $line) {
5481 if ($line->product_type < 2 && $line->situation_percent < 100) {
5482 $displayWarranty =
false;
5490 return $displayWarranty;
5500 if (empty($this->retained_warranty)) {
5504 $retainedWarrantyAmount = 0;
5508 $displayWarranty =
true;
5510 if (!empty($this->lines)) {
5511 foreach ($this->lines as $i => $line) {
5512 if ($line->product_type < 2 && $line->situation_percent < 100) {
5513 $displayWarranty =
false;
5519 if ($displayWarranty && !empty($this->situation_final)) {
5521 $TPreviousIncoice = $this->tab_previous_situation_invoice;
5524 foreach ($TPreviousIncoice as &$fac) {
5525 $total2BillWT += $fac->total_ttc;
5527 $total2BillWT += $this->total_ttc;
5529 $retainedWarrantyAmount = $total2BillWT * $this->retained_warranty / 100;
5535 $retainedWarrantyAmount = $this->total_ttc * $this->retained_warranty / 100;
5538 if ($rounding < 0) {
5542 if ($rounding > 0) {
5543 return round($retainedWarrantyAmount, $rounding);
5546 return $retainedWarrantyAmount;
5557 dol_syslog(get_class($this).
'::setRetainedWarranty('.$value.
')');
5559 if ($this->
status >= 0) {
5560 $fieldname =
'retained_warranty';
5561 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
5562 $sql .=
" SET ".$fieldname.
" = ".((float) $value);
5563 $sql .=
' WHERE rowid='.((int) $this->
id);
5565 if ($this->db->query($sql)) {
5566 $this->retained_warranty = (float) $value;
5569 dol_syslog(get_class($this).
'::setRetainedWarranty Erreur '.$sql.
' - '.$this->db->error());
5570 $this->error = $this->db->error();
5574 dol_syslog(get_class($this).
'::setRetainedWarranty, status of the object is incompatible');
5575 $this->error =
'Status of the object is incompatible '.$this->status;
5590 if (!$timestamp && $dateYmd) {
5591 $timestamp = $this->db->jdate($dateYmd);
5595 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit('.$timestamp.
')');
5596 if ($this->
status >= 0) {
5597 $fieldname =
'retained_warranty_date_limit';
5598 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
5599 $sql .=
" SET ".$fieldname.
" = ".(strval($timestamp) !=
'' ?
"'".$this->db->idate($timestamp).
"'" :
'null');
5600 $sql .=
' WHERE rowid = '.((int) $this->
id);
5602 if ($this->db->query($sql)) {
5603 $this->retained_warranty_date_limit = $timestamp;
5606 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit Erreur '.$sql.
' - '.$this->db->error());
5607 $this->error = $this->db->error();
5611 dol_syslog(get_class($this).
'::setRetainedWarrantyDateLimit, status of the object is incompatible');
5612 $this->error =
'Status of the object is incompatible '.$this->status;
5631 global $conf, $langs, $user;
5637 $errorsMsg = array();
5639 $langs->load(
"bills");
5641 if (!isModEnabled(
'facture')) {
5642 $this->output .= $langs->trans(
'ModuleNotEnabled', $langs->transnoentitiesnoconv(
"Facture"));
5645 if (!in_array($datetouse, array(
'duedate',
'invoicedate'))) {
5646 $this->output .=
'Bad value for parameter datetouse. Must be "duedate" or "invoicedate"';
5656 require_once DOL_DOCUMENT_ROOT.
'/core/lib/date.lib.php';
5657 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmail.class.php';
5658 require_once DOL_DOCUMENT_ROOT.
'/core/class/CMailFile.class.php';
5659 $formmail =
new FormMail($this->db);
5664 $tmpinvoice =
new Facture($this->db);
5669 $sql =
"SELECT rowid as id FROM ".MAIN_DB_PREFIX.
"facture as f";
5670 if (!empty($paymentmode) && $paymentmode !=
'all') {
5671 $sql .=
", ".MAIN_DB_PREFIX.
"c_paiement as cp";
5673 $sql .=
" WHERE f.paye = 0";
5674 $sql .=
" AND f.fk_statut = ".self::STATUS_VALIDATED;
5675 if ($datetouse ==
'invoicedate') {
5676 $sql .=
" AND f.datef = '".$this->db->idate($tmpidate,
'gmt').
"'";
5678 $sql .=
" AND f.date_lim_reglement = '".$this->db->idate($tmpidate,
'gmt').
"'";
5680 $sql .=
" AND f.entity IN (".getEntity(
'facture', 0).
")";
5681 if (!empty($paymentmode) && $paymentmode !=
'all') {
5682 $sql .=
" AND f.fk_mode_reglement = cp.id AND cp.code = '".$this->db->escape($paymentmode).
"'";
5685 if ($datetouse ==
'invoicedate') {
5686 $sql .= $this->db->order(
"datef",
"ASC");
5688 $sql .= $this->db->order(
"date_lim_reglement",
"ASC");
5691 $resql = $this->db->query($sql);
5694 if ($datetouse ==
'invoicedate') {
5695 $this->output .= $langs->transnoentitiesnoconv(
"SearchValidatedInvoicesWithDate", $stmpidate);
5697 $this->output .= $langs->transnoentitiesnoconv(
"SearchUnpaidInvoicesWithDueDate", $stmpidate);
5699 if (!empty($paymentmode) && $paymentmode !=
'all') {
5700 $this->output .=
' ('.$langs->transnoentitiesnoconv(
"PaymentMode").
' '.$paymentmode.
')';
5702 $this->output .=
'<br>';
5705 while ($obj = $this->db->fetch_object($resql)) {
5708 $res = $tmpinvoice->fetch($obj->id);
5710 $tmpinvoice->fetch_thirdparty();
5712 $outputlangs =
new Translate(
'', $conf);
5713 if ($tmpinvoice->thirdparty->default_lang) {
5714 $outputlangs->setDefaultLang($tmpinvoice->thirdparty->default_lang);
5715 $outputlangs->loadLangs(array(
"main",
"bills"));
5717 $outputlangs = $langs;
5721 $arraymessage = $formmail->getEMailTemplate($this->db,
'facture_send', $user, $outputlangs, (is_numeric($template) ? $template : 0), 1, (is_numeric($template) ?
'' : $template));
5722 if (is_numeric($arraymessage) && $arraymessage <= 0) {
5723 $langs->load(
"errors");
5724 $this->output .= $langs->trans(
'ErrorFailedToFindEmailTemplate', $template);
5737 $sendTopic =
make_substitutions(empty($arraymessage->topic) ? $outputlangs->transnoentitiesnoconv(
'InformationMessage') : $arraymessage->topic, $substitutionarray, $outputlangs, 1);
5740 $content = $outputlangs->transnoentitiesnoconv($arraymessage->content);
5746 if ($forcerecipient) {
5747 $to = array($forcerecipient);
5749 $res = $tmpinvoice->fetch_thirdparty();
5750 $recipient = $tmpinvoice->thirdparty;
5752 $tmparraycontact = $tmpinvoice->liste_contact(-1,
'external', 0,
'BILLING');
5753 if (is_array($tmparraycontact) && count($tmparraycontact) > 0) {
5754 foreach ($tmparraycontact as $data_email) {
5755 if (!empty($data_email[
'email'])) {
5756 $to[] = $tmpinvoice->thirdparty->contact_get_property($data_email[
'id'],
'email');
5760 if (empty($to) && !empty($recipient->email)) {
5761 $to[] = $recipient->email;
5764 $errormesg =
"Failed to send remind to thirdparty id=".$tmpinvoice->socid.
". No email defined for invoice or customer.";
5768 $errormesg =
"Failed to load recipient with thirdparty id=".$tmpinvoice->socid;
5775 if (!empty($arraymessage->email_from)) {
5776 $from = $arraymessage->email_from;
5779 $errormesg =
"Failed to get sender into global setup MAIN_MAIL_EMAIL_FROM";
5783 if (!$error && !empty($to)) {
5786 $to = implode(
',', $to);
5787 if (!empty($arraymessage->email_to)) {
5788 $to = $to.
','.$arraymessage->email_to;
5792 $errors_to = $conf->global->MAIN_MAIL_ERRORS_TO;
5794 $trackid =
'inv'.$tmpinvoice->id;
5795 $sendcontext =
'standard';
5798 if (!empty($arraymessage->email_tocc)) {
5799 $email_tocc = $arraymessage->email_tocc;
5803 if (!empty($arraymessage->email_tobcc)) {
5804 $email_tobcc = $arraymessage->email_tobcc;
5811 if ($arraymessage->joinfiles == 1 && !empty($tmpinvoice->last_main_doc)) {
5812 $joinFile[] = DOL_DATA_ROOT.
'/'.$tmpinvoice->last_main_doc;
5813 $joinFileName[] = basename($tmpinvoice->last_main_doc);
5814 $joinFileMime[] =
dol_mimetype(DOL_DATA_ROOT.
'/'.$tmpinvoice->last_main_doc);
5818 $cMailFile =
new CMailFile($sendTopic, $to, $from, $sendContent, $joinFile, $joinFileMime, $joinFileName, $email_tocc, $email_tobcc, 0, 1, $errors_to,
'', $trackid,
'', $sendcontext,
'');
5821 if ($cMailFile->sendfile()) {
5825 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
5830 $actioncomm->type_code =
'AC_OTH_AUTO';
5831 $actioncomm->socid = $tmpinvoice->thirdparty->id;
5832 $actioncomm->contact_id = 0;
5834 $actioncomm->code =
'AC_EMAIL';
5835 $actioncomm->label =
'sendEmailsRemindersOnInvoiceDueDateOK (nbdays='.$nbdays.
' paymentmode='.$paymentmode.
' template='.$template.
' datetouse='.$datetouse.
' forcerecipient='.$forcerecipient.
')';
5836 $actioncomm->note_private = $sendContent;
5837 $actioncomm->fk_project = $tmpinvoice->fk_project;
5838 $actioncomm->datep =
dol_now();
5839 $actioncomm->datef = $actioncomm->datep;
5840 $actioncomm->percentage = -1;
5841 $actioncomm->authorid = $user->id;
5842 $actioncomm->userownerid = $user->id;
5844 $actioncomm->email_msgid = $cMailFile->msgid;
5845 $actioncomm->email_subject = $sendTopic;
5846 $actioncomm->email_from = $from;
5847 $actioncomm->email_sender =
'';
5848 $actioncomm->email_to = $to;
5852 $actioncomm->errors_to = $errors_to;
5854 $actioncomm->elementtype =
'invoice';
5855 $actioncomm->fk_element = $tmpinvoice->id;
5859 $actioncomm->create($user);
5861 $errormesg = $cMailFile->error.
' : '.$to;
5865 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
5870 $actioncomm->type_code =
'AC_OTH_AUTO';
5871 $actioncomm->socid = $tmpinvoice->thirdparty->id;
5872 $actioncomm->contact_id = 0;
5874 $actioncomm->code =
'AC_EMAIL';
5875 $actioncomm->label =
'sendEmailsRemindersOnInvoiceDueDateKO';
5876 $actioncomm->note_private = $errormesg;
5877 $actioncomm->fk_project = $tmpinvoice->fk_project;
5878 $actioncomm->datep =
dol_now();
5879 $actioncomm->datef = $actioncomm->datep;
5880 $actioncomm->percentage = -1;
5881 $actioncomm->authorid = $user->id;
5882 $actioncomm->userownerid = $user->id;
5884 $actioncomm->email_msgid = $cMailFile->msgid;
5885 $actioncomm->email_from = $from;
5886 $actioncomm->email_sender =
'';
5887 $actioncomm->email_to = $to;
5891 $actioncomm->errors_to = $errors_to;
5895 $actioncomm->create($user);
5898 $this->db->commit();
5902 $errorsMsg[] = $errormesg;
5905 $errorsMsg[] =
'Failed to fetch record invoice with ID = '.$obj->id;
5915 $this->output .=
'Nb of emails sent : '.$nbMailSend;
5917 dol_syslog(__METHOD__.
" end - ".$this->output, LOG_INFO);
5921 $this->error =
'Nb of emails sent : '.$nbMailSend.
', '.(!empty($errorsMsg)) ? join(
', ', $errorsMsg) : $error;
5923 dol_syslog(__METHOD__.
" end - ".$this->error, LOG_INFO);
5938 $sql =
"SELECT datef";
5939 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture";
5940 $sql .=
" WHERE type = " . (int) $this->
type ;
5941 $sql .=
" AND date_valid IS NOT NULL";
5942 $sql .=
" AND entity IN (".getEntity(
'invoice').
")";
5943 $sql .=
" ORDER BY datef DESC LIMIT 1";
5945 $result = $this->db->query($sql);
5948 if ($this->db->num_rows($result)) {
5949 $obj = $this->db->fetch_object($result);
5950 $last_date = $this->db->jdate($obj->datef);
5951 $invoice_date = $this->date;
5953 $is_last_of_same_type = $invoice_date >= $last_date;
5954 if ($allow_validated_drafts) {
5958 return array($is_last_of_same_type, $last_date);
5981 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
5983 $return =
'<div class="box-flex-item box-flex-grow-zero">';
5984 $return .=
'<div class="info-box info-box-sm">';
5985 $return .=
'<span class="info-box-icon bg-infobox-action">';
5987 $return .=
'</span>';
5988 $return .=
'<div class="info-box-content">';
5989 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl(1) : $this->ref).
'</span>';
5990 if ($selected >= 0) {
5991 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
5993 if (!empty($arraydata[
'thirdparty'])) {
5994 $return .=
'<br><span class="info-box-label">'.$arraydata[
'thirdparty'].
'</span>';
5996 if (property_exists($this,
'date')) {
5997 $return .=
'<br><span class="info-box-label">'.dol_print_date($this->date,
'day').
'</span>';
5999 if (property_exists($this,
'total_ht')) {
6000 $return .=
' <span class="info-box-label amount" title="'.dol_escape_htmltag($langs->trans(
"AmountHT")).
'">'.
price($this->total_ht);
6001 $return .=
' '.$langs->trans(
"HT");
6002 $return .=
'</span>';
6004 if (method_exists($this,
'getLibStatut')) {
6005 $alreadypaid = (empty($arraydata[
'alreadypaid']) ? 0 : $arraydata[
'alreadypaid']);
6006 $return .=
'<br><div class="info-box-status">'.$this->getLibStatut(3, $alreadypaid).
'</div>';
6008 $return .=
'</div>';
6009 $return .=
'</div>';
6010 $return .=
'</div>';
6024 public $element =
'facturedet';
6029 public $table_element =
'facturedet';
6046 public $localtax1_type;
6047 public $localtax2_type;
6048 public $fk_remise_except;
6051 public $fk_fournprice;
6061 public $remise_percent;
6079 public $fk_warehouse;
6088 public $fk_code_ventilation = 0;
6094 public $skip_update_total;
6099 public $situation_percent;
6124 $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,';
6125 $sql .=
' fd.localtax1_tx, fd. localtax2_tx, fd.remise, fd.remise_percent, fd.fk_remise_except, fd.subprice, fd.ref_ext,';
6126 $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,';
6127 $sql .=
' fd.info_bits, fd.special_code, fd.total_ht, fd.total_tva, fd.total_ttc, fd.total_localtax1, fd.total_localtax2, fd.rang,';
6128 $sql .=
' fd.fk_code_ventilation,';
6129 $sql .=
' fd.fk_unit, fd.fk_user_author, fd.fk_user_modif,';
6130 $sql .=
' fd.situation_percent, fd.fk_prev_id,';
6131 $sql .=
' fd.multicurrency_subprice,';
6132 $sql .=
' fd.multicurrency_total_ht,';
6133 $sql .=
' fd.multicurrency_total_tva,';
6134 $sql .=
' fd.multicurrency_total_ttc,';
6135 $sql .=
' p.ref as product_ref, p.label as product_label, p.description as product_desc';
6136 $sql .=
' FROM '.MAIN_DB_PREFIX.
'facturedet as fd';
6137 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON fd.fk_product = p.rowid';
6138 $sql .=
' WHERE fd.rowid = '.((int) $rowid);
6140 $result = $this->db->query($sql);
6142 $objp = $this->db->fetch_object($result);
6145 $this->error =
'InvoiceLine with id '. $rowid .
' not found sql='.$sql;
6149 $this->
rowid = $objp->rowid;
6150 $this->
id = $objp->rowid;
6151 $this->fk_facture = $objp->fk_facture;
6152 $this->fk_parent_line = $objp->fk_parent_line;
6153 $this->label = $objp->custom_label;
6154 $this->desc = $objp->description;
6155 $this->qty = $objp->qty;
6156 $this->subprice = $objp->subprice;
6157 $this->ref_ext = $objp->ref_ext;
6158 $this->vat_src_code = $objp->vat_src_code;
6159 $this->tva_tx = $objp->tva_tx;
6160 $this->localtax1_tx = $objp->localtax1_tx;
6161 $this->localtax2_tx = $objp->localtax2_tx;
6162 $this->remise_percent = $objp->remise_percent;
6163 $this->fk_remise_except = $objp->fk_remise_except;
6164 $this->fk_product = $objp->fk_product;
6165 $this->product_type = $objp->product_type;
6166 $this->date_start = $this->db->jdate($objp->date_start);
6167 $this->date_end = $this->db->jdate($objp->date_end);
6168 $this->info_bits = $objp->info_bits;
6169 $this->tva_npr = ($objp->info_bits & 1 == 1) ? 1 : 0;
6170 $this->special_code = $objp->special_code;
6171 $this->total_ht = $objp->total_ht;
6172 $this->total_tva = $objp->total_tva;
6173 $this->total_localtax1 = $objp->total_localtax1;
6174 $this->total_localtax2 = $objp->total_localtax2;
6175 $this->total_ttc = $objp->total_ttc;
6176 $this->fk_code_ventilation = $objp->fk_code_ventilation;
6177 $this->rang = $objp->rang;
6178 $this->fk_fournprice = $objp->fk_fournprice;
6179 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $this->fk_fournprice, $objp->pa_ht);
6180 $this->pa_ht = $marginInfos[0];
6181 $this->marge_tx = $marginInfos[1];
6182 $this->marque_tx = $marginInfos[2];
6184 $this->
ref = $objp->product_ref;
6186 $this->product_ref = $objp->product_ref;
6187 $this->product_label = $objp->product_label;
6188 $this->product_desc = $objp->product_desc;
6190 $this->fk_unit = $objp->fk_unit;
6191 $this->fk_user_modif = $objp->fk_user_modif;
6192 $this->fk_user_author = $objp->fk_user_author;
6194 $this->situation_percent = $objp->situation_percent;
6195 $this->fk_prev_id = $objp->fk_prev_id;
6197 $this->multicurrency_subprice = $objp->multicurrency_subprice;
6198 $this->multicurrency_total_ht = $objp->multicurrency_total_ht;
6199 $this->multicurrency_total_tva = $objp->multicurrency_total_tva;
6200 $this->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
6204 $this->db->free($result);
6208 $this->error = $this->db->lasterror();
6220 public function insert($notrigger = 0, $noerrorifdiscountalreadylinked = 0)
6222 global $langs, $user, $conf;
6226 $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht ==
'');
6228 dol_syslog(get_class($this).
"::insert rang=".$this->rang, LOG_DEBUG);
6231 $this->desc = trim($this->desc);
6232 if (empty($this->tva_tx)) {
6235 if (empty($this->localtax1_tx)) {
6236 $this->localtax1_tx = 0;
6238 if (empty($this->localtax2_tx)) {
6239 $this->localtax2_tx = 0;
6241 if (empty($this->localtax1_type)) {
6242 $this->localtax1_type = 0;
6244 if (empty($this->localtax2_type)) {
6245 $this->localtax2_type = 0;
6247 if (empty($this->total_localtax1)) {
6248 $this->total_localtax1 = 0;
6250 if (empty($this->total_localtax2)) {
6251 $this->total_localtax2 = 0;
6253 if (empty($this->rang)) {
6256 if (empty($this->remise_percent)) {
6257 $this->remise_percent = 0;
6259 if (empty($this->info_bits)) {
6260 $this->info_bits = 0;
6262 if (empty($this->subprice)) {
6263 $this->subprice = 0;
6265 if (empty($this->ref_ext)) {
6266 $this->ref_ext =
'';
6268 if (empty($this->special_code)) {
6269 $this->special_code = 0;
6271 if (empty($this->fk_parent_line)) {
6272 $this->fk_parent_line = 0;
6274 if (empty($this->fk_prev_id)) {
6275 $this->fk_prev_id = 0;
6277 if (!isset($this->situation_percent) || $this->situation_percent > 100 || (
string) $this->situation_percent ==
'') {
6278 $this->situation_percent = 100;
6281 if (empty($this->pa_ht)) {
6284 if (empty($this->multicurrency_subprice)) {
6285 $this->multicurrency_subprice = 0;
6287 if (empty($this->multicurrency_total_ht)) {
6288 $this->multicurrency_total_ht = 0;
6290 if (empty($this->multicurrency_total_tva)) {
6291 $this->multicurrency_total_tva = 0;
6293 if (empty($this->multicurrency_total_ttc)) {
6294 $this->multicurrency_total_ttc = 0;
6298 if ($this->pa_ht == 0 && $pa_ht_isemptystring) {
6299 if (($result = $this->
defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0) {
6302 $this->pa_ht = $result;
6307 if ($this->product_type < 0) {
6308 $this->error =
'ErrorProductTypeMustBe0orMore';
6311 if (!empty($this->fk_product) && $this->fk_product > 0) {
6315 $this->error =
'ErrorProductIdDoesNotExists';
6316 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6324 $sql =
'INSERT INTO '.MAIN_DB_PREFIX.
'facturedet';
6325 $sql .=
' (fk_facture, fk_parent_line, label, description, qty,';
6326 $sql .=
' vat_src_code, tva_tx, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type,';
6327 $sql .=
' fk_product, product_type, remise_percent, subprice, ref_ext, fk_remise_except,';
6328 $sql .=
' date_start, date_end, fk_code_ventilation, ';
6329 $sql .=
' rang, special_code, fk_product_fournisseur_price, buy_price_ht,';
6330 $sql .=
' info_bits, total_ht, total_tva, total_ttc, total_localtax1, total_localtax2,';
6331 $sql .=
' situation_percent, fk_prev_id,';
6332 $sql .=
' fk_unit, fk_user_author, fk_user_modif,';
6333 $sql .=
' fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc';
6335 $sql .=
" VALUES (".$this->fk_facture.
",";
6336 $sql .=
" ".($this->fk_parent_line > 0 ? $this->fk_parent_line :
"null").
",";
6337 $sql .=
" ".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null").
",";
6338 $sql .=
" '".$this->db->escape($this->desc).
"',";
6339 $sql .=
" ".price2num($this->qty).
",";
6340 $sql .=
" ".(empty($this->vat_src_code) ?
"''" :
"'".$this->db->escape($this->vat_src_code).
"'").
",";
6341 $sql .=
" ".price2num($this->tva_tx).
",";
6342 $sql .=
" ".price2num($this->localtax1_tx).
",";
6343 $sql .=
" ".price2num($this->localtax2_tx).
",";
6344 $sql .=
" '".$this->db->escape($this->localtax1_type).
"',";
6345 $sql .=
" '".$this->db->escape($this->localtax2_type).
"',";
6346 $sql .=
' '.((!empty($this->fk_product) && $this->fk_product > 0) ? $this->fk_product :
"null").
',';
6347 $sql .=
" ".((int) $this->product_type).
",";
6348 $sql .=
" ".price2num($this->remise_percent).
",";
6349 $sql .=
" ".price2num($this->subprice).
",";
6350 $sql .=
" '".$this->db->escape($this->ref_ext).
"',";
6351 $sql .=
' '.(!empty($this->fk_remise_except) ? $this->fk_remise_except :
"null").
',';
6352 $sql .=
" ".(!empty($this->date_start) ?
"'".$this->db->idate($this->date_start).
"'" :
"null").
",";
6353 $sql .=
" ".(!empty($this->date_end) ?
"'".$this->db->idate($this->date_end).
"'" :
"null").
",";
6354 $sql .=
' '.((int) $this->fk_code_ventilation).
',';
6355 $sql .=
' '.((int) $this->rang).
',';
6356 $sql .=
' '.((int) $this->special_code).
',';
6357 $sql .=
' '.(!empty($this->fk_fournprice) ? $this->fk_fournprice :
"null").
',';
6358 $sql .=
' '.price2num($this->pa_ht).
',';
6359 $sql .=
" '".$this->db->escape($this->info_bits).
"',";
6360 $sql .=
" ".price2num($this->total_ht).
",";
6361 $sql .=
" ".price2num($this->total_tva).
",";
6362 $sql .=
" ".price2num($this->total_ttc).
",";
6363 $sql .=
" ".price2num($this->total_localtax1).
",";
6364 $sql .=
" ".price2num($this->total_localtax2);
6365 $sql .=
", ".((float) $this->situation_percent);
6366 $sql .=
", ".(!empty($this->fk_prev_id) ? $this->fk_prev_id :
"null");
6367 $sql .=
", ".(!$this->fk_unit ?
'NULL' : $this->fk_unit);
6368 $sql .=
", ".((int) $user->id);
6369 $sql .=
", ".((int) $user->id);
6370 $sql .=
", ".(int) $this->fk_multicurrency;
6371 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
6372 $sql .=
", ".price2num($this->multicurrency_subprice);
6373 $sql .=
", ".price2num($this->multicurrency_total_ht);
6374 $sql .=
", ".price2num($this->multicurrency_total_tva);
6375 $sql .=
", ".price2num($this->multicurrency_total_ttc);
6378 dol_syslog(get_class($this).
"::insert", LOG_DEBUG);
6379 $resql = $this->db->query($sql);
6381 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
'facturedet');
6382 $this->
rowid = $this->id;
6393 if ($this->fk_remise_except) {
6395 $result = $discount->fetch($this->fk_remise_except);
6400 if ($discount->fk_facture_line > 0) {
6401 if (empty($noerrorifdiscountalreadylinked)) {
6402 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed", $discount->id);
6403 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6404 $this->db->rollback();
6408 $result = $discount->link_to_invoice($this->
rowid, 0);
6410 $this->error = $discount->error;
6411 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6412 $this->db->rollback();
6417 $this->error = $langs->trans(
"ErrorADiscountThatHasBeenRemovedIsIncluded");
6418 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6419 $this->db->rollback();
6423 $this->error = $discount->error;
6424 dol_syslog(get_class($this).
"::insert Error ".$this->error, LOG_ERR);
6425 $this->db->rollback();
6432 $result = $this->
call_trigger(
'LINEBILL_INSERT', $user);
6434 $this->db->rollback();
6440 $this->db->commit();
6443 $this->error = $this->db->lasterror();
6444 $this->db->rollback();
6456 public function update($user =
null, $notrigger = 0)
6458 global $user, $conf;
6462 $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht ==
'');
6465 $this->desc = trim($this->desc);
6466 if (empty($this->ref_ext)) {
6467 $this->ref_ext =
'';
6469 if (empty($this->tva_tx)) {
6472 if (empty($this->localtax1_tx)) {
6473 $this->localtax1_tx = 0;
6475 if (empty($this->localtax2_tx)) {
6476 $this->localtax2_tx = 0;
6478 if (empty($this->localtax1_type)) {
6479 $this->localtax1_type = 0;
6481 if (empty($this->localtax2_type)) {
6482 $this->localtax2_type = 0;
6484 if (empty($this->total_localtax1)) {
6485 $this->total_localtax1 = 0;
6487 if (empty($this->total_localtax2)) {
6488 $this->total_localtax2 = 0;
6490 if (empty($this->remise_percent)) {
6491 $this->remise_percent = 0;
6493 if (empty($this->info_bits)) {
6494 $this->info_bits = 0;
6496 if (empty($this->special_code)) {
6497 $this->special_code = 0;
6499 if (empty($this->product_type)) {
6500 $this->product_type = 0;
6502 if (empty($this->fk_parent_line)) {
6503 $this->fk_parent_line = 0;
6505 if (!isset($this->situation_percent) || $this->situation_percent > 100 || (
string) $this->situation_percent ==
'') {
6506 $this->situation_percent = 100;
6508 if (empty($this->pa_ht)) {
6512 if (empty($this->multicurrency_subprice)) {
6513 $this->multicurrency_subprice = 0;
6515 if (empty($this->multicurrency_total_ht)) {
6516 $this->multicurrency_total_ht = 0;
6518 if (empty($this->multicurrency_total_tva)) {
6519 $this->multicurrency_total_tva = 0;
6521 if (empty($this->multicurrency_total_ttc)) {
6522 $this->multicurrency_total_ttc = 0;
6526 if ($this->product_type < 0) {
6531 if ($this->pa_ht == 0 && $pa_ht_isemptystring) {
6533 $result = $this->
defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product);
6537 $this->pa_ht = $result;
6544 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facturedet SET";
6545 $sql .=
" description='".$this->db->escape($this->desc).
"'";
6546 $sql .=
", ref_ext='".$this->db->escape($this->ref_ext).
"'";
6547 $sql .=
", label=".(!empty($this->label) ?
"'".$this->db->escape($this->label).
"'" :
"null");
6548 $sql .=
", subprice=".price2num($this->subprice);
6549 $sql .=
", remise_percent=".price2num($this->remise_percent);
6550 if ($this->fk_remise_except) {
6551 $sql .=
", fk_remise_except=".$this->fk_remise_except;
6553 $sql .=
", fk_remise_except=null";
6555 $sql .=
", vat_src_code = '".(empty($this->vat_src_code) ?
'' : $this->db->escape($this->vat_src_code)).
"'";
6556 $sql .=
", tva_tx=".price2num($this->tva_tx);
6557 $sql .=
", localtax1_tx=".price2num($this->localtax1_tx);
6558 $sql .=
", localtax2_tx=".price2num($this->localtax2_tx);
6559 $sql .=
", localtax1_type='".$this->db->escape($this->localtax1_type).
"'";
6560 $sql .=
", localtax2_type='".$this->db->escape($this->localtax2_type).
"'";
6561 $sql .=
", qty=".price2num($this->qty);
6562 $sql .=
", date_start=".(!empty($this->date_start) ?
"'".$this->db->idate($this->date_start).
"'" :
"null");
6563 $sql .=
", date_end=".(!empty($this->date_end) ?
"'".$this->db->idate($this->date_end).
"'" :
"null");
6564 $sql .=
", product_type=".$this->product_type;
6565 $sql .=
", info_bits='".$this->db->escape($this->info_bits).
"'";
6566 $sql .=
", special_code='".$this->db->escape($this->special_code).
"'";
6567 if (empty($this->skip_update_total)) {
6568 $sql .=
", total_ht=".price2num($this->total_ht);
6569 $sql .=
", total_tva=".price2num($this->total_tva);
6570 $sql .=
", total_ttc=".price2num($this->total_ttc);
6571 $sql .=
", total_localtax1=".price2num($this->total_localtax1);
6572 $sql .=
", total_localtax2=".price2num($this->total_localtax2);
6574 $sql .=
", fk_product_fournisseur_price=".(!empty($this->fk_fournprice) ?
"'".$this->db->escape($this->fk_fournprice).
"'" :
"null");
6575 $sql .=
", buy_price_ht=".(($this->pa_ht || (string) $this->pa_ht ===
'0') ?
price2num($this->pa_ht) :
"null");
6576 $sql .=
", fk_parent_line=".($this->fk_parent_line > 0 ? $this->fk_parent_line :
"null");
6577 if (!empty($this->rang)) {
6578 $sql .=
", rang=".((int) $this->rang);
6580 $sql .=
", situation_percent = ".((float) $this->situation_percent);
6581 $sql .=
", fk_unit = ".(!$this->fk_unit ?
'NULL' : $this->fk_unit);
6582 $sql .=
", fk_user_modif = ".((int) $user->id);
6585 $sql .=
", multicurrency_subprice=".price2num($this->multicurrency_subprice);
6586 $sql .=
", multicurrency_total_ht=".price2num($this->multicurrency_total_ht);
6587 $sql .=
", multicurrency_total_tva=".price2num($this->multicurrency_total_tva);
6588 $sql .=
", multicurrency_total_ttc=".price2num($this->multicurrency_total_ttc);
6590 $sql .=
" WHERE rowid = ".((int) $this->
rowid);
6592 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
6593 $resql = $this->db->query($sql);
6596 $this->
id = $this->rowid;
6603 if (!$error && !$notrigger) {
6605 $result = $this->
call_trigger(
'LINEBILL_MODIFY', $user);
6607 $this->db->rollback();
6612 $this->db->commit();
6615 $this->error = $this->db->error();
6616 $this->db->rollback();
6628 public function delete($tmpuser =
null, $notrigger =
false)
6635 if (empty($notrigger)) {
6636 $result = $this->
call_trigger(
'LINEBILL_DELETE', $user);
6638 $this->db->rollback();
6647 $this->db->rollback();
6652 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'societe_remise_except';
6653 $sql .=
' SET fk_facture_line = NULL';
6654 $sql .=
' WHERE fk_facture_line = '.((int) $this->
id);
6656 dol_syslog(get_class($this).
"::deleteline", LOG_DEBUG);
6657 $result = $this->db->query($sql);
6659 $this->error = $this->db->error();
6660 $this->errors[] = $this->error;
6661 $this->db->rollback();
6665 $sql =
'UPDATE '.MAIN_DB_PREFIX.
'element_time';
6666 $sql .=
' SET invoice_id = NULL, invoice_line_id = NULL';
6667 $sql .=
' WHERE invoice_line_id = '.((int) $this->
id);
6668 if (!$this->db->query($sql)) {
6669 $this->error = $this->db->error().
" sql=".$sql;
6670 $this->errors[] = $this->error;
6671 $this->db->rollback();
6675 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"facturedet WHERE rowid = ".((int) $this->
id);
6677 if ($this->db->query($sql)) {
6678 $this->db->commit();
6681 $this->error = $this->db->error().
" sql=".$sql;
6682 $this->errors[] = $this->error;
6683 $this->db->rollback();
6699 dol_syslog(get_class($this).
"::update_total", LOG_DEBUG);
6702 if (empty($this->total_localtax1)) {
6703 $this->total_localtax1 = 0;
6705 if (empty($this->total_localtax2)) {
6706 $this->total_localtax2 = 0;
6710 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"facturedet SET";
6711 $sql .=
" total_ht=".price2num($this->total_ht);
6712 $sql .=
",total_tva=".price2num($this->total_tva);
6713 $sql .=
",total_localtax1=".price2num($this->total_localtax1);
6714 $sql .=
",total_localtax2=".price2num($this->total_localtax2);
6715 $sql .=
",total_ttc=".price2num($this->total_ttc);
6716 $sql .=
" WHERE rowid = ".((int) $this->
rowid);
6718 dol_syslog(get_class($this).
"::update_total", LOG_DEBUG);
6720 $resql = $this->db->query($sql);
6722 $this->db->commit();
6725 $this->error = $this->db->error();
6726 $this->db->rollback();
6743 global $invoicecache;
6745 if (is_null($this->fk_prev_id) || empty($this->fk_prev_id) || $this->fk_prev_id ==
"") {
6749 if (!isset($invoicecache[$invoiceid])) {
6750 $invoicecache[$invoiceid] =
new Facture($this->db);
6751 $invoicecache[$invoiceid]->fetch($invoiceid);
6757 $sql =
"SELECT situation_percent FROM ".MAIN_DB_PREFIX.
"facturedet WHERE rowid = ".((int) $this->fk_prev_id);
6758 $resql = $this->db->query($sql);
6759 if ($resql && $this->db->num_rows($resql) > 0) {
6760 $res = $this->db->fetch_array($resql);
6762 $returnPercent = (float) $res[
'situation_percent'];
6764 if ($include_credit_note) {
6765 $sql =
'SELECT fd.situation_percent FROM '.MAIN_DB_PREFIX.
'facturedet fd';
6766 $sql .=
' JOIN '.MAIN_DB_PREFIX.
'facture f ON (f.rowid = fd.fk_facture) ';
6767 $sql .=
" WHERE fd.fk_prev_id = ".((int) $this->fk_prev_id);
6768 $sql .=
" AND f.situation_cycle_ref = ".((int) $invoicecache[$invoiceid]->situation_cycle_ref);
6769 $sql .=
" AND f.type = ".Facture::TYPE_CREDIT_NOTE;
6771 $res = $this->db->query($sql);
6773 while ($obj = $this->db->fetch_object($res)) {
6774 $returnPercent = $returnPercent + (float) $obj->situation_percent;
6781 return $returnPercent;
6783 $this->error = $this->db->error();
6784 dol_syslog(get_class($this).
"::select Error ".$this->error, LOG_ERR);
6785 $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