dolibarr  17.0.4
card-rec.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2002-2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
6  * Copyright (C) 2013-2023 Juanjo Menent <jmenent@2byte.es>
7  * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
8  * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
9  * Copyright (C) 2015 Alexandre Spangaro <aspangaro@open-dsi.fr>
10  * Copyright (C) 2016 Meziane Sof <virtualsof@yahoo.fr>
11  * Copyright (C) 2017-2018 Frédéric France <frederic.france@netlogic.fr>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program. If not, see <https://www.gnu.org/licenses/>.
25  */
26 
33 // Load Dolibarr environment
34 require '../../main.inc.php';
35 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php';
36 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
37 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
38 if (isModEnabled('project')) {
39  include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
40  //include_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
41 }
42 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
43 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
44 require_once DOL_DOCUMENT_ROOT.'/core/lib/invoice.lib.php';
45 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
46 
47 // Load translation files required by the page
48 $langs->loadLangs(array('bills', 'companies', 'compta', 'admin', 'other', 'products', 'banks'));
49 
50 $action = GETPOST('action', 'alpha');
51 $massaction = GETPOST('massaction', 'alpha');
52 $show_files = GETPOST('show_files', 'int');
53 $confirm = GETPOST('confirm', 'alpha');
54 $cancel = GETPOST('cancel', 'alpha');
55 $toselect = GETPOST('toselect', 'array');
56 $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'invoicetemplatelist'; // To manage different context of search
57 
58 // Security check
59 $id = (GETPOST('facid', 'int') ?GETPOST('facid', 'int') : GETPOST('id', 'int'));
60 $lineid = GETPOST('lineid', 'int');
61 $ref = GETPOST('ref', 'alpha');
62 if ($user->socid) {
63  $socid = $user->socid;
64 }
65 $objecttype = 'facture_rec';
66 if ($action == "create" || $action == "add") {
67  $objecttype = '';
68 }
69 $projectid = GETPOST('projectid', 'int');
70 
71 $year_date_when = GETPOST('year_date_when');
72 $month_date_when = GETPOST('month_date_when');
73 
74 $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
75 $sortfield = GETPOST('sortfield', 'aZ09comma');
76 $sortorder = GETPOST('sortorder', 'aZ09comma');
77 $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
78 if (empty($page) || $page == -1) {
79  $page = 0;
80 } // If $page is not defined, or '' or -1
81 $offset = $limit * $page;
82 if (!$sortorder) {
83  $sortorder = 'DESC';
84 }
85 if (!$sortfield) {
86  $sortfield = 'f.titre';
87 }
88 $pageprev = $page - 1;
89 $pagenext = $page + 1;
90 
91 $object = new FactureRec($db);
92 if (($id > 0 || $ref) && $action != 'create' && $action != 'add') {
93  $ret = $object->fetch($id, $ref);
94  if (!$ret) {
95  setEventMessages($langs->trans("ErrorRecordNotFound"), null, 'errors');
96  }
97 }
98 
99 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
100 $hookmanager->initHooks(array('invoicereccard', 'globalcard'));
101 $extrafields = new ExtraFields($db);
102 
103 // fetch optionals attributes and labels
104 $extrafields->fetch_name_optionals_label($object->table_element);
105 
106 $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
107 
108 $permissionnote = $user->rights->facture->creer; // Used by the include of actions_setnotes.inc.php
109 $permissiondellink = $user->rights->facture->creer; // Used by the include of actions_dellink.inc.php
110 $permissiontoedit = $user->rights->facture->creer; // Used by the include of actions_lineupdonw.inc.php
111 
112 $usercanread = $user->rights->facture->lire;
113 $usercancreate = $user->rights->facture->creer;
114 $usercanissuepayment = $user->rights->facture->paiement;
115 $usercandelete = $user->rights->facture->supprimer;
116 $usercanvalidate = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->facture->invoice_advance->validate)));
117 $usercansend = (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->facture->invoice_advance->send);
118 $usercanreopen = (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->facture->invoice_advance->reopen);
119 $usercanunvalidate = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($usercancreate)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->facture->invoice_advance->unvalidate)));
120 
121 $usercanproductignorepricemin = ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS));
122 $usercancreatemargin = $user->hasRight("margins", "creer");
123 $usercanreadallmargin = $user->hasRight("margins", "liretous");
124 $usercancreatewithdrarequest = $user->hasRight("prelevement", "bons", "creer");
125 
126 $now = dol_now();
127 
128 $error = 0;
129 
130 $result = restrictedArea($user, 'facture', $object->id, $objecttype);
131 
132 
133 /*
134  * Actions
135  */
136 
137 if (GETPOST('cancel', 'alpha')) {
138  $action = 'list';
139  $massaction = '';
140 }
141 if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
142  $massaction = '';
143 }
144 
145 $parameters = array();
146 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
147 if ($reshook < 0) {
148  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
149 }
150 
151 if (empty($reshook)) {
152  if (GETPOST('cancel', 'alpha')) {
153  $action = '';
154  }
155 
156  // Selection of new fields
157  include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
158 
159  // Set note
160  include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not include_once
161 
162  include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be include, not include_once
163 
164  include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; // Must be include, not include_once
165 
166  // Mass actions
167  /*$objectclass='MyObject';
168  $objectlabel='MyObject';
169  $permissiontoread = $user->rights->mymodule->read;
170  $permissiontodelete = $user->rights->mymodule->delete;
171  $uploaddir = $conf->mymodule->dir_output;
172  include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';*/
173 
174  // Create predefined invoice
175  if ($action == 'add') {
176  if (!GETPOST('title', 'alphanohtml')) {
177  setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->trans("Title")), null, 'errors');
178  $action = "create";
179  $error++;
180  }
181 
182  $frequency = GETPOST('frequency', 'int');
183  $reyear = GETPOST('reyear', 'int');
184  $remonth = GETPOST('remonth', 'int');
185  $reday = GETPOST('reday', 'int');
186  $rehour = GETPOST('rehour', 'int');
187  $remin = GETPOST('remin', 'int');
188  $nb_gen_max = GETPOST('nb_gen_max', 'int');
189  //if (empty($nb_gen_max)) $nb_gen_max =0;
190 
191  if (GETPOST('frequency', 'int')) {
192  if (empty($reyear) || empty($remonth) || empty($reday)) {
193  setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->trans("Date")), null, 'errors');
194  $action = "create";
195  $error++;
196  }
197  /*if ($nb_gen_max === '') {
198  setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->trans("MaxPeriodNumber")), null, 'errors');
199  $action = "create";
200  $error++;
201  }*/
202  }
203 
204  if (!$error) {
205  $object->titre = GETPOST('title', 'alphanohtml'); // deprecated
206  $object->title = GETPOST('title', 'alphanohtml');
207  $object->note_private = GETPOST('note_private', 'restricthtml');
208  $object->note_public = GETPOST('note_public', 'restricthtml');
209  $object->model_pdf = GETPOST('modelpdf', 'alphanohtml');
210  $object->usenewprice = GETPOST('usenewprice', 'alphanohtml');
211 
212  $object->mode_reglement_id = GETPOST('mode_reglement_id', 'int');
213  $object->cond_reglement_id = GETPOST('cond_reglement_id', 'int');
214 
215  $object->frequency = $frequency;
216  $object->unit_frequency = GETPOST('unit_frequency', 'alpha');
217  $object->nb_gen_max = $nb_gen_max;
218  $object->auto_validate = GETPOST('auto_validate', 'int');
219  $object->generate_pdf = GETPOST('generate_pdf', 'int');
220  $object->fk_project = $projectid;
221 
222  $date_next_execution = dol_mktime($rehour, $remin, 0, $remonth, $reday, $reyear);
223  $object->date_when = $date_next_execution;
224 
225  // Get first contract linked to invoice used to generate template (facid is id of source invoice)
226  if (GETPOST('facid', 'int') > 0) {
227  $srcObject = new Facture($db);
228  $srcObject->fetch(GETPOST('facid', 'int'));
229 
230  $srcObject->fetchObjectLinked();
231 
232  if (!empty($srcObject->linkedObjectsIds['contrat'])) {
233  $contractidid = reset($srcObject->linkedObjectsIds['contrat']);
234 
235  $object->origin = 'contrat';
236  $object->origin_id = $contractidid;
237  $object->linked_objects[$object->origin] = $object->origin_id;
238  }
239  }
240 
241  $db->begin();
242 
243  $oldinvoice = new Facture($db);
244  $oldinvoice->fetch(GETPOST('facid', 'int'));
245 
246  $result = $object->create($user, $oldinvoice->id);
247  if ($result > 0) {
248  $result = $oldinvoice->delete($user, 1);
249  if ($result < 0) {
250  $error++;
251  setEventMessages($oldinvoice->error, $oldinvoice->errors, 'errors');
252  $action = "create";
253  }
254  } else {
255  $error++;
256  setEventMessages($object->error, $object->errors, 'errors');
257  $action = "create";
258  }
259 
260  if (!$error) {
261  $db->commit();
262 
263  header("Location: ".$_SERVER['PHP_SELF'].'?facid='.$object->id);
264  exit;
265  } else {
266  $db->rollback();
267 
268  $action = "create";
269  }
270  }
271  }
272 
273  // Delete
274  if ($action == 'confirm_deleteinvoice' && $confirm == 'yes' && $user->rights->facture->supprimer) {
275  $object->delete($user);
276 
277  header("Location: ".DOL_URL_ROOT.'/compta/facture/invoicetemplate_list.php');
278  exit;
279  }
280 
281 
282  // Update field
283  // Set condition
284  if ($action == 'setconditions' && $user->rights->facture->creer) {
285  $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'));
286  } elseif ($action == 'setmode' && $user->rights->facture->creer) {
287  // Set mode
288  $result = $object->setPaymentMethods(GETPOST('mode_reglement_id', 'int'));
289  } elseif ($action == 'classin' && $user->rights->facture->creer) {
290  // Set project
291  $object->setProject(GETPOST('projectid', 'int'));
292  } elseif ($action == 'setref' && $user->rights->facture->creer) {
293  // Set bank account
294  //var_dump(GETPOST('ref', 'alpha'));exit;
295  $result = $object->setValueFrom('titre', $ref, '', null, 'text', '', $user, 'BILLREC_MODIFY');
296  if ($result > 0) {
297  $object->titre = $ref; // deprecated
298  $object->title = $ref;
299  $object->ref = $object->title;
300  } else {
301  $error++;
302  if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
303  $langs->load("errors");
304  setEventMessages($langs->trans('ErrorRefAlreadyExists', $ref), null, 'errors');
305  } else {
306  setEventMessages($object->error, $object->errors, 'errors');
307  }
308  }
309  } elseif ($action == 'setbankaccount' && $user->rights->facture->creer) {
310  // Set bank account
311  $result = $object->setBankAccount(GETPOST('fk_account', 'int'));
312  } elseif ($action == 'setfrequency' && $user->rights->facture->creer) {
313  // Set frequency and unit frequency
314  $object->setFrequencyAndUnit(GETPOST('frequency', 'int'), GETPOST('unit_frequency', 'alpha'));
315  } elseif ($action == 'setdate_when' && $user->rights->facture->creer) {
316  // Set next date of execution
317  $date = dol_mktime(GETPOST('date_whenhour'), GETPOST('date_whenmin'), 0, GETPOST('date_whenmonth'), GETPOST('date_whenday'), GETPOST('date_whenyear'));
318  if (!empty($date)) {
319  $object->setNextDate($date);
320  }
321  } elseif ($action == 'setnb_gen_max' && $user->rights->facture->creer) {
322  // Set max period
323  $object->setMaxPeriod(GETPOST('nb_gen_max', 'int'));
324  } elseif ($action == 'setauto_validate' && $user->rights->facture->creer) {
325  // Set auto validate
326  $object->setAutoValidate(GETPOST('auto_validate', 'int'));
327  } elseif ($action == 'setgenerate_pdf' && $user->rights->facture->creer) {
328  // Set generate pdf
329  $object->setGeneratepdf(GETPOST('generate_pdf', 'int'));
330  } elseif ($action == 'setmodelpdf' && $user->rights->facture->creer) {
331  // Set model pdf
332  $object->setModelpdf(GETPOST('modelpdf', 'alpha'));
333  } elseif ($action == 'disable' && $user->rights->facture->creer) {
334  // Set status disabled
335  $db->begin();
336 
337  $object->fetch($id);
338 
339  $res = $object->setValueFrom('suspended', 1);
340  if ($res <= 0) {
341  $error++;
342  }
343 
344  if (!$error) {
345  $db->commit();
346  } else {
347  $db->rollback();
348  setEventMessages($object->error, $object->errors, 'errors');
349  }
350  } elseif ($action == 'enable' && $user->rights->facture->creer) {
351  // Set status enabled
352  $db->begin();
353 
354  $object->fetch($id);
355 
356  $res = $object->setValueFrom('suspended', 0);
357  if ($res <= 0) {
358  $error++;
359  }
360 
361  if (!$error) {
362  $db->commit();
363  } else {
364  $db->rollback();
365  setEventMessages($object->error, $object->errors, 'errors');
366  }
367  } elseif ($action == 'setmulticurrencycode' && $usercancreate) {
368  // Multicurrency Code
369  $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha'));
370  } elseif ($action == 'setmulticurrencyrate' && $usercancreate) {
371  // Multicurrency rate
372  $result = $object->setMulticurrencyRate(price2num(GETPOST('multicurrency_tx')), GETPOST('calculation_mode', 'int'));
373  }
374 
375  // Delete line
376  if ($action == 'confirm_deleteline' && $confirm == 'yes' && $user->rights->facture->creer) {
377  $object->fetch($id);
378  $object->fetch_thirdparty();
379 
380  $db->begin();
381 
382  $line = new FactureLigneRec($db);
383 
384  // For triggers
385  $line->id = $lineid;
386 
387  if ($line->delete($user) > 0) {
388  $result = $object->update_price(1);
389 
390  if ($result > 0) {
391  $db->commit();
392  $object->fetch($object->id); // Reload lines
393  } else {
394  $db->rollback();
395  setEventMessages($db->lasterror(), null, 'errors');
396  }
397  } else {
398  $db->rollback();
399  setEventMessages($line->error, $line->errors, 'errors');
400  }
401  } elseif ($action == 'update_extras') {
402  $object->oldcopy = dol_clone($object);
403 
404  // Fill array 'array_options' with data from update form
405  $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml'));
406  if ($ret < 0) {
407  $error++;
408  }
409 
410  if (!$error) {
411  $result = $object->insertExtraFields('BILLREC_MODIFY');
412  if ($result < 0) {
413  setEventMessages($object->error, $object->errors, 'errors');
414  $error++;
415  }
416  }
417  }
418 
419  // Add a new line
420  if ($action == 'addline' && $user->rights->facture->creer) {
421  $langs->load('errors');
422  $error = 0;
423 
424  // Set if we used free entry or predefined product
425  $predef = '';
426  $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
427  $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
428  $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU', 2);
429  $prod_entry_mode = GETPOST('prod_entry_mode', 'alpha');
430  if ($prod_entry_mode == 'free') {
431  $idprod = 0;
432  $tva_tx = (GETPOST('tva_tx', 'alpha') ? GETPOST('tva_tx', 'alpha') : 0);
433  } else {
434  $idprod = GETPOST('idprod', 'int');
435  $tva_tx = '';
436  }
437 
438  $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS', 2);
439  $remise_percent = price2num(GETPOST('remise_percent'.$predef), '', 2);
440  if (empty($remise_percent)) {
441  $remise_percent = 0;
442  }
443 
444  // Extrafields
445  $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
446  $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
447  // Unset extrafield
448  if (is_array($extralabelsline)) {
449  // Get extra fields
450  foreach ($extralabelsline as $key => $value) {
451  unset($_POST["options_".$key.$predef]);
452  }
453  }
454 
455  if ((empty($idprod) || $idprod < 0) && ($price_ht < 0) && ($qty < 0)) {
456  setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), null, 'errors');
457  $error++;
458  }
459  if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && GETPOST('type') < 0) {
460  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
461  $error++;
462  }
463  if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && (!($price_ht >= 0) || $price_ht == '')) { // Unit price can be 0 but not ''
464  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
465  $error++;
466  }
467  if ($qty == '') {
468  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
469  $error++;
470  }
471  if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && empty($product_desc)) {
472  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
473  $error++;
474  }
475  if ($qty < 0) {
476  $langs->load("errors");
477  setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
478  $error++;
479  }
480 
481  if (!$error && ($qty >= 0) && (!empty($product_desc) || (!empty($idprod) && $idprod > 0))) {
482  $ret = $object->fetch($id);
483  if ($ret < 0) {
484  dol_print_error($db, $object->error);
485  exit();
486  }
487  $ret = $object->fetch_thirdparty();
488 
489  // Clean parameters
490  $date_start = dol_mktime(GETPOST('date_start'.$predef.'hour'), GETPOST('date_start'.$predef.'min'), GETPOST('date_start'.$predef.'sec'), GETPOST('date_start'.$predef.'month'), GETPOST('date_start'.$predef.'day'), GETPOST('date_start'.$predef.'year'));
491  $date_end = dol_mktime(GETPOST('date_end'.$predef.'hour'), GETPOST('date_end'.$predef.'min'), GETPOST('date_end'.$predef.'sec'), GETPOST('date_end'.$predef.'month'), GETPOST('date_end'.$predef.'day'), GETPOST('date_end'.$predef.'year'));
492  $price_base_type = (GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT');
493 
494  // Define special_code for special lines
495  $special_code = 0;
496  // if (!GETPOST('qty')) $special_code=3; // Options should not exists on invoices
497 
498  // Ecrase $pu par celui du produit
499  // Ecrase $desc par celui du produit
500  // Ecrase $tva_tx par celui du produit
501  // Ecrase $base_price_type par celui du produit
502  // Replaces $fk_unit with the product's
503  if (!empty($idprod) && $idprod > 0) {
504  $prod = new Product($db);
505  $prod->fetch($idprod);
506 
507  $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
508 
509  // Update if prices fields are defined
510  $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
511  $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
512  if (empty($tva_tx)) {
513  $tva_npr = 0;
514  }
515 
516  // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
517  $pqp = (GETPOST('pbq', 'int') ? GETPOST('pbq', 'int') : 0);
518 
519  $datapriceofproduct = $prod->getSellPrice($mysoc, $object->thirdparty, $pqp);
520 
521  $pu_ht = $datapriceofproduct['pu_ht'];
522  $pu_ttc = $datapriceofproduct['pu_ttc'];
523  $price_min = $datapriceofproduct['price_min'];
524  $price_base_type = empty($datapriceofproduct['price_base_type']) ? 'HT' : $datapriceofproduct['price_base_type'];
525  $tva_tx = $datapriceofproduct['tva_tx'];
526  $tva_npr = $datapriceofproduct['tva_npr'];
527 
528  $tmpvat = price2num(preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx));
529  $tmpprodvat = price2num(preg_replace('/\s*\‍(.*\‍)/', '', $prod->tva_tx));
530 
531  // if price ht was forced (ie: from gui when calculated by margin rate and cost price). TODO Why this ?
532  if (!empty($price_ht)) {
533  $pu_ht = price2num($price_ht, 'MU');
534  $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
535  } elseif ($tmpvat != $tmpprodvat) {
536  // On reevalue prix selon taux tva car taux tva transaction peut etre different
537  // de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
538  if ($price_base_type != 'HT') {
539  $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
540  } else {
541  $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
542  }
543  }
544 
545  $desc = '';
546 
547  // Define output language
548  if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
549  $outputlangs = $langs;
550  $newlang = '';
551  if (empty($newlang) && GETPOST('lang_id', 'aZ09')) {
552  $newlang = GETPOST('lang_id', 'aZ09');
553  }
554  if (empty($newlang)) {
555  $newlang = $object->thirdparty->default_lang;
556  }
557  if (!empty($newlang)) {
558  $outputlangs = new Translate("", $conf);
559  $outputlangs->setDefaultLang($newlang);
560  }
561 
562  $desc = (!empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
563  } else {
564  $desc = $prod->description;
565  }
566 
567  $desc = dol_concatdesc($desc, $product_desc);
568 
569  // Add custom code and origin country into description
570  if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (!empty($prod->customcode) || !empty($prod->country_code))) {
571  $tmptxt = '(';
572  // Define output language
573  if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
574  $outputlangs = $langs;
575  $newlang = '';
576  if (empty($newlang) && GETPOST('lang_id', 'alpha')) {
577  $newlang = GETPOST('lang_id', 'alpha');
578  }
579  if (empty($newlang)) {
580  $newlang = $object->thirdparty->default_lang;
581  }
582  if (!empty($newlang)) {
583  $outputlangs = new Translate("", $conf);
584  $outputlangs->setDefaultLang($newlang);
585  $outputlangs->load('products');
586  }
587  if (!empty($prod->customcode)) {
588  $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomCode").': '.$prod->customcode;
589  }
590  if (!empty($prod->customcode) && !empty($prod->country_code)) {
591  $tmptxt .= ' - ';
592  }
593  if (!empty($prod->country_code)) {
594  $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, 0, $db, $outputlangs, 0);
595  }
596  } else {
597  if (!empty($prod->customcode)) {
598  $tmptxt .= $langs->transnoentitiesnoconv("CustomCode").': '.$prod->customcode;
599  }
600  if (!empty($prod->customcode) && !empty($prod->country_code)) {
601  $tmptxt .= ' - ';
602  }
603  if (!empty($prod->country_code)) {
604  $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, 0, $db, $langs, 0);
605  }
606  }
607  $tmptxt .= ')';
608  $desc = dol_concatdesc($desc, $tmptxt);
609  }
610 
611  $type = $prod->type;
612  $fk_unit = $prod->fk_unit;
613  } else {
614  $pu_ht = price2num($price_ht, 'MU');
615  $pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
616  $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
617  $tva_tx = str_replace('*', '', $tva_tx);
618  if (empty($tva_tx)) {
619  $tva_npr = 0;
620  }
621  $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
622  $desc = $product_desc;
623  $type = GETPOST('type');
624  $fk_unit = GETPOST('units', 'alpha');
625  }
626 
627  $date_start_fill = GETPOST('date_start_fill', 'int');
628  $date_end_fill = GETPOST('date_end_fill', 'int');
629 
630  // Margin
631  $fournprice = price2num(GETPOST('fournprice'.$predef) ? GETPOST('fournprice'.$predef) : '');
632  $buyingprice = price2num(GETPOST('buying_price'.$predef) != '' ? GETPOST('buying_price'.$predef) : ''); // If buying_price is '0', we must keep this value
633 
634  // Local Taxes
635  $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $mysoc, $tva_npr);
636  $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $mysoc, $tva_npr);
637 
638  $info_bits = 0;
639  if ($tva_npr) {
640  $info_bits |= 0x01;
641  }
642 
643  if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($pu_ht) * (1 - price2num($remise_percent) / 100) < price2num($price_min)))) {
644  $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency));
645  setEventMessages($mesg, null, 'errors');
646  } else {
647  // Insert line
648  $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $price_base_type, $info_bits, '', $pu_ttc, $type, -1, $special_code, $label, $fk_unit, 0, $date_start_fill, $date_end_fill, $fournprice, $buyingprice);
649 
650  if ($result > 0) {
651  // Define output language and generate document
652  /*if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
653  {
654  // Define output language
655  $outputlangs = $langs;
656  $newlang = '';
657  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
658  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) $newlang = $object->thirdparty->default_lang;
659  if (!empty($newlang)) {
660  $outputlangs = new Translate("", $conf);
661  $outputlangs->setDefaultLang($newlang);
662  }
663  $model=$object->model_pdf;
664  $ret = $object->fetch($id); // Reload to get new records
665 
666  $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
667  if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
668  }*/
669  $object->fetch($object->id); // Reload lines
670 
671  unset($_POST['prod_entry_mode']);
672 
673  unset($_POST['qty']);
674  unset($_POST['type']);
675  unset($_POST['remise_percent']);
676  unset($_POST['price_ht']);
677  unset($_POST['multicurrency_price_ht']);
678  unset($_POST['price_ttc']);
679  unset($_POST['tva_tx']);
680  unset($_POST['product_ref']);
681  unset($_POST['product_label']);
682  unset($_POST['product_desc']);
683  unset($_POST['fournprice']);
684  unset($_POST['buying_price']);
685  unset($_POST['np_marginRate']);
686  unset($_POST['np_markRate']);
687  unset($_POST['dp_desc']);
688  unset($_POST['idprod']);
689  unset($_POST['units']);
690 
691  unset($_POST['date_starthour']);
692  unset($_POST['date_startmin']);
693  unset($_POST['date_startsec']);
694  unset($_POST['date_startday']);
695  unset($_POST['date_startmonth']);
696  unset($_POST['date_startyear']);
697  unset($_POST['date_endhour']);
698  unset($_POST['date_endmin']);
699  unset($_POST['date_endsec']);
700  unset($_POST['date_endday']);
701  unset($_POST['date_endmonth']);
702  unset($_POST['date_endyear']);
703 
704  unset($_POST['date_start_fill']);
705  unset($_POST['date_end_fill']);
706 
707  unset($_POST['situations']);
708  unset($_POST['progress']);
709  } else {
710  setEventMessages($object->error, $object->errors, 'errors');
711  }
712 
713  $action = '';
714  }
715  }
716  } elseif ($action == 'updateline' && $usercancreate && !GETPOST('cancel', 'alpha')) {
717  if (!$object->fetch($id) > 0) {
718  dol_print_error($db);
719  }
720  $object->fetch_thirdparty();
721 
722  // Clean parameters
723  $date_start = '';
724  $date_end = '';
725  //$date_start = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear'));
726  //$date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear'));
727  $description = dol_htmlcleanlastbr(GETPOST('product_desc', 'restricthtml') ? GETPOST('product_desc', 'restricthtml') : GETPOST('desc', 'restricthtml'));
728  $pu_ht = price2num(GETPOST('price_ht'), '', 2);
729  $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
730  $qty = GETPOST('qty');
731  $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), '', 2);
732 
733  // Define info_bits
734  $info_bits = 0;
735  if (preg_match('/\*/', $vat_rate)) {
736  $info_bits |= 0x01;
737  }
738 
739  // Define vat_rate
740  $vat_rate = str_replace('*', '', $vat_rate);
741  $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty);
742  $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty);
743 
744  // Add buying price
745  $fournprice = price2num(GETPOST('fournprice') ? GETPOST('fournprice') : '');
746  $buyingprice = price2num(GETPOST('buying_price') != '' ? GETPOST('buying_price') : ''); // If buying_price is '0', we muste keep this value
747 
748  // Extrafields
749  $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
750  $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
751 
752  $objectline = new FactureLigneRec($db);
753  if ($objectline->fetch(GETPOST('lineid', 'int'))) {
754  $objectline->array_options = $array_options;
755  $result = $objectline->insertExtraFields();
756  if ($result < 0) {
757  setEventMessages($langs->trans('Error').$result, null, 'errors');
758  }
759  }
760 
761  $position = ($objectline->rang >= 0 ? $objectline->rang : 0);
762 
763  // Unset extrafield
764  if (is_array($extralabelsline)) {
765  // Get extra fields
766  foreach ($extralabelsline as $key => $value) {
767  unset($_POST["options_".$key]);
768  }
769  }
770 
771  // Define special_code for special lines
772  $special_code = GETPOST('special_code', 'int');
773  if ($special_code == 3) {
774  $special_code = 0; // Options should not exists on invoices
775  }
776 
777  /*$line = new FactureLigne($db);
778  $line->fetch(GETPOST('lineid', 'int'));
779  $percent = $line->get_prev_progress($object->id);
780 
781  if (GETPOST('progress') < $percent)
782  {
783  $mesg = '<div class="warning">' . $langs->trans("CantBeLessThanMinPercent") . '</div>';
784  setEventMessages($mesg, null, 'warnings');
785  $error++;
786  $result = -1;
787  }*/
788 
789  $remise_percent = price2num(GETPOST('remise_percent'), '', 2);
790  if (empty($remise_percent)) {
791  $remise_percent = 0;
792  }
793 
794  // Check minimum price
795  $productid = GETPOST('productid', 'int');
796  if (!empty($productid)) {
797  $product = new Product($db);
798  $product->fetch($productid);
799 
800  $type = $product->type;
801 
802  $price_min = $product->price_min;
803  if (!empty($conf->global->PRODUIT_MULTIPRICES) && !empty($object->thirdparty->price_level)) {
804  $price_min = $product->multiprices_min[$object->thirdparty->price_level];
805  }
806 
807  $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : '');
808 
809  $typeinvoice = Facture::TYPE_STANDARD;
810 
811  // Check price is not lower than minimum (check is done only for standard or replacement invoices)
812  if (((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)) && (($typeinvoice == Facture::TYPE_STANDARD || $typeinvoice == Facture::TYPE_REPLACEMENT) && $price_min && ((float) price2num($pu_ht) * (1 - (float) $remise_percent / 100) < (float) price2num($price_min)))) {
813  setEventMessages($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)), null, 'errors');
814  $error++;
815  }
816  } else {
817  $type = GETPOST('type', 'int');
818  $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
819 
820  // Check parameters
821  if (GETPOST('type', 'int') < 0) {
822  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
823  $error++;
824  }
825  }
826  if ($qty < 0) {
827  $langs->load("errors");
828  setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
829  $error++;
830  }
831 
832  $date_start_fill = GETPOST('date_start_fill', 'int');
833  $date_end_fill = GETPOST('date_end_fill', 'int');
834 
835  // Update line
836  if (!$error) {
837  $result = $object->updateline(
838  GETPOST('lineid', 'int'),
839  $description,
840  $pu_ht,
841  $qty,
842  $vat_rate,
843  $localtax1_rate,
844  $localtax1_rate,
845  GETPOST('productid', 'int'),
846  $remise_percent,
847  'HT',
848  $info_bits,
849  0,
850  0,
851  $type,
852  $position,
853  $special_code,
854  $label,
855  GETPOST('units'),
856  $pu_ht_devise,
857  0,
858  $date_start_fill,
859  $date_end_fill,
860  $fournprice,
861  $buyingprice
862  );
863 
864  if ($result >= 0) {
865  /*if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
866  // Define output language
867  $outputlangs = $langs;
868  $newlang = '';
869  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id','aZ09'))
870  $newlang = GETPOST('lang_id','aZ09');
871  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang))
872  $newlang = $object->thirdparty->default_lang;
873  if (!empty($newlang)) {
874  $outputlangs = new Translate("", $conf);
875  $outputlangs->setDefaultLang($newlang);
876  }
877 
878  $ret = $object->fetch($id); // Reload to get new records
879  $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
880  }*/
881 
882  $object->fetch($object->id); // Reload lines
883 
884  unset($_POST['qty']);
885  unset($_POST['type']);
886  unset($_POST['productid']);
887  unset($_POST['remise_percent']);
888  unset($_POST['price_ht']);
889  unset($_POST['multicurrency_price_ht']);
890  unset($_POST['price_ttc']);
891  unset($_POST['tva_tx']);
892  unset($_POST['product_ref']);
893  unset($_POST['product_label']);
894  unset($_POST['product_desc']);
895  unset($_POST['fournprice']);
896  unset($_POST['buying_price']);
897  unset($_POST['np_marginRate']);
898  unset($_POST['np_markRate']);
899 
900  unset($_POST['dp_desc']);
901  unset($_POST['idprod']);
902  unset($_POST['units']);
903 
904  unset($_POST['date_starthour']);
905  unset($_POST['date_startmin']);
906  unset($_POST['date_startsec']);
907  unset($_POST['date_startday']);
908  unset($_POST['date_startmonth']);
909  unset($_POST['date_startyear']);
910  unset($_POST['date_endhour']);
911  unset($_POST['date_endmin']);
912  unset($_POST['date_endsec']);
913  unset($_POST['date_endday']);
914  unset($_POST['date_endmonth']);
915  unset($_POST['date_endyear']);
916 
917  unset($_POST['situations']);
918  unset($_POST['progress']);
919  } else {
920  setEventMessages($object->error, $object->errors, 'errors');
921  }
922  }
923  }
924 }
925 
926 
927 /*
928  * View
929  */
930 
931 $help_url = '';
932 llxHeader('', $langs->trans("RepeatableInvoices"), $help_url);
933 
934 $form = new Form($db);
935 $formother = new FormOther($db);
936 if (isModEnabled('project')) {
937  $formproject = new FormProjets($db);
938 }
939 $companystatic = new Societe($db);
940 $invoicerectmp = new FactureRec($db);
941 
942 $now = dol_now();
943 $nowlasthour = dol_get_last_hour($now);
944 
945 
946 /*
947  * Create mode
948  */
949 if ($action == 'create') {
950  print load_fiche_titre($langs->trans("CreateRepeatableInvoice"), '', 'bill');
951 
952  $object = new Facture($db); // Source invoice
953  $product_static = new Product($db);
954 
955  if ($object->fetch($id, $ref) > 0) {
956  $result = $object->getLinesArray();
957 
958  print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
959  print '<input type="hidden" name="token" value="'.newToken().'">';
960  print '<input type="hidden" name="action" value="add">';
961  print '<input type="hidden" name="facid" value="'.$object->id.'">';
962 
963  print dol_get_fiche_head(null, '', '', 0);
964 
965  $rowspan = 4;
966  if (isModEnabled('project')) {
967  $rowspan++;
968  }
969  if ($object->fk_account > 0) {
970  $rowspan++;
971  }
972 
973  print '<table class="border centpercent">';
974 
975  $object->fetch_thirdparty();
976 
977  // Title
978  print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Title").'</td><td>';
979  print '<input class="flat quatrevingtpercent" type="text" name="title" value="'.dol_escape_htmltag(GETPOST("title", 'alphanohtml')).'" autofocus>';
980  print '</td></tr>';
981 
982  // Third party
983  print '<tr><td class="titlefieldcreate">'.$langs->trans("Customer").'</td><td>'.$object->thirdparty->getNomUrl(1, 'customer').'</td>';
984  print '</tr>';
985 
986  $note_public = GETPOSTISSET('note_public') ? GETPOST('note_public', 'restricthtml') : $object->note_public;
987  $note_private = GETPOSTISSET('note_private') ? GETPOST('note_private', 'restricthtml') : $object->note_private;
988 
989  // Help of substitution key
990  $substitutionarray = getCommonSubstitutionArray($langs, 2, null, $object);
991 
992  $substitutionarray['__INVOICE_PREVIOUS_MONTH__'] = $langs->trans("PreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, -1, 'm'), '%m').')';
993  $substitutionarray['__INVOICE_MONTH__'] = $langs->trans("MonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($object->date, '%m').')';
994  $substitutionarray['__INVOICE_NEXT_MONTH__'] = $langs->trans("NextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, 1, 'm'), '%m').')';
995  $substitutionarray['__INVOICE_PREVIOUS_MONTH_TEXT__'] = $langs->trans("TextPreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, -1, 'm'), '%B').')';
996  $substitutionarray['__INVOICE_MONTH_TEXT__'] = $langs->trans("TextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($object->date, '%B').')';
997  $substitutionarray['__INVOICE_NEXT_MONTH_TEXT__'] = $langs->trans("TextNextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, 1, 'm'), '%B').')';
998  $substitutionarray['__INVOICE_PREVIOUS_YEAR__'] = $langs->trans("PreviousYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, -1, 'y'), '%Y').')';
999  $substitutionarray['__INVOICE_YEAR__'] = $langs->trans("YearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($object->date, '%Y').')';
1000  $substitutionarray['__INVOICE_NEXT_YEAR__'] = $langs->trans("NextYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, 1, 'y'), '%Y').')';
1001  // Only on template invoices
1002  $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_BEFORE_GEN__'] = $langs->trans("DateNextInvoiceBeforeGen").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, 1, 'm'), 'dayhour').')';
1003  $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_AFTER_GEN__'] = $langs->trans("DateNextInvoiceAfterGen").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, 2, 'm'), 'dayhour').')';
1004  $substitutionarray['__INVOICE_COUNTER_CURRENT__'] = $langs->trans("Count");
1005  $substitutionarray['__INVOICE_COUNTER_MAX__'] = $langs->trans("MaxPeriodNumber");
1006 
1007  $htmltext = '<i>'.$langs->trans("FollowingConstantsWillBeSubstituted").':<br>';
1008  foreach ($substitutionarray as $key => $val) {
1009  $htmltext .= $key.' = '.$langs->trans($val).'<br>';
1010  }
1011  $htmltext .= '</i>';
1012 
1013  // Public note
1014  print '<tr>';
1015  print '<td class="tdtop">';
1016  print $form->textwithpicto($langs->trans('NotePublic'), $htmltext, 1, 'help', '', 0, 2, 'notepublic');
1017  print '</td>';
1018  print '<td>';
1019  $doleditor = new DolEditor('note_public', $note_public, '', 80, 'dolibarr_notes', 'In', 0, false, empty($conf->global->FCKEDITOR_ENABLE_NOTE_PUBLIC) ? 0 : 1, ROWS_3, '90%');
1020  print $doleditor->Create(1);
1021 
1022  // Private note
1023  if (empty($user->socid)) {
1024  print '<tr>';
1025  print '<td class="tdtop">';
1026  print $form->textwithpicto($langs->trans('NotePrivate'), $htmltext, 1, 'help', '', 0, 2, 'noteprivate');
1027  print '</td>';
1028  print '<td>';
1029  $doleditor = new DolEditor('note_private', $note_private, '', 80, 'dolibarr_notes', 'In', 0, false, empty($conf->global->FCKEDITOR_ENABLE_NOTE_PRIVATE) ? 0 : 1, ROWS_3, '90%');
1030  print $doleditor->Create(1);
1031  // print '<textarea name="note_private" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'.</textarea>
1032  print '</td></tr>';
1033  }
1034 
1035  // Author
1036  print "<tr><td>".$langs->trans("Author")."</td><td>".$user->getFullName($langs)."</td></tr>";
1037 
1038  // Payment term
1039  print "<tr><td>".$langs->trans("PaymentConditions")."</td><td>";
1040  print $form->getSelectConditionsPaiements(GETPOSTISSET('cond_reglement_id') ? GETPOST('cond_reglement_id', 'int') : $object->cond_reglement_id, 'cond_reglement_id', -1, 0, 0, '');
1041  //$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id');
1042  print "</td></tr>";
1043 
1044  // Payment mode
1045  print "<tr><td>".$langs->trans("PaymentMode")."</td><td>";
1046  print img_picto('', 'payment', 'class="pictofixedwidth"');
1047  print $form->select_types_paiements(GETPOSTISSET('mode_reglement_id') ? GETPOST('mode_reglement_id', 'int') : $object->mode_reglement_id, 'mode_reglement_id', '', 0, 1, 0, 0, 1, '', 1);
1048  //$form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', '', 1);
1049  print "</td></tr>";
1050 
1051  // Bank account
1052  if ($object->fk_account > 0) {
1053  print "<tr><td>".$langs->trans('BankAccount')."</td><td>";
1054  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
1055  print "</td></tr>";
1056  }
1057 
1058  // Project
1059  if (isModEnabled('project') && is_object($object->thirdparty) && $object->thirdparty->id > 0) {
1060  $projectid = GETPOST('projectid') ?GETPOST('projectid') : $object->fk_project;
1061  $langs->load('projects');
1062  print '<tr><td>'.$langs->trans('Project').'</td><td>';
1063  print img_picto('', 'project', 'class="pictofixedwidth"');
1064  $numprojet = $formproject->select_projects($object->thirdparty->id, $projectid, 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 0, 0, '');
1065  print ' &nbsp; <a href="'.DOL_URL_ROOT.'/projet/card.php?socid='.$object->thirdparty->id.'&action=create&status=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create&socid='.$object->thirdparty->id.(!empty($id) ? '&id='.$id : '')).'">'.img_object($langs->trans("AddProject"), 'add').'</a>';
1066  print '</td></tr>';
1067  }
1068 
1069  // Model pdf
1070  print "<tr><td>".$langs->trans('Model')."</td><td>";
1071  include_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php';
1072  $list = ModelePDFFactures::liste_modeles($db);
1073  print img_picto('', 'generic', 'class="pictofixedwidth"');
1074  print $form->selectarray('modelpdf', $list, $conf->global->FACTURE_ADDON_PDF);
1075  print "</td></tr>";
1076 
1077  print "</table>";
1078 
1079  print dol_get_fiche_end();
1080 
1081 
1082  // Autogeneration
1083  $title = $langs->trans("Recurrence");
1084  print load_fiche_titre(img_picto('', 'recurring', 'class="pictofixedwidth"').$title, '', '');
1085 
1086  print dol_get_fiche_head(null, '', '', 0);
1087 
1088  print '<table class="border centpercent">';
1089 
1090  // Frequency + unit
1091  print '<tr><td class="titlefieldcreate">'.$form->textwithpicto($langs->trans("Frequency"), $langs->transnoentitiesnoconv('toolTipFrequency'))."</td><td>";
1092  print "<input type='text' name='frequency' value='".GETPOST('frequency', 'int')."' size='4' />&nbsp;";
1093  print $form->selectarray('unit_frequency', array('d'=>$langs->trans('Day'), 'm'=>$langs->trans('Month'), 'y'=>$langs->trans('Year')), (GETPOST('unit_frequency') ?GETPOST('unit_frequency') : 'm'));
1094  print "</td></tr>";
1095 
1096  // Date next run
1097  print "<tr><td>".$langs->trans('NextDateToExecution')."</td><td>";
1098  $date_next_execution = isset($date_next_execution) ? $date_next_execution : (GETPOST('remonth') ? dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')) : -1);
1099  print $form->selectDate($date_next_execution, '', 1, 1, '', "add", 1, 1);
1100  print "</td></tr>";
1101 
1102  // Number max of generation
1103  print "<tr><td>".$langs->trans("MaxPeriodNumber")."</td><td>";
1104  print '<input type="text" name="nb_gen_max" value="'.GETPOST('nb_gen_max').'" size="5" />';
1105  print "</td></tr>";
1106 
1107  // Auto validate the invoice
1108  print "<tr><td>".$langs->trans("StatusOfGeneratedInvoices")."</td><td>";
1109  $select = array('0'=>$langs->trans('BillStatusDraft'), '1'=>$langs->trans('BillStatusValidated'));
1110  print $form->selectarray('auto_validate', $select, GETPOST('auto_validate'));
1111  print "</td></tr>";
1112 
1113  // Auto generate document
1114  if (!empty($conf->global->INVOICE_REC_CAN_DISABLE_DOCUMENT_FILE_GENERATION)) {
1115  print "<tr><td>".$langs->trans("StatusOfGeneratedDocuments")."</td><td>";
1116  $select = array('0'=>$langs->trans('DoNotGenerateDoc'), '1'=>$langs->trans('AutoGenerateDoc'));
1117  print $form->selectarray('generate_pdf', $select, GETPOST('generate_pdf'));
1118  print "</td></tr>";
1119  } else {
1120  print '<input type="hidden" name="generate_pdf" value="1">';
1121  }
1122 
1123  print "</table>";
1124 
1125  print dol_get_fiche_end();
1126 
1127 
1128  $title = $langs->trans("ProductsAndServices");
1129  if (!isModEnabled('service')) {
1130  $title = $langs->trans("Products");
1131  } elseif (!isModEnabled('product')) {
1132  $title = $langs->trans("Services");
1133  }
1134 
1135  print load_fiche_titre($title, '', '');
1136 
1137  /*
1138  * Invoice lines
1139  */
1140  print '<div class="div-table-responsive-no-min">';
1141  print '<table id="tablelines" class="noborder noshadow" width="100%">';
1142  // Show object lines
1143  if (!empty($object->lines)) {
1144  $disableedit = 1;
1145  $disablemove = 1;
1146  $disableremove = 1;
1147  $object->printObjectLines('', $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice
1148  }
1149 
1150  print "</table>\n";
1151  print '<div>';
1152 
1153  print '</td></tr>';
1154 
1155  if ($flag_price_may_change) {
1156  print '<tr><td colspan="3" class="left">';
1157  print '<select name="usenewprice" class="flat">';
1158  print '<option value="0">'.$langs->trans("AlwaysUseFixedPrice").'</option>';
1159  print '<option value="1" disabled>'.$langs->trans("AlwaysUseNewPrice").'</option>';
1160  print '</select>';
1161  print '</td></tr>';
1162  }
1163  print "</table>\n";
1164 
1165  print $form->buttonsSaveCancel("Create");
1166 
1167  print "</form>\n";
1168  } else {
1169  dol_print_error('', "Error, no invoice ".$object->id);
1170  }
1171 } else {
1172  /*
1173  * View mode
1174  */
1175  if ($object->id > 0) {
1176  $object->fetch_thirdparty();
1177 
1178  // Confirmation de la suppression d'une ligne produit
1179  if ($action == 'ask_deleteline') {
1180  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 'no', 1);
1181  }
1182 
1183  // Confirm delete of repeatable invoice
1184  if ($action == 'delete') {
1185  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteRepeatableInvoice'), $langs->trans('ConfirmDeleteRepeatableInvoice'), 'confirm_deleteinvoice', '', 'no', 1);
1186  }
1187 
1188  // Call Hook formConfirm
1189  $parameters = array('formConfirm' => $formconfirm);
1190  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1191  if (empty($reshook)) {
1192  $formconfirm .= $hookmanager->resPrint;
1193  } elseif ($reshook > 0) {
1194  $formconfirm = $hookmanager->resPrint;
1195  }
1196 
1197  print $formconfirm;
1198 
1199  $author = new User($db);
1200  $author->fetch($object->user_author);
1201 
1202  $head = invoice_rec_prepare_head($object);
1203 
1204  print dol_get_fiche_head($head, 'card', $langs->trans("RepeatableInvoice"), -1, 'bill'); // Add a div
1205 
1206  // Recurring invoice content
1207 
1208  $linkback = '<a href="'.DOL_URL_ROOT.'/compta/facture/invoicetemplate_list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
1209 
1210  $morehtmlref = '';
1211  if ($action != 'editref') {
1212  $morehtmlref .= $form->editfieldkey($object->ref, 'ref', $object->ref, $object, $user->rights->facture->creer, '', '', 0, 2);
1213  } else {
1214  $morehtmlref .= $form->editfieldval('', 'ref', $object->ref, $object, $user->rights->facture->creer, 'string');
1215  }
1216 
1217  $morehtmlref .= '<div class="refidno">';
1218  // Ref customer
1219  //$morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->facture->creer, 'string', '', 0, 1);
1220  //$morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->facture->creer, 'string', '', null, null, '', 1);
1221  // Thirdparty
1222  $morehtmlref .= $langs->trans('ThirdParty').' : '.$object->thirdparty->getNomUrl(1);
1223  // Project
1224  if (isModEnabled('project')) {
1225  $langs->load("projects");
1226  $morehtmlref .= '<br>'.$langs->trans('Project').' ';
1227  if ($user->rights->facture->creer) {
1228  if ($action != 'classify') {
1229  $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> : ';
1230  }
1231  if ($action == 'classify') {
1232  //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
1233  $morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
1234  $morehtmlref .= '<input type="hidden" name="action" value="classin">';
1235  $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
1236  $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
1237  $morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
1238  $morehtmlref .= '</form>';
1239  } else {
1240  $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1, '', 'maxwidth300');
1241  }
1242  } else {
1243  if (!empty($object->fk_project)) {
1244  $proj = new Project($db);
1245  $proj->fetch($object->fk_project);
1246  $morehtmlref .= ' : '.$proj->getNomUrl(1);
1247  if ($proj->title) {
1248  $morehtmlref .= ' - '.$proj->title;
1249  }
1250  } else {
1251  $morehtmlref .= '';
1252  }
1253  }
1254  }
1255  $morehtmlref .= '</div>';
1256 
1257  $morehtmlright = '';
1258 
1259  dol_banner_tab($object, 'ref', $linkback, 1, 'title', 'none', $morehtmlref, '', 0, '', $morehtmlright);
1260 
1261  print '<div class="fichecenter">';
1262  print '<div class="fichehalfleft">';
1263  print '<div class="underbanner clearboth"></div>';
1264 
1265  print '<table class="border centpercent tableforfield">';
1266 
1267  print '<tr><td class="titlefield">'.$langs->trans("Author").'</td><td>';
1268  print $author->getNomUrl(-1);
1269  print "</td></tr>";
1270 
1271  print '<tr><td>'.$langs->trans("AmountHT").'</td>';
1272  print '<td>'.price($object->total_ht, '', $langs, 1, -1, -1, $conf->currency).'</td>';
1273  print '</tr>';
1274 
1275  print '<tr><td>'.$langs->trans("AmountVAT").'</td><td>'.price($object->total_tva, '', $langs, 1, -1, -1, $conf->currency).'</td>';
1276  print '</tr>';
1277 
1278  // Amount Local Taxes
1279  if (($mysoc->localtax1_assuj == "1" && $mysoc->useLocalTax(1)) || $object->total_localtax1 != 0) { // Localtax1
1280  print '<tr><td>'.$langs->transcountry("AmountLT1", $mysoc->country_code).'</td>';
1281  print '<td class="nowrap">'.price($object->total_localtax1, 1, '', 1, - 1, - 1, $conf->currency).'</td></tr>';
1282  }
1283  if (($mysoc->localtax2_assuj == "1" && $mysoc->useLocalTax(2)) || $object->total_localtax2 != 0) { // Localtax2
1284  print '<tr><td>'.$langs->transcountry("AmountLT2", $mysoc->country_code).'</td>';
1285  print '<td class=nowrap">'.price($object->total_localtax2, 1, '', 1, - 1, - 1, $conf->currency).'</td></tr>';
1286  }
1287 
1288  print '<tr><td>'.$langs->trans("AmountTTC").'</td><td colspan="3">'.price($object->total_ttc, '', $langs, 1, -1, -1, $conf->currency).'</td>';
1289  print '</tr>';
1290 
1291 
1292  // Payment term
1293  print '<tr><td>';
1294  print '<table class="nobordernopadding centpercent"><tr><td>';
1295  print $langs->trans('PaymentConditionsShort');
1296  print '</td>';
1297  if ($action != 'editconditions' && $user->rights->facture->creer) {
1298  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editconditions&token='.newToken().'&facid='.$object->id.'">'.img_edit($langs->trans('SetConditions'), 1).'</a></td>';
1299  }
1300  print '</tr></table>';
1301  print '</td><td>';
1302  if ($object->type != Facture::TYPE_CREDIT_NOTE) {
1303  if ($action == 'editconditions') {
1304  $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->cond_reglement_id, 'cond_reglement_id');
1305  } else {
1306  $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->cond_reglement_id, 'none');
1307  }
1308  } else {
1309  print '&nbsp;';
1310  }
1311  print '</td></tr>';
1312 
1313  // Payment mode
1314  print '<tr><td>';
1315  print '<table class="nobordernopadding" width="100%"><tr><td>';
1316  print $langs->trans('PaymentMode');
1317  print '</td>';
1318  if ($action != 'editmode' && $user->rights->facture->creer) {
1319  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editmode&token='.newToken().'&facid='.$object->id.'">'.img_edit($langs->trans('SetMode'), 1).'</a></td>';
1320  }
1321  print '</tr></table>';
1322  print '</td><td>';
1323  if ($action == 'editmode') {
1324  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
1325  } else {
1326  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'none');
1327  }
1328  print '</td></tr>';
1329 
1330  // Multicurrency
1331  if (isModEnabled('multicurrency')) {
1332  // Multicurrency code
1333  print '<tr>';
1334  print '<td>';
1335  print '<table class="nobordernopadding" width="100%"><tr><td>';
1336  print $form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0);
1337  print '</td>';
1338  if ($usercancreate && $action != 'editmulticurrencycode' && !empty($object->brouillon)) {
1339  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editmulticurrencycode&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1).'</a></td>';
1340  }
1341  print '</tr></table>';
1342  print '</td><td>';
1343  $htmlname = (($usercancreate && $action == 'editmulticurrencycode') ? 'multicurrency_code' : 'none');
1344  $form->form_multicurrency_code($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_code, $htmlname);
1345  print '</td></tr>';
1346 
1347  // Multicurrency rate
1348  if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) {
1349  print '<tr>';
1350  print '<td>';
1351  print '<table class="nobordernopadding" width="100%"><tr><td>';
1352  print $form->editfieldkey('CurrencyRate', 'multicurrency_tx', '', $object, 0);
1353  print '</td>';
1354  if ($usercancreate && $action != 'editmulticurrencyrate' && !empty($object->brouillon) && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
1355  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editmulticurrencyrate&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1).'</a></td>';
1356  }
1357  print '</tr></table>';
1358  print '</td><td>';
1359  if ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') {
1360  if ($action == 'actualizemulticurrencyrate') {
1361  list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
1362  }
1363  $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, ($usercancreate ? 'multicurrency_tx' : 'none'), $object->multicurrency_code);
1364  } else {
1365  $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
1366  if ($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
1367  print '<div class="inline-block"> &nbsp; &nbsp; &nbsp; &nbsp; ';
1368  print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=actualizemulticurrencyrate">'.$langs->trans("ActualizeCurrency").'</a>';
1369  print '</div>';
1370  }
1371  }
1372  print '</td></tr>';
1373  }
1374  }
1375 
1376  // Help of substitution key
1377  $dateexample = dol_now();
1378  if (!empty($object->frequency) && !empty($object->date_when)) {
1379  $dateexample = $object->date_when;
1380  }
1381 
1382  // Help of substitution key
1383  $substitutionarray = getCommonSubstitutionArray($langs, 2, null, $object);
1384 
1385  $substitutionarray['__INVOICE_PREVIOUS_MONTH__'] = $langs->trans("PreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%m').')';
1386  $substitutionarray['__INVOICE_MONTH__'] = $langs->trans("MonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%m').')';
1387  $substitutionarray['__INVOICE_NEXT_MONTH__'] = $langs->trans("NextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%m').')';
1388  $substitutionarray['__INVOICE_PREVIOUS_MONTH_TEXT__'] = $langs->trans("TextPreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%B').')';
1389  $substitutionarray['__INVOICE_MONTH_TEXT__'] = $langs->trans("TextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%B').')';
1390  $substitutionarray['__INVOICE_NEXT_MONTH_TEXT__'] = $langs->trans("TextNextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%B').')';
1391  $substitutionarray['__INVOICE_PREVIOUS_YEAR__'] = $langs->trans("PreviousYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'y'), '%Y').')';
1392  $substitutionarray['__INVOICE_YEAR__'] = $langs->trans("YearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%Y').')';
1393  $substitutionarray['__INVOICE_NEXT_YEAR__'] = $langs->trans("NextYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'y'), '%Y').')';
1394  // Only on template invoices
1395  $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_BEFORE_GEN__'] = $langs->trans("DateNextInvoiceBeforeGen").' ('.$langs->trans("Example").': '.dol_print_date(($object->date_when ? $object->date_when : dol_now()), 'dayhour').')';
1396  $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_AFTER_GEN__'] = $langs->trans("DateNextInvoiceAfterGen").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree(($object->date_when ? $object->date_when : dol_now()), $object->frequency, $object->unit_frequency), 'dayhour').')';
1397  $substitutionarray['__INVOICE_COUNTER_CURRENT__'] = $object->nb_gen_done;
1398  $substitutionarray['__INVOICE_COUNTER_MAX__'] = $object->nb_gen_max;
1399 
1400  $htmltext = '<i>'.$langs->trans("FollowingConstantsWillBeSubstituted").':<br>';
1401  foreach ($substitutionarray as $key => $val) {
1402  $htmltext .= $key.' = '.$langs->trans($val).'<br>';
1403  }
1404  $htmltext .= '</i>';
1405 
1406  // Note public
1407  print '<tr><td>';
1408  print $form->editfieldkey($form->textwithpicto($langs->trans('NotePublic'), $htmltext, 1, 'help', '', 0, 2, 'notepublic'), 'note_public', $object->note_public, $object, $user->rights->facture->creer);
1409  print '</td><td class="wordbreak">';
1410  print $form->editfieldval($langs->trans("NotePublic"), 'note_public', $object->note_public, $object, $user->rights->facture->creer, 'textarea:'.ROWS_4.':90%', '', null, null, '', 1);
1411  print '</td>';
1412  print '</tr>';
1413 
1414  // Note private
1415  print '<tr><td>';
1416  print $form->editfieldkey($form->textwithpicto($langs->trans("NotePrivate"), $htmltext, 1, 'help', '', 0, 2, 'noteprivate'), 'note_private', $object->note_private, $object, $user->rights->facture->creer);
1417  print '</td><td class="wordbreak">';
1418  print $form->editfieldval($langs->trans("NotePrivate"), 'note_private', $object->note_private, $object, $user->rights->facture->creer, 'textarea:'.ROWS_4.':90%', '', null, null, '', 1);
1419  print '</td>';
1420  print '</tr>';
1421 
1422  // Bank Account
1423  print '<tr><td class="nowrap">';
1424  print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
1425  print $langs->trans('BankAccount');
1426  print '<td>';
1427  if (($action != 'editbankaccount') && $user->rights->facture->creer && $object->statut == FactureRec::STATUS_DRAFT) {
1428  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editbankaccount&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetBankAccount'), 1).'</a></td>';
1429  }
1430  print '</tr></table>';
1431  print '</td><td>';
1432  if ($action == 'editbankaccount') {
1433  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1);
1434  } else {
1435  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
1436  }
1437  print "</td>";
1438  print '</tr>';
1439 
1440  // Model pdf
1441  print '<tr><td class="nowrap">';
1442  print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
1443  print $langs->trans('Model');
1444  print '<td>';
1445  if (($action != 'editmodelpdf') && $user->rights->facture->creer && $object->statut == FactureRec::STATUS_DRAFT) {
1446  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editmodelpdf&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetModel'), 1).'</a></td>';
1447  }
1448  print '</tr></table>';
1449  print '</td><td>';
1450  if ($action == 'editmodelpdf') {
1451  include_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php';
1452  $list = array();
1453  $models = ModelePDFFactures::liste_modeles($db);
1454  foreach ($models as $k => $model) {
1455  $list[] = str_replace(':', '|', $k).':'.$model;
1456  }
1457  $select = 'select;'.implode(',', $list);
1458  print $form->editfieldval($langs->trans("Model"), 'modelpdf', $object->model_pdf, $object, $user->rights->facture->creer, $select);
1459  } else {
1460  print $object->model_pdf;
1461  }
1462  print "</td>";
1463  print '</tr>';
1464 
1465  // Other attributes
1466  $cols = 2;
1467  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1468 
1469  print '</table>';
1470 
1471  print '</div>';
1472  print '<div class="fichehalfright">';
1473  print '<div class="underbanner clearboth"></div>';
1474 
1475 
1476  /*
1477  * Recurrence
1478  */
1479  $title = $langs->trans("Recurrence");
1480  //print load_fiche_titre($title, '', 'calendar');
1481 
1482  print '<table class="border centpercent tableforfield">';
1483 
1484  print '<tr><td colspan="2">'.img_picto('', 'recurring', 'class="pictofixedwidth"').$title.'</td></tr>';
1485 
1486  // if "frequency" is empty or = 0, the reccurence is disabled
1487  print '<tr><td style="width: 50%">';
1488  print '<table class="nobordernopadding" width="100%"><tr><td>';
1489  print $langs->trans('Frequency');
1490  print '</td>';
1491  if ($action != 'editfrequency' && $user->rights->facture->creer) {
1492  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editfrequency&token='.newToken().'&facid='.$object->id.'">'.img_edit($langs->trans('Edit'), 1).'</a></td>';
1493  }
1494  print '</tr></table>';
1495  print '</td><td>';
1496  if ($action == 'editfrequency') {
1497  print '<form method="post" action="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'">';
1498  print '<input type="hidden" name="action" value="setfrequency">';
1499  print '<input type="hidden" name="token" value="'.newToken().'">';
1500  print '<table class="nobordernopadding">';
1501  print '<tr><td>';
1502  print "<input type='text' name='frequency' value='".$object->frequency."' size='5' />&nbsp;";
1503  print $form->selectarray('unit_frequency', array('d'=>$langs->trans('Day'), 'm'=>$langs->trans('Month'), 'y'=>$langs->trans('Year')), ($object->unit_frequency ? $object->unit_frequency : 'm'));
1504  print '</td>';
1505  print '<td class="left"><input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans("Modify").'"></td>';
1506  print '</tr></table></form>';
1507  } else {
1508  if ($object->frequency > 0) {
1509  print $langs->trans('FrequencyPer_'.$object->unit_frequency, $object->frequency);
1510  } else {
1511  print '<span class="opacitymedium">'.$langs->trans("NotARecurringInvoiceTemplate").'</span>';
1512  }
1513  }
1514  print '</td></tr>';
1515 
1516  // Date when (next invoice generation)
1517  print '<tr><td>';
1518  if ($action == 'date_when' || $object->frequency > 0) {
1519  print $form->editfieldkey($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->rights->facture->creer, 'day');
1520  } else {
1521  print $langs->trans("NextDateToExecution");
1522  }
1523  print '</td><td>';
1524  if ($action == 'date_when' || $object->frequency > 0) {
1525  print $form->editfieldval($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->rights->facture->creer, 'day', $object->date_when, null, '', '', 0, 'strikeIfMaxNbGenReached');
1526  }
1527  //var_dump(dol_print_date($object->date_when+60, 'dayhour').' - '.dol_print_date($now, 'dayhour'));
1528  if (!$object->isMaxNbGenReached()) {
1529  if (!$object->suspended && $action != 'editdate_when' && $object->frequency > 0 && $object->date_when && $object->date_when < $now) {
1530  print img_warning($langs->trans("Late"));
1531  }
1532  } else {
1533  print img_info($langs->trans("MaxNumberOfGenerationReached"));
1534  }
1535  print '</td>';
1536  print '</tr>';
1537 
1538  // Max period / Rest period
1539  print '<tr><td>';
1540  if ($action == 'nb_gen_max' || $object->frequency > 0) {
1541  print $form->editfieldkey($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max, $object, $user->rights->facture->creer);
1542  } else {
1543  print $langs->trans("MaxPeriodNumber");
1544  }
1545  print '</td><td>';
1546  if ($action == 'nb_gen_max' || $object->frequency > 0) {
1547  print $form->editfieldval($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max ? $object->nb_gen_max : '', $object, $user->rights->facture->creer);
1548  } else {
1549  print '';
1550  }
1551  print '</td>';
1552  print '</tr>';
1553 
1554  // Status of generated invoices
1555  print '<tr><td>';
1556  if ($action == 'auto_validate' || $object->frequency > 0) {
1557  print $form->editfieldkey($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $user->rights->facture->creer);
1558  } else {
1559  print $langs->trans("StatusOfGeneratedInvoices");
1560  }
1561  print '</td><td>';
1562  $select = 'select;0:'.$langs->trans('BillStatusDraft').',1:'.$langs->trans('BillStatusValidated');
1563  if ($action == 'auto_validate' || $object->frequency > 0) {
1564  print $form->editfieldval($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $user->rights->facture->creer, $select);
1565  }
1566  print '</td>';
1567  // Auto generate documents
1568  if (!empty($conf->global->INVOICE_REC_CAN_DISABLE_DOCUMENT_FILE_GENERATION)) {
1569  print '<tr>';
1570  print '<td>';
1571  if ($action == 'generate_pdf' || $object->frequency > 0) {
1572  print $form->editfieldkey($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', $object->generate_pdf, $object, $user->rights->facture->creer);
1573  } else {
1574  print $langs->trans("StatusOfGeneratedDocuments");
1575  }
1576  print '</td>';
1577  print '<td>';
1578  $select = 'select;0:'.$langs->trans('DoNotGenerateDoc').',1:'.$langs->trans('AutogenerateDoc');
1579  if ($action == 'generate_pdf' || $object->frequency > 0) {
1580  print $form->editfieldval($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', $object->generate_pdf, $object, $user->rights->facture->creer, $select);
1581  }
1582  print '</td>';
1583  print '</tr>';
1584  } else {
1585  print '<input type="hidden" name="generate_pdf" value="1">';
1586  }
1587 
1588  print '</table>';
1589 
1590  // Frequencry/Recurring section
1591  if ($object->frequency > 0) {
1592  print '<br>';
1593 
1594  if (!isModEnabled('cron')) {
1595  print info_admin($langs->trans("EnableAndSetupModuleCron", $langs->transnoentitiesnoconv("Module2300Name")));
1596  }
1597 
1598  print '<div class="underbanner clearboth"></div>';
1599  print '<table class="border centpercent tableforfield">';
1600 
1601  // Nb of generation already done
1602  print '<tr><td style="width: 50%">'.$langs->trans("NbOfGenerationDone").'</td>';
1603  print '<td>';
1604  print $object->nb_gen_done ? $object->nb_gen_done : '0';
1605  print '</td>';
1606  print '</tr>';
1607 
1608  // Date last
1609  print '<tr><td>';
1610  print $langs->trans("DateLastGeneration");
1611  print '</td><td>';
1612  print dol_print_date($object->date_last_gen, 'dayhour');
1613  print '</td>';
1614  print '</tr>';
1615 
1616  print '</table>';
1617 
1618  print '<br>';
1619  }
1620 
1621  print '</div>';
1622  print '</div>';
1623 
1624  print '<div class="clearboth"></div><br>';
1625 
1626 
1627  // Lines
1628  print '<form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline') ? '#add' : '#line_'.GETPOST('lineid', 'int')).'" method="POST">';
1629  print '<input type="hidden" name="token" value="' . newToken().'">';
1630  print '<input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">';
1631  print '<input type="hidden" name="mode" value="">';
1632  print '<input type="hidden" name="id" value="' . $object->id.'">';
1633  print '<input type="hidden" name="page_y" value="">';
1634 
1635  if (!empty($conf->use_javascript_ajax) && $object->statut == 0) {
1636  include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
1637  }
1638 
1639  print '<div class="div-table-responsive-no-min">';
1640  print '<table id="tablelines" class="noborder noshadow centpercent">';
1641  // Show object lines
1642  if (!empty($object->lines)) {
1643  $canchangeproduct = 1;
1644  $object->printObjectLines($action, $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice
1645  }
1646 
1647  // Form to add new line
1648  if ($object->statut == $object::STATUS_DRAFT && $user->rights->facture->creer && $action != 'valid' && $action != 'editline') {
1649  if ($action != 'editline') {
1650  // Add free products/services
1651 
1652  $parameters = array();
1653  $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1654  if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1655  if (empty($reshook))
1656  $object->formAddObjectLine(0, $mysoc, $object->thirdparty); // No date selector for template invoice
1657  }
1658  }
1659 
1660  print "</table>\n";
1661  print '</div>';
1662 
1663  print "</form>\n";
1664 
1665  print dol_get_fiche_end();
1666 
1667 
1668  /*
1669  * Action bar
1670  */
1671  print '<div class="tabsAction">';
1672 
1673  $parameters = array();
1674  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1675  if (empty($reshook)) {
1676  $params = array(
1677  'attr' => array(
1678  'class' => 'classfortooltip',
1679  ),
1680  );
1681  if (empty($object->suspended)) {
1682  if ($user->rights->facture->creer) {
1683  if (!empty($object->frequency) && $object->nb_gen_max > 0 && ($object->nb_gen_done >= $object->nb_gen_max)) {
1684  print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("MaxGenerationReached")) . '">' . $langs->trans("CreateBill") . '</a></div>';
1685  } else {
1686  if (empty($object->frequency) || $object->date_when <= $nowlasthour) {
1687  print '<div class="inline-block divButAction"><a class="butAction" href="' . DOL_URL_ROOT . '/compta/facture/card.php?action=create&socid=' . $object->thirdparty->id . '&fac_rec=' . $object->id . '">' . $langs->trans("CreateBill") . '</a></div>';
1688  } else {
1689  print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("DateIsNotEnough")) . '">' . $langs->trans("CreateBill") . '</a></div>';
1690  }
1691  }
1692  } else {
1693  print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#">' . $langs->trans("CreateBill") . '</a></div>';
1694  }
1695  }
1696 
1697  if ($user->rights->facture->creer) {
1698  if (empty($object->suspended)) {
1699  print '<div class="inline-block divButAction"><a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?action=disable&id='.$object->id.'&token='.newToken().'">'.$langs->trans("Disable").'</a></div>';
1700  } else {
1701  print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=enable&id='.$object->id.'&token='.newToken().'">'.$langs->trans("Enable").'</a></div>';
1702  }
1703  }
1704 
1705  // Delete
1706  print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=delete&token=' . newToken(), 'delete', $user->rights->facture->supprimer);
1707  }
1708  print '</div>';
1709 
1710 
1711 
1712  print '<div class="fichecenter"><div class="fichehalfleft">';
1713  print '<a name="builddoc"></a>'; // ancre
1714 
1715 
1716  // Show links to link elements
1717  $linktoelem = $form->showLinkToObjectBlock($object, null, array('invoice'));
1718 
1719  $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
1720 
1721 
1722  print '</div>';
1723  print '<div class="fichehalfright">';
1724 
1725  $MAXEVENT = 10;
1726 
1727  //$morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', dol_buildpath('/mymodule/myobject_agenda.php', 1).'?id='.$object->id);
1728 
1729  // List of actions on element
1730  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
1731  $formactions = new FormActions($db);
1732  $somethingshown = $formactions->showactions($object, $object->element, (is_object($object->thirdparty) ? $object->thirdparty->id : 0), 1, '', $MAXEVENT, '', $morehtmlcenter);
1733 
1734  print '</div>';
1735  print '</div>';
1736  }
1737 }
1738 
1739 // End of page
1740 llxFooter();
1741 $db->close();
if(GETPOST('button_removefilter_x', 'alpha')||GETPOST('button_removefilter.x', 'alpha')||GETPOST('button_removefilter', 'alpha')) if(GETPOST('button_search_x', 'alpha')||GETPOST('button_search.x', 'alpha')||GETPOST('button_search', 'alpha')) if($action=="save" &&empty($cancel)) $help_url
View.
Definition: agenda.php:118
if(preg_match('/set_([a-z0-9_\-]+)/i', $action, $reg)) if(preg_match('/del_([a-z0-9_\-]+)/i', $action, $reg)) if($action=='set') elseif($action=='specimen') elseif($action=='setmodel') elseif($action=='del') elseif($action=='setdoc') $formactions
View.
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:56
llxFooter()
Empty footer.
Definition: wrapper.php:70
const STATUS_DRAFT
Draft status.
Class to manage a WYSIWYG editor.
Class to manage standard extra fields.
Class to manage invoices.
const TYPE_REPLACEMENT
Replacement invoice.
const TYPE_STANDARD
Standard invoice.
const TYPE_CREDIT_NOTE
Credit note invoice.
Class to manage invoice lines of templates.
Class to manage invoice templates.
Class to manage building of HTML components.
Class to manage generation of HTML components Only common components must be here.
Classe permettant la generation de composants html autre Only common components are here.
Class to manage building of HTML components.
static liste_modeles($db, $maxfilenamelength=0)
Return list of active generation modules.
static getIdAndTxFromCode($dbs, $code, $date_document='')
Get id and rate of currency from code.
Class to manage products or services.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
Definition: user.class.php:47
getCountry($searchkey, $withcode='', $dbtouse=0, $outputlangs='', $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
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...
Definition: date.lib.php:621
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition: date.lib.php:121
dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $onlybanner=0, $morehtmlright='')
Show tab footer of a card.
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...
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='')
Show tabs of a record.
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields.
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_get_fiche_end($notab=0)
Return tab footer of a card.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dol_clone($object, $native=0)
Create a clone of instance of object (new instance with same value for each properties) With native =...
dolGetButtonAction($label, $text='', $actionType='default', $url='', $id='', $userRight=1, $params=array())
Function dolGetButtonAction.
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Fonction qui renvoie si tva doit etre tva percue recuperable.
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...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='')
Show information for admin users or standard users.
get_localtax($vatrate, $local, $thirdparty_buyer="", $thirdparty_seller="", $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate,...
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null)
Return array of possible common substitutions.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
isModEnabled($module)
Is Dolibarr module enabled.
img_edit($titlealt='default', $float=0, $other='')
Show logo editer/modifier fiche.
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) VAT...
img_info($titlealt='default')
Show info logo.
invoice_rec_prepare_head($object)
Return array head with list of tabs to view object informations.
$formconfirm
if ($action == 'delbookkeepingyear') {
div float
Buy price without taxes.
Definition: style.css.php:913
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.