dolibarr  x.y.z
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 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->rights->margins->creer;
123 $usercanreadallmargin = $user->rights->margins->liretous;
124 $usercancreatewithdrarequest = $user->rights->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_delete' && $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 
441  // Extrafields
442  $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
443  $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
444  // Unset extrafield
445  if (is_array($extralabelsline)) {
446  // Get extra fields
447  foreach ($extralabelsline as $key => $value) {
448  unset($_POST["options_".$key.$predef]);
449  }
450  }
451 
452  if ((empty($idprod) || $idprod < 0) && ($price_ht < 0) && ($qty < 0)) {
453  setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), null, 'errors');
454  $error++;
455  }
456  if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && GETPOST('type') < 0) {
457  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
458  $error++;
459  }
460  if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && (!($price_ht >= 0) || $price_ht == '')) { // Unit price can be 0 but not ''
461  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
462  $error++;
463  }
464  if ($qty == '') {
465  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
466  $error++;
467  }
468  if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && empty($product_desc)) {
469  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
470  $error++;
471  }
472  if ($qty < 0) {
473  $langs->load("errors");
474  setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
475  $error++;
476  }
477 
478  if (!$error && ($qty >= 0) && (!empty($product_desc) || (!empty($idprod) && $idprod > 0))) {
479  $ret = $object->fetch($id);
480  if ($ret < 0) {
481  dol_print_error($db, $object->error);
482  exit();
483  }
484  $ret = $object->fetch_thirdparty();
485 
486  // Clean parameters
487  $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'));
488  $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'));
489  $price_base_type = (GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT');
490 
491  // Define special_code for special lines
492  $special_code = 0;
493  // if (!GETPOST('qty')) $special_code=3; // Options should not exists on invoices
494 
495  // Ecrase $pu par celui du produit
496  // Ecrase $desc par celui du produit
497  // Ecrase $tva_tx par celui du produit
498  // Ecrase $base_price_type par celui du produit
499  // Replaces $fk_unit with the product's
500  if (!empty($idprod) && $idprod > 0) {
501  $prod = new Product($db);
502  $prod->fetch($idprod);
503 
504  $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
505 
506  // Update if prices fields are defined
507  $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
508  $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
509  if (empty($tva_tx)) {
510  $tva_npr = 0;
511  }
512 
513  // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
514  $pqp = (GETPOST('pbq', 'int') ? GETPOST('pbq', 'int') : 0);
515 
516  $datapriceofproduct = $prod->getSellPrice($mysoc, $object->thirdparty, $pqp);
517 
518  $pu_ht = $datapriceofproduct['pu_ht'];
519  $pu_ttc = $datapriceofproduct['pu_ttc'];
520  $price_min = $datapriceofproduct['price_min'];
521  $price_base_type = $datapriceofproduct['price_base_type'];
522  $tva_tx = $datapriceofproduct['tva_tx'];
523  $tva_npr = $datapriceofproduct['tva_npr'];
524 
525  $tmpvat = price2num(preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx));
526  $tmpprodvat = price2num(preg_replace('/\s*\‍(.*\‍)/', '', $prod->tva_tx));
527 
528  // if price ht was forced (ie: from gui when calculated by margin rate and cost price). TODO Why this ?
529  if (!empty($price_ht)) {
530  $pu_ht = price2num($price_ht, 'MU');
531  $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
532  } elseif ($tmpvat != $tmpprodvat) {
533  // On reevalue prix selon taux tva car taux tva transaction peut etre different
534  // de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
535  if ($price_base_type != 'HT') {
536  $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
537  } else {
538  $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
539  }
540  }
541 
542  $desc = '';
543 
544  // Define output language
545  if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
546  $outputlangs = $langs;
547  $newlang = '';
548  if (empty($newlang) && GETPOST('lang_id', 'aZ09')) {
549  $newlang = GETPOST('lang_id', 'aZ09');
550  }
551  if (empty($newlang)) {
552  $newlang = $object->thirdparty->default_lang;
553  }
554  if (!empty($newlang)) {
555  $outputlangs = new Translate("", $conf);
556  $outputlangs->setDefaultLang($newlang);
557  }
558 
559  $desc = (!empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
560  } else {
561  $desc = $prod->description;
562  }
563 
564  $desc = dol_concatdesc($desc, $product_desc);
565 
566  // Add custom code and origin country into description
567  if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (!empty($prod->customcode) || !empty($prod->country_code))) {
568  $tmptxt = '(';
569  // Define output language
570  if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
571  $outputlangs = $langs;
572  $newlang = '';
573  if (empty($newlang) && GETPOST('lang_id', 'alpha')) {
574  $newlang = GETPOST('lang_id', 'alpha');
575  }
576  if (empty($newlang)) {
577  $newlang = $object->thirdparty->default_lang;
578  }
579  if (!empty($newlang)) {
580  $outputlangs = new Translate("", $conf);
581  $outputlangs->setDefaultLang($newlang);
582  $outputlangs->load('products');
583  }
584  if (!empty($prod->customcode)) {
585  $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomCode").': '.$prod->customcode;
586  }
587  if (!empty($prod->customcode) && !empty($prod->country_code)) {
588  $tmptxt .= ' - ';
589  }
590  if (!empty($prod->country_code)) {
591  $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, 0, $db, $outputlangs, 0);
592  }
593  } else {
594  if (!empty($prod->customcode)) {
595  $tmptxt .= $langs->transnoentitiesnoconv("CustomCode").': '.$prod->customcode;
596  }
597  if (!empty($prod->customcode) && !empty($prod->country_code)) {
598  $tmptxt .= ' - ';
599  }
600  if (!empty($prod->country_code)) {
601  $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, 0, $db, $langs, 0);
602  }
603  }
604  $tmptxt .= ')';
605  $desc = dol_concatdesc($desc, $tmptxt);
606  }
607 
608  $type = $prod->type;
609  $fk_unit = $prod->fk_unit;
610  } else {
611  $pu_ht = price2num($price_ht, 'MU');
612  $pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
613  $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
614  $tva_tx = str_replace('*', '', $tva_tx);
615  if (empty($tva_tx)) {
616  $tva_npr = 0;
617  }
618  $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
619  $desc = $product_desc;
620  $type = GETPOST('type');
621  $fk_unit = GETPOST('units', 'alpha');
622  }
623 
624  $date_start_fill = GETPOST('date_start_fill', 'int');
625  $date_end_fill = GETPOST('date_end_fill', 'int');
626 
627  // Margin
628  $fournprice = price2num(GETPOST('fournprice'.$predef) ? GETPOST('fournprice'.$predef) : '');
629  $buyingprice = price2num(GETPOST('buying_price'.$predef) != '' ? GETPOST('buying_price'.$predef) : ''); // If buying_price is '0', we must keep this value
630 
631  // Local Taxes
632  $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $mysoc, $tva_npr);
633  $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $mysoc, $tva_npr);
634 
635  $info_bits = 0;
636  if ($tva_npr) {
637  $info_bits |= 0x01;
638  }
639 
640  if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($pu_ht) * (1 - price2num($remise_percent) / 100) < price2num($price_min)))) {
641  $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency));
642  setEventMessages($mesg, null, 'errors');
643  } else {
644  // Insert line
645  $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);
646 
647  if ($result > 0) {
648  // Define output language and generate document
649  /*if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
650  {
651  // Define output language
652  $outputlangs = $langs;
653  $newlang = '';
654  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
655  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) $newlang = $object->thirdparty->default_lang;
656  if (!empty($newlang)) {
657  $outputlangs = new Translate("", $conf);
658  $outputlangs->setDefaultLang($newlang);
659  }
660  $model=$object->model_pdf;
661  $ret = $object->fetch($id); // Reload to get new records
662 
663  $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
664  if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
665  }*/
666  $object->fetch($object->id); // Reload lines
667 
668  unset($_POST['prod_entry_mode']);
669 
670  unset($_POST['qty']);
671  unset($_POST['type']);
672  unset($_POST['remise_percent']);
673  unset($_POST['price_ht']);
674  unset($_POST['multicurrency_price_ht']);
675  unset($_POST['price_ttc']);
676  unset($_POST['tva_tx']);
677  unset($_POST['product_ref']);
678  unset($_POST['product_label']);
679  unset($_POST['product_desc']);
680  unset($_POST['fournprice']);
681  unset($_POST['buying_price']);
682  unset($_POST['np_marginRate']);
683  unset($_POST['np_markRate']);
684  unset($_POST['dp_desc']);
685  unset($_POST['idprod']);
686  unset($_POST['units']);
687 
688  unset($_POST['date_starthour']);
689  unset($_POST['date_startmin']);
690  unset($_POST['date_startsec']);
691  unset($_POST['date_startday']);
692  unset($_POST['date_startmonth']);
693  unset($_POST['date_startyear']);
694  unset($_POST['date_endhour']);
695  unset($_POST['date_endmin']);
696  unset($_POST['date_endsec']);
697  unset($_POST['date_endday']);
698  unset($_POST['date_endmonth']);
699  unset($_POST['date_endyear']);
700 
701  unset($_POST['date_start_fill']);
702  unset($_POST['date_end_fill']);
703 
704  unset($_POST['situations']);
705  unset($_POST['progress']);
706  } else {
707  setEventMessages($object->error, $object->errors, 'errors');
708  }
709 
710  $action = '';
711  }
712  }
713  } elseif ($action == 'updateline' && $usercancreate && !GETPOST('cancel', 'alpha')) {
714  if (!$object->fetch($id) > 0) {
715  dol_print_error($db);
716  }
717  $object->fetch_thirdparty();
718 
719  // Clean parameters
720  $date_start = '';
721  $date_end = '';
722  //$date_start = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear'));
723  //$date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear'));
724  $description = dol_htmlcleanlastbr(GETPOST('product_desc', 'restricthtml') ? GETPOST('product_desc', 'restricthtml') : GETPOST('desc', 'restricthtml'));
725  $pu_ht = price2num(GETPOST('price_ht'), '', 2);
726  $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
727  $qty = GETPOST('qty');
728  $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), '', 2);
729 
730  // Define info_bits
731  $info_bits = 0;
732  if (preg_match('/\*/', $vat_rate)) {
733  $info_bits |= 0x01;
734  }
735 
736  // Define vat_rate
737  $vat_rate = str_replace('*', '', $vat_rate);
738  $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty);
739  $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty);
740 
741  // Add buying price
742  $fournprice = price2num(GETPOST('fournprice') ? GETPOST('fournprice') : '');
743  $buyingprice = price2num(GETPOST('buying_price') != '' ? GETPOST('buying_price') : ''); // If buying_price is '0', we muste keep this value
744 
745  // Extrafields
746  $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
747  $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
748 
749  $objectline = new FactureLigneRec($db);
750  if ($objectline->fetch(GETPOST('lineid', 'int'))) {
751  $objectline->array_options = $array_options;
752  $result = $objectline->insertExtraFields();
753  if ($result < 0) {
754  setEventMessages($langs->trans('Error').$result, null, 'errors');
755  }
756  }
757 
758  $position = ($objectline->rang >= 0 ? $objectline->rang : 0);
759 
760  // Unset extrafield
761  if (is_array($extralabelsline)) {
762  // Get extra fields
763  foreach ($extralabelsline as $key => $value) {
764  unset($_POST["options_".$key]);
765  }
766  }
767 
768  // Define special_code for special lines
769  $special_code = GETPOST('special_code', 'int');
770  if ($special_code == 3) {
771  $special_code = 0; // Options should not exists on invoices
772  }
773 
774  /*$line = new FactureLigne($db);
775  $line->fetch(GETPOST('lineid', 'int'));
776  $percent = $line->get_prev_progress($object->id);
777 
778  if (GETPOST('progress') < $percent)
779  {
780  $mesg = '<div class="warning">' . $langs->trans("CantBeLessThanMinPercent") . '</div>';
781  setEventMessages($mesg, null, 'warnings');
782  $error++;
783  $result = -1;
784  }*/
785 
786  $remise_percent = price2num(GETPOST('remise_percent'), '', 2);
787 
788  // Check minimum price
789  $productid = GETPOST('productid', 'int');
790  if (!empty($productid)) {
791  $product = new Product($db);
792  $product->fetch($productid);
793 
794  $type = $product->type;
795 
796  $price_min = $product->price_min;
797  if (!empty($conf->global->PRODUIT_MULTIPRICES) && !empty($object->thirdparty->price_level)) {
798  $price_min = $product->multiprices_min[$object->thirdparty->price_level];
799  }
800 
801  $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : '');
802 
803  $typeinvoice = Facture::TYPE_STANDARD;
804 
805  // Check price is not lower than minimum (check is done only for standard or replacement invoices)
806  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)))) {
807  setEventMessages($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)), null, 'errors');
808  $error++;
809  }
810  } else {
811  $type = GETPOST('type', 'int');
812  $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
813 
814  // Check parameters
815  if (GETPOST('type', 'int') < 0) {
816  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
817  $error++;
818  }
819  }
820  if ($qty < 0) {
821  $langs->load("errors");
822  setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
823  $error++;
824  }
825 
826  $date_start_fill = GETPOST('date_start_fill', 'int');
827  $date_end_fill = GETPOST('date_end_fill', 'int');
828 
829  // Update line
830  if (!$error) {
831  $result = $object->updateline(
832  GETPOST('lineid', 'int'),
833  $description,
834  $pu_ht,
835  $qty,
836  $vat_rate,
837  $localtax1_rate,
838  $localtax1_rate,
839  GETPOST('productid', 'int'),
840  $remise_percent,
841  'HT',
842  $info_bits,
843  0,
844  0,
845  $type,
846  $position,
847  $special_code,
848  $label,
849  GETPOST('units'),
850  $pu_ht_devise,
851  0,
852  $date_start_fill,
853  $date_end_fill,
854  $fournprice,
855  $buyingprice
856  );
857 
858  if ($result >= 0) {
859  /*if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
860  // Define output language
861  $outputlangs = $langs;
862  $newlang = '';
863  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id','aZ09'))
864  $newlang = GETPOST('lang_id','aZ09');
865  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang))
866  $newlang = $object->thirdparty->default_lang;
867  if (!empty($newlang)) {
868  $outputlangs = new Translate("", $conf);
869  $outputlangs->setDefaultLang($newlang);
870  }
871 
872  $ret = $object->fetch($id); // Reload to get new records
873  $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
874  }*/
875 
876  $object->fetch($object->id); // Reload lines
877 
878  unset($_POST['qty']);
879  unset($_POST['type']);
880  unset($_POST['productid']);
881  unset($_POST['remise_percent']);
882  unset($_POST['price_ht']);
883  unset($_POST['multicurrency_price_ht']);
884  unset($_POST['price_ttc']);
885  unset($_POST['tva_tx']);
886  unset($_POST['product_ref']);
887  unset($_POST['product_label']);
888  unset($_POST['product_desc']);
889  unset($_POST['fournprice']);
890  unset($_POST['buying_price']);
891  unset($_POST['np_marginRate']);
892  unset($_POST['np_markRate']);
893 
894  unset($_POST['dp_desc']);
895  unset($_POST['idprod']);
896  unset($_POST['units']);
897 
898  unset($_POST['date_starthour']);
899  unset($_POST['date_startmin']);
900  unset($_POST['date_startsec']);
901  unset($_POST['date_startday']);
902  unset($_POST['date_startmonth']);
903  unset($_POST['date_startyear']);
904  unset($_POST['date_endhour']);
905  unset($_POST['date_endmin']);
906  unset($_POST['date_endsec']);
907  unset($_POST['date_endday']);
908  unset($_POST['date_endmonth']);
909  unset($_POST['date_endyear']);
910 
911  unset($_POST['situations']);
912  unset($_POST['progress']);
913  } else {
914  setEventMessages($object->error, $object->errors, 'errors');
915  }
916  }
917  }
918 }
919 
920 
921 /*
922  * View
923  */
924 
925 $help_url = '';
926 llxHeader('', $langs->trans("RepeatableInvoices"), $help_url);
927 
928 $form = new Form($db);
929 $formother = new FormOther($db);
930 if (isModEnabled('project')) {
931  $formproject = new FormProjets($db);
932 }
933 $companystatic = new Societe($db);
934 $invoicerectmp = new FactureRec($db);
935 
936 $now = dol_now();
937 $nowlasthour = dol_get_last_hour($now);
938 
939 
940 /*
941  * Create mode
942  */
943 if ($action == 'create') {
944  print load_fiche_titre($langs->trans("CreateRepeatableInvoice"), '', 'bill');
945 
946  $object = new Facture($db); // Source invoice
947  $product_static = new Product($db);
948 
949  if ($object->fetch($id, $ref) > 0) {
950  $result = $object->getLinesArray();
951 
952  print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
953  print '<input type="hidden" name="token" value="'.newToken().'">';
954  print '<input type="hidden" name="action" value="add">';
955  print '<input type="hidden" name="facid" value="'.$object->id.'">';
956 
957  print dol_get_fiche_head(null, '', '', 0);
958 
959  $rowspan = 4;
960  if (isModEnabled('project')) {
961  $rowspan++;
962  }
963  if ($object->fk_account > 0) {
964  $rowspan++;
965  }
966 
967  print '<table class="border centpercent">';
968 
969  $object->fetch_thirdparty();
970 
971  // Title
972  print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Title").'</td><td>';
973  print '<input class="flat quatrevingtpercent" type="text" name="title" value="'.dol_escape_htmltag(GETPOST("title", 'alphanohtml')).'" autofocus>';
974  print '</td></tr>';
975 
976  // Third party
977  print '<tr><td class="titlefieldcreate">'.$langs->trans("Customer").'</td><td>'.$object->thirdparty->getNomUrl(1, 'customer').'</td>';
978  print '</tr>';
979 
980  $note_public = GETPOSTISSET('note_public') ? GETPOST('note_public', 'restricthtml') : $object->note_public;
981  $note_private = GETPOSTISSET('note_private') ? GETPOST('note_private', 'restricthtml') : $object->note_private;
982 
983  // Help of substitution key
984  $substitutionarray = getCommonSubstitutionArray($langs, 2, null, $object);
985 
986  $substitutionarray['__INVOICE_PREVIOUS_MONTH__'] = $langs->trans("PreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, -1, 'm'), '%m').')';
987  $substitutionarray['__INVOICE_MONTH__'] = $langs->trans("MonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($object->date, '%m').')';
988  $substitutionarray['__INVOICE_NEXT_MONTH__'] = $langs->trans("NextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, 1, 'm'), '%m').')';
989  $substitutionarray['__INVOICE_PREVIOUS_MONTH_TEXT__'] = $langs->trans("TextPreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, -1, 'm'), '%B').')';
990  $substitutionarray['__INVOICE_MONTH_TEXT__'] = $langs->trans("TextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($object->date, '%B').')';
991  $substitutionarray['__INVOICE_NEXT_MONTH_TEXT__'] = $langs->trans("TextNextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, 1, 'm'), '%B').')';
992  $substitutionarray['__INVOICE_PREVIOUS_YEAR__'] = $langs->trans("PreviousYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, -1, 'y'), '%Y').')';
993  $substitutionarray['__INVOICE_YEAR__'] = $langs->trans("YearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($object->date, '%Y').')';
994  $substitutionarray['__INVOICE_NEXT_YEAR__'] = $langs->trans("NextYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, 1, 'y'), '%Y').')';
995  // Only on template invoices
996  $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').')';
997  $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').')';
998  $substitutionarray['__INVOICE_COUNTER_CURRENT__'] = $langs->trans("Count");
999  $substitutionarray['__INVOICE_COUNTER_MAX__'] = $langs->trans("MaxPeriodNumber");
1000 
1001  $htmltext = '<i>'.$langs->trans("FollowingConstantsWillBeSubstituted").':<br>';
1002  foreach ($substitutionarray as $key => $val) {
1003  $htmltext .= $key.' = '.$langs->trans($val).'<br>';
1004  }
1005  $htmltext .= '</i>';
1006 
1007  // Public note
1008  print '<tr>';
1009  print '<td class="tdtop">';
1010  print $form->textwithpicto($langs->trans('NotePublic'), $htmltext, 1, 'help', '', 0, 2, 'notepublic');
1011  print '</td>';
1012  print '<td>';
1013  $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%');
1014  print $doleditor->Create(1);
1015 
1016  // Private note
1017  if (empty($user->socid)) {
1018  print '<tr>';
1019  print '<td class="tdtop">';
1020  print $form->textwithpicto($langs->trans('NotePrivate'), $htmltext, 1, 'help', '', 0, 2, 'noteprivate');
1021  print '</td>';
1022  print '<td>';
1023  $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%');
1024  print $doleditor->Create(1);
1025  // print '<textarea name="note_private" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'.</textarea>
1026  print '</td></tr>';
1027  }
1028 
1029  // Author
1030  print "<tr><td>".$langs->trans("Author")."</td><td>".$user->getFullName($langs)."</td></tr>";
1031 
1032  // Payment term
1033  print "<tr><td>".$langs->trans("PaymentConditions")."</td><td>";
1034  print $form->getSelectConditionsPaiements(GETPOSTISSET('cond_reglement_id') ? GETPOST('cond_reglement_id', 'int') : $object->cond_reglement_id, 'cond_reglement_id', -1, 0, 0, '');
1035  //$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id');
1036  print "</td></tr>";
1037 
1038  // Payment mode
1039  print "<tr><td>".$langs->trans("PaymentMode")."</td><td>";
1040  print img_picto('', 'payment', 'class="pictofixedwidth"');
1041  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);
1042  //$form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', '', 1);
1043  print "</td></tr>";
1044 
1045  // Bank account
1046  if ($object->fk_account > 0) {
1047  print "<tr><td>".$langs->trans('BankAccount')."</td><td>";
1048  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
1049  print "</td></tr>";
1050  }
1051 
1052  // Project
1053  if (isModEnabled('project') && is_object($object->thirdparty) && $object->thirdparty->id > 0) {
1054  $projectid = GETPOST('projectid') ?GETPOST('projectid') : $object->fk_project;
1055  $langs->load('projects');
1056  print '<tr><td>'.$langs->trans('Project').'</td><td>';
1057  print img_picto('', 'project', 'class="pictofixedwidth"');
1058  $numprojet = $formproject->select_projects($object->thirdparty->id, $projectid, 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 0, 0, '');
1059  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>';
1060  print '</td></tr>';
1061  }
1062 
1063  // Model pdf
1064  print "<tr><td>".$langs->trans('Model')."</td><td>";
1065  include_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php';
1066  $list = ModelePDFFactures::liste_modeles($db);
1067  print img_picto('', 'generic', 'class="pictofixedwidth"');
1068  print $form->selectarray('modelpdf', $list, $conf->global->FACTURE_ADDON_PDF);
1069  print "</td></tr>";
1070 
1071  print "</table>";
1072 
1073  print dol_get_fiche_end();
1074 
1075 
1076  // Autogeneration
1077  $title = $langs->trans("Recurrence");
1078  print load_fiche_titre(img_picto('', 'recurring', 'class="pictofixedwidth"').$title, '', '');
1079 
1080  print dol_get_fiche_head(null, '', '', 0);
1081 
1082  print '<table class="border centpercent">';
1083 
1084  // Frequency + unit
1085  print '<tr><td class="titlefieldcreate">'.$form->textwithpicto($langs->trans("Frequency"), $langs->transnoentitiesnoconv('toolTipFrequency'))."</td><td>";
1086  print "<input type='text' name='frequency' value='".GETPOST('frequency', 'int')."' size='4' />&nbsp;";
1087  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'));
1088  print "</td></tr>";
1089 
1090  // Date next run
1091  print "<tr><td>".$langs->trans('NextDateToExecution')."</td><td>";
1092  $date_next_execution = isset($date_next_execution) ? $date_next_execution : (GETPOST('remonth') ? dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')) : -1);
1093  print $form->selectDate($date_next_execution, '', 1, 1, '', "add", 1, 1);
1094  print "</td></tr>";
1095 
1096  // Number max of generation
1097  print "<tr><td>".$langs->trans("MaxPeriodNumber")."</td><td>";
1098  print '<input type="text" name="nb_gen_max" value="'.GETPOST('nb_gen_max').'" size="5" />';
1099  print "</td></tr>";
1100 
1101  // Auto validate the invoice
1102  print "<tr><td>".$langs->trans("StatusOfGeneratedInvoices")."</td><td>";
1103  $select = array('0'=>$langs->trans('BillStatusDraft'), '1'=>$langs->trans('BillStatusValidated'));
1104  print $form->selectarray('auto_validate', $select, GETPOST('auto_validate'));
1105  print "</td></tr>";
1106 
1107  // Auto generate document
1108  if (!empty($conf->global->INVOICE_REC_CAN_DISABLE_DOCUMENT_FILE_GENERATION)) {
1109  print "<tr><td>".$langs->trans("StatusOfGeneratedDocuments")."</td><td>";
1110  $select = array('0'=>$langs->trans('DoNotGenerateDoc'), '1'=>$langs->trans('AutoGenerateDoc'));
1111  print $form->selectarray('generate_pdf', $select, GETPOST('generate_pdf'));
1112  print "</td></tr>";
1113  } else {
1114  print '<input type="hidden" name="generate_pdf" value="1">';
1115  }
1116 
1117  print "</table>";
1118 
1119  print dol_get_fiche_end();
1120 
1121 
1122  $title = $langs->trans("ProductsAndServices");
1123  if (!isModEnabled('service')) {
1124  $title = $langs->trans("Products");
1125  } elseif (!isModEnabled('product')) {
1126  $title = $langs->trans("Services");
1127  }
1128 
1129  print load_fiche_titre($title, '', '');
1130 
1131  /*
1132  * Invoice lines
1133  */
1134  print '<div class="div-table-responsive-no-min">';
1135  print '<table id="tablelines" class="noborder noshadow" width="100%">';
1136  // Show object lines
1137  if (!empty($object->lines)) {
1138  $disableedit = 1;
1139  $disablemove = 1;
1140  $disableremove = 1;
1141  $object->printObjectLines('', $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice
1142  }
1143 
1144  print "</table>\n";
1145  print '<div>';
1146 
1147  print '</td></tr>';
1148 
1149  if ($flag_price_may_change) {
1150  print '<tr><td colspan="3" class="left">';
1151  print '<select name="usenewprice" class="flat">';
1152  print '<option value="0">'.$langs->trans("AlwaysUseFixedPrice").'</option>';
1153  print '<option value="1" disabled>'.$langs->trans("AlwaysUseNewPrice").'</option>';
1154  print '</select>';
1155  print '</td></tr>';
1156  }
1157  print "</table>\n";
1158 
1159  print $form->buttonsSaveCancel("Create");
1160 
1161  print "</form>\n";
1162  } else {
1163  dol_print_error('', "Error, no invoice ".$object->id);
1164  }
1165 } else {
1166  /*
1167  * View mode
1168  */
1169  if ($object->id > 0) {
1170  $object->fetch_thirdparty();
1171 
1172  // Confirmation de la suppression d'une ligne produit
1173  if ($action == 'ask_deleteline') {
1174  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 'no', 1);
1175  }
1176 
1177  // Confirm delete of repeatable invoice
1178  if ($action == 'delete') {
1179  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteRepeatableInvoice'), $langs->trans('ConfirmDeleteRepeatableInvoice'), 'confirm_delete', '', 'no', 1);
1180  }
1181 
1182  // Call Hook formConfirm
1183  $parameters = array('formConfirm' => $formconfirm);
1184  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1185  if (empty($reshook)) {
1186  $formconfirm .= $hookmanager->resPrint;
1187  } elseif ($reshook > 0) {
1188  $formconfirm = $hookmanager->resPrint;
1189  }
1190 
1191  print $formconfirm;
1192 
1193  $author = new User($db);
1194  $author->fetch($object->user_author);
1195 
1196  $head = invoice_rec_prepare_head($object);
1197 
1198  print dol_get_fiche_head($head, 'card', $langs->trans("RepeatableInvoice"), -1, 'bill'); // Add a div
1199 
1200  // Recurring invoice content
1201 
1202  $linkback = '<a href="'.DOL_URL_ROOT.'/compta/facture/invoicetemplate_list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
1203 
1204  $morehtmlref = '';
1205  if ($action != 'editref') {
1206  $morehtmlref .= $form->editfieldkey($object->ref, 'ref', $object->ref, $object, $user->rights->facture->creer, '', '', 0, 2);
1207  } else {
1208  $morehtmlref .= $form->editfieldval('', 'ref', $object->ref, $object, $user->rights->facture->creer, 'string');
1209  }
1210 
1211  $morehtmlref .= '<div class="refidno">';
1212  // Ref customer
1213  //$morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->facture->creer, 'string', '', 0, 1);
1214  //$morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->facture->creer, 'string', '', null, null, '', 1);
1215  // Thirdparty
1216  $morehtmlref .= $langs->trans('ThirdParty').' : '.$object->thirdparty->getNomUrl(1);
1217  // Project
1218  if (isModEnabled('project')) {
1219  $langs->load("projects");
1220  $morehtmlref .= '<br>'.$langs->trans('Project').' ';
1221  if ($user->rights->facture->creer) {
1222  if ($action != 'classify') {
1223  $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> : ';
1224  }
1225  if ($action == 'classify') {
1226  //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
1227  $morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
1228  $morehtmlref .= '<input type="hidden" name="action" value="classin">';
1229  $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
1230  $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
1231  $morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
1232  $morehtmlref .= '</form>';
1233  } else {
1234  $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
1235  }
1236  } else {
1237  if (!empty($object->fk_project)) {
1238  $proj = new Project($db);
1239  $proj->fetch($object->fk_project);
1240  $morehtmlref .= ' : '.$proj->getNomUrl(1);
1241  if ($proj->title) {
1242  $morehtmlref .= ' - '.$proj->title;
1243  }
1244  } else {
1245  $morehtmlref .= '';
1246  }
1247  }
1248  }
1249  $morehtmlref .= '</div>';
1250 
1251  $morehtmlright = '';
1252 
1253  dol_banner_tab($object, 'ref', $linkback, 1, 'title', 'none', $morehtmlref, '', 0, '', $morehtmlright);
1254 
1255  print '<div class="fichecenter">';
1256  print '<div class="fichehalfleft">';
1257  print '<div class="underbanner clearboth"></div>';
1258 
1259  print '<table class="border centpercent tableforfield">';
1260 
1261  print '<tr><td class="titlefield">'.$langs->trans("Author").'</td><td>';
1262  print $author->getNomUrl(-1);
1263  print "</td></tr>";
1264 
1265  print '<tr><td>'.$langs->trans("AmountHT").'</td>';
1266  print '<td>'.price($object->total_ht, '', $langs, 1, -1, -1, $conf->currency).'</td>';
1267  print '</tr>';
1268 
1269  print '<tr><td>'.$langs->trans("AmountVAT").'</td><td>'.price($object->total_tva, '', $langs, 1, -1, -1, $conf->currency).'</td>';
1270  print '</tr>';
1271 
1272  // Amount Local Taxes
1273  if (($mysoc->localtax1_assuj == "1" && $mysoc->useLocalTax(1)) || $object->total_localtax1 != 0) { // Localtax1
1274  print '<tr><td>'.$langs->transcountry("AmountLT1", $mysoc->country_code).'</td>';
1275  print '<td class="nowrap">'.price($object->total_localtax1, 1, '', 1, - 1, - 1, $conf->currency).'</td></tr>';
1276  }
1277  if (($mysoc->localtax2_assuj == "1" && $mysoc->useLocalTax(2)) || $object->total_localtax2 != 0) { // Localtax2
1278  print '<tr><td>'.$langs->transcountry("AmountLT2", $mysoc->country_code).'</td>';
1279  print '<td class=nowrap">'.price($object->total_localtax2, 1, '', 1, - 1, - 1, $conf->currency).'</td></tr>';
1280  }
1281 
1282  print '<tr><td>'.$langs->trans("AmountTTC").'</td><td colspan="3">'.price($object->total_ttc, '', $langs, 1, -1, -1, $conf->currency).'</td>';
1283  print '</tr>';
1284 
1285 
1286  // Payment term
1287  print '<tr><td>';
1288  print '<table class="nobordernopadding centpercent"><tr><td>';
1289  print $langs->trans('PaymentConditionsShort');
1290  print '</td>';
1291  if ($action != 'editconditions' && $user->rights->facture->creer) {
1292  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>';
1293  }
1294  print '</tr></table>';
1295  print '</td><td>';
1296  if ($object->type != Facture::TYPE_CREDIT_NOTE) {
1297  if ($action == 'editconditions') {
1298  $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->cond_reglement_id, 'cond_reglement_id');
1299  } else {
1300  $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->cond_reglement_id, 'none');
1301  }
1302  } else {
1303  print '&nbsp;';
1304  }
1305  print '</td></tr>';
1306 
1307  // Payment mode
1308  print '<tr><td>';
1309  print '<table class="nobordernopadding" width="100%"><tr><td>';
1310  print $langs->trans('PaymentMode');
1311  print '</td>';
1312  if ($action != 'editmode' && $user->rights->facture->creer) {
1313  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>';
1314  }
1315  print '</tr></table>';
1316  print '</td><td>';
1317  if ($action == 'editmode') {
1318  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
1319  } else {
1320  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'none');
1321  }
1322  print '</td></tr>';
1323 
1324  // Multicurrency
1325  if (isModEnabled('multicurrency')) {
1326  // Multicurrency code
1327  print '<tr>';
1328  print '<td>';
1329  print '<table class="nobordernopadding" width="100%"><tr><td>';
1330  print $form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0);
1331  print '</td>';
1332  if ($usercancreate && $action != 'editmulticurrencycode' && !empty($object->brouillon)) {
1333  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>';
1334  }
1335  print '</tr></table>';
1336  print '</td><td>';
1337  $htmlname = (($usercancreate && $action == 'editmulticurrencycode') ? 'multicurrency_code' : 'none');
1338  $form->form_multicurrency_code($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_code, $htmlname);
1339  print '</td></tr>';
1340 
1341  // Multicurrency rate
1342  if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) {
1343  print '<tr>';
1344  print '<td>';
1345  print '<table class="nobordernopadding" width="100%"><tr><td>';
1346  print $form->editfieldkey('CurrencyRate', 'multicurrency_tx', '', $object, 0);
1347  print '</td>';
1348  if ($usercancreate && $action != 'editmulticurrencyrate' && !empty($object->brouillon) && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
1349  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>';
1350  }
1351  print '</tr></table>';
1352  print '</td><td>';
1353  if ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') {
1354  if ($action == 'actualizemulticurrencyrate') {
1355  list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
1356  }
1357  $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, ($usercancreate ? 'multicurrency_tx' : 'none'), $object->multicurrency_code);
1358  } else {
1359  $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
1360  if ($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
1361  print '<div class="inline-block"> &nbsp; &nbsp; &nbsp; &nbsp; ';
1362  print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=actualizemulticurrencyrate">'.$langs->trans("ActualizeCurrency").'</a>';
1363  print '</div>';
1364  }
1365  }
1366  print '</td></tr>';
1367  }
1368  }
1369 
1370  // Help of substitution key
1371  $dateexample = dol_now();
1372  if (!empty($object->frequency) && !empty($object->date_when)) {
1373  $dateexample = $object->date_when;
1374  }
1375 
1376  // Help of substitution key
1377  $substitutionarray = getCommonSubstitutionArray($langs, 2, null, $object);
1378 
1379  $substitutionarray['__INVOICE_PREVIOUS_MONTH__'] = $langs->trans("PreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%m').')';
1380  $substitutionarray['__INVOICE_MONTH__'] = $langs->trans("MonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%m').')';
1381  $substitutionarray['__INVOICE_NEXT_MONTH__'] = $langs->trans("NextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%m').')';
1382  $substitutionarray['__INVOICE_PREVIOUS_MONTH_TEXT__'] = $langs->trans("TextPreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%B').')';
1383  $substitutionarray['__INVOICE_MONTH_TEXT__'] = $langs->trans("TextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%B').')';
1384  $substitutionarray['__INVOICE_NEXT_MONTH_TEXT__'] = $langs->trans("TextNextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%B').')';
1385  $substitutionarray['__INVOICE_PREVIOUS_YEAR__'] = $langs->trans("PreviousYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'y'), '%Y').')';
1386  $substitutionarray['__INVOICE_YEAR__'] = $langs->trans("YearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%Y').')';
1387  $substitutionarray['__INVOICE_NEXT_YEAR__'] = $langs->trans("NextYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'y'), '%Y').')';
1388  // Only on template invoices
1389  $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').')';
1390  $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').')';
1391  $substitutionarray['__INVOICE_COUNTER_CURRENT__'] = $object->nb_gen_done;
1392  $substitutionarray['__INVOICE_COUNTER_MAX__'] = $object->nb_gen_max;
1393 
1394  $htmltext = '<i>'.$langs->trans("FollowingConstantsWillBeSubstituted").':<br>';
1395  foreach ($substitutionarray as $key => $val) {
1396  $htmltext .= $key.' = '.$langs->trans($val).'<br>';
1397  }
1398  $htmltext .= '</i>';
1399 
1400  // Note public
1401  print '<tr><td>';
1402  print $form->editfieldkey($form->textwithpicto($langs->trans('NotePublic'), $htmltext, 1, 'help', '', 0, 2, 'notepublic'), 'note_public', $object->note_public, $object, $user->rights->facture->creer);
1403  print '</td><td class="wordbreak">';
1404  print $form->editfieldval($langs->trans("NotePublic"), 'note_public', $object->note_public, $object, $user->rights->facture->creer, 'textarea:'.ROWS_4.':90%', '', null, null, '', 1);
1405  print '</td>';
1406  print '</tr>';
1407 
1408  // Note private
1409  print '<tr><td>';
1410  print $form->editfieldkey($form->textwithpicto($langs->trans("NotePrivate"), $htmltext, 1, 'help', '', 0, 2, 'noteprivate'), 'note_private', $object->note_private, $object, $user->rights->facture->creer);
1411  print '</td><td class="wordbreak">';
1412  print $form->editfieldval($langs->trans("NotePrivate"), 'note_private', $object->note_private, $object, $user->rights->facture->creer, 'textarea:'.ROWS_4.':90%', '', null, null, '', 1);
1413  print '</td>';
1414  print '</tr>';
1415 
1416  // Bank Account
1417  print '<tr><td class="nowrap">';
1418  print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
1419  print $langs->trans('BankAccount');
1420  print '<td>';
1421  if (($action != 'editbankaccount') && $user->rights->facture->creer && $object->statut == FactureRec::STATUS_DRAFT) {
1422  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>';
1423  }
1424  print '</tr></table>';
1425  print '</td><td>';
1426  if ($action == 'editbankaccount') {
1427  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1);
1428  } else {
1429  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
1430  }
1431  print "</td>";
1432  print '</tr>';
1433 
1434  // Model pdf
1435  print '<tr><td class="nowrap">';
1436  print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
1437  print $langs->trans('Model');
1438  print '<td>';
1439  if (($action != 'editmodelpdf') && $user->rights->facture->creer && $object->statut == FactureRec::STATUS_DRAFT) {
1440  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>';
1441  }
1442  print '</tr></table>';
1443  print '</td><td>';
1444  if ($action == 'editmodelpdf') {
1445  include_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php';
1446  $list = array();
1447  $models = ModelePDFFactures::liste_modeles($db);
1448  foreach ($models as $k => $model) {
1449  $list[] = str_replace(':', '|', $k).':'.$model;
1450  }
1451  $select = 'select;'.implode(',', $list);
1452  print $form->editfieldval($langs->trans("Model"), 'modelpdf', $object->model_pdf, $object, $user->rights->facture->creer, $select);
1453  } else {
1454  print $object->model_pdf;
1455  }
1456  print "</td>";
1457  print '</tr>';
1458 
1459  // Other attributes
1460  $cols = 2;
1461  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1462 
1463  print '</table>';
1464 
1465  print '</div>';
1466  print '<div class="fichehalfright">';
1467  print '<div class="underbanner clearboth"></div>';
1468 
1469 
1470  /*
1471  * Recurrence
1472  */
1473  $title = $langs->trans("Recurrence");
1474  //print load_fiche_titre($title, '', 'calendar');
1475 
1476  print '<table class="border centpercent tableforfield">';
1477 
1478  print '<tr><td colspan="2">'.img_picto('', 'recurring', 'class="pictofixedwidth"').$title.'</td></tr>';
1479 
1480  // if "frequency" is empty or = 0, the reccurence is disabled
1481  print '<tr><td style="width: 50%">';
1482  print '<table class="nobordernopadding" width="100%"><tr><td>';
1483  print $langs->trans('Frequency');
1484  print '</td>';
1485  if ($action != 'editfrequency' && $user->rights->facture->creer) {
1486  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>';
1487  }
1488  print '</tr></table>';
1489  print '</td><td>';
1490  if ($action == 'editfrequency') {
1491  print '<form method="post" action="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'">';
1492  print '<input type="hidden" name="action" value="setfrequency">';
1493  print '<input type="hidden" name="token" value="'.newToken().'">';
1494  print '<table class="nobordernopadding">';
1495  print '<tr><td>';
1496  print "<input type='text' name='frequency' value='".$object->frequency."' size='5' />&nbsp;";
1497  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'));
1498  print '</td>';
1499  print '<td class="left"><input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans("Modify").'"></td>';
1500  print '</tr></table></form>';
1501  } else {
1502  if ($object->frequency > 0) {
1503  print $langs->trans('FrequencyPer_'.$object->unit_frequency, $object->frequency);
1504  } else {
1505  print '<span class="opacitymedium">'.$langs->trans("NotARecurringInvoiceTemplate").'</span>';
1506  }
1507  }
1508  print '</td></tr>';
1509 
1510  // Date when (next invoice generation)
1511  print '<tr><td>';
1512  if ($action == 'date_when' || $object->frequency > 0) {
1513  print $form->editfieldkey($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->rights->facture->creer, 'day');
1514  } else {
1515  print $langs->trans("NextDateToExecution");
1516  }
1517  print '</td><td>';
1518  if ($action == 'date_when' || $object->frequency > 0) {
1519  print $form->editfieldval($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->rights->facture->creer, 'day', $object->date_when, null, '', '', 0, 'strikeIfMaxNbGenReached');
1520  }
1521  //var_dump(dol_print_date($object->date_when+60, 'dayhour').' - '.dol_print_date($now, 'dayhour'));
1522  if (!$object->isMaxNbGenReached()) {
1523  if (!$object->suspended && $action != 'editdate_when' && $object->frequency > 0 && $object->date_when && $object->date_when < $now) {
1524  print img_warning($langs->trans("Late"));
1525  }
1526  } else {
1527  print img_info($langs->trans("MaxNumberOfGenerationReached"));
1528  }
1529  print '</td>';
1530  print '</tr>';
1531 
1532  // Max period / Rest period
1533  print '<tr><td>';
1534  if ($action == 'nb_gen_max' || $object->frequency > 0) {
1535  print $form->editfieldkey($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max, $object, $user->rights->facture->creer);
1536  } else {
1537  print $langs->trans("MaxPeriodNumber");
1538  }
1539  print '</td><td>';
1540  if ($action == 'nb_gen_max' || $object->frequency > 0) {
1541  print $form->editfieldval($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max ? $object->nb_gen_max : '', $object, $user->rights->facture->creer);
1542  } else {
1543  print '';
1544  }
1545  print '</td>';
1546  print '</tr>';
1547 
1548  // Status of generated invoices
1549  print '<tr><td>';
1550  if ($action == 'auto_validate' || $object->frequency > 0) {
1551  print $form->editfieldkey($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $user->rights->facture->creer);
1552  } else {
1553  print $langs->trans("StatusOfGeneratedInvoices");
1554  }
1555  print '</td><td>';
1556  $select = 'select;0:'.$langs->trans('BillStatusDraft').',1:'.$langs->trans('BillStatusValidated');
1557  if ($action == 'auto_validate' || $object->frequency > 0) {
1558  print $form->editfieldval($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $user->rights->facture->creer, $select);
1559  }
1560  print '</td>';
1561  // Auto generate documents
1562  if (!empty($conf->global->INVOICE_REC_CAN_DISABLE_DOCUMENT_FILE_GENERATION)) {
1563  print '<tr>';
1564  print '<td>';
1565  if ($action == 'generate_pdf' || $object->frequency > 0) {
1566  print $form->editfieldkey($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', $object->generate_pdf, $object, $user->rights->facture->creer);
1567  } else {
1568  print $langs->trans("StatusOfGeneratedDocuments");
1569  }
1570  print '</td>';
1571  print '<td>';
1572  $select = 'select;0:'.$langs->trans('DoNotGenerateDoc').',1:'.$langs->trans('AutogenerateDoc');
1573  if ($action == 'generate_pdf' || $object->frequency > 0) {
1574  print $form->editfieldval($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', $object->generate_pdf, $object, $user->rights->facture->creer, $select);
1575  }
1576  print '</td>';
1577  print '</tr>';
1578  } else {
1579  print '<input type="hidden" name="generate_pdf" value="1">';
1580  }
1581 
1582  print '</table>';
1583 
1584  // Frequencry/Recurring section
1585  if ($object->frequency > 0) {
1586  print '<br>';
1587 
1588  if (!isModEnabled('cron')) {
1589  print info_admin($langs->trans("EnableAndSetupModuleCron", $langs->transnoentitiesnoconv("Module2300Name")));
1590  }
1591 
1592  print '<div class="underbanner clearboth"></div>';
1593  print '<table class="border centpercent tableforfield">';
1594 
1595  // Nb of generation already done
1596  print '<tr><td style="width: 50%">'.$langs->trans("NbOfGenerationDone").'</td>';
1597  print '<td>';
1598  print $object->nb_gen_done ? $object->nb_gen_done : '0';
1599  print '</td>';
1600  print '</tr>';
1601 
1602  // Date last
1603  print '<tr><td>';
1604  print $langs->trans("DateLastGeneration");
1605  print '</td><td>';
1606  print dol_print_date($object->date_last_gen, 'dayhour');
1607  print '</td>';
1608  print '</tr>';
1609 
1610  print '</table>';
1611 
1612  print '<br>';
1613  }
1614 
1615  print '</div>';
1616  print '</div>';
1617 
1618  print '<div class="clearboth"></div><br>';
1619 
1620 
1621  // Lines
1622  print '<form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline') ? '#add' : '#line_'.GETPOST('lineid', 'int')).'" method="POST">';
1623  print '<input type="hidden" name="token" value="' . newToken().'">';
1624  print '<input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">';
1625  print '<input type="hidden" name="mode" value="">';
1626  print '<input type="hidden" name="id" value="' . $object->id.'">';
1627  print '<input type="hidden" name="page_y" value="">';
1628 
1629  if (!empty($conf->use_javascript_ajax) && $object->statut == 0) {
1630  include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
1631  }
1632 
1633  print '<div class="div-table-responsive-no-min">';
1634  print '<table id="tablelines" class="noborder noshadow centpercent">';
1635  // Show object lines
1636  if (!empty($object->lines)) {
1637  $canchangeproduct = 1;
1638  $object->printObjectLines($action, $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice
1639  }
1640 
1641  // Form to add new line
1642  if ($object->statut == $object::STATUS_DRAFT && $user->rights->facture->creer && $action != 'valid' && $action != 'editline') {
1643  if ($action != 'editline') {
1644  // Add free products/services
1645 
1646  $parameters = array();
1647  $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1648  if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1649  if (empty($reshook))
1650  $object->formAddObjectLine(0, $mysoc, $object->thirdparty); // No date selector for template invoice
1651  }
1652  }
1653 
1654  print "</table>\n";
1655  print '</div>';
1656 
1657  print "</form>\n";
1658 
1659  print dol_get_fiche_end();
1660 
1661 
1662  /*
1663  * Action bar
1664  */
1665  print '<div class="tabsAction">';
1666 
1667  $parameters = array();
1668  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1669  if (empty($reshook)) {
1670  $params = array(
1671  'attr' => array(
1672  'class' => 'classfortooltip',
1673  ),
1674  );
1675  if (empty($object->suspended)) {
1676  if ($user->rights->facture->creer) {
1677  if (!empty($object->frequency) && $object->nb_gen_max > 0 && ($object->nb_gen_done >= $object->nb_gen_max)) {
1678  print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("MaxGenerationReached")) . '">' . $langs->trans("CreateBill") . '</a></div>';
1679  } else {
1680  if (empty($object->frequency) || $object->date_when <= $nowlasthour) {
1681  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>';
1682  } else {
1683  print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("DateIsNotEnough")) . '">' . $langs->trans("CreateBill") . '</a></div>';
1684  }
1685  }
1686  } else {
1687  print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#">' . $langs->trans("CreateBill") . '</a></div>';
1688  }
1689  }
1690 
1691  if ($user->rights->facture->creer) {
1692  if (empty($object->suspended)) {
1693  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>';
1694  } else {
1695  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>';
1696  }
1697  }
1698 
1699  // Delete
1700  print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=delete&token=' . newToken(), 'delete', $user->rights->facture->supprimer);
1701  }
1702  print '</div>';
1703 
1704 
1705 
1706  print '<div class="fichecenter"><div class="fichehalfleft">';
1707  print '<a name="builddoc"></a>'; // ancre
1708 
1709 
1710  // Show links to link elements
1711  $linktoelem = $form->showLinkToObjectBlock($object, null, array('invoice'));
1712 
1713  $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
1714 
1715 
1716  print '</div>';
1717  print '<div class="fichehalfright">';
1718 
1719  $MAXEVENT = 10;
1720 
1721  //$morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', dol_buildpath('/mymodule/myobject_agenda.php', 1).'?id='.$object->id);
1722 
1723  // List of actions on element
1724  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
1725  $formactions = new FormActions($db);
1726  $somethingshown = $formactions->showactions($object, $object->element, (is_object($object->thirdparty) ? $object->thirdparty->id : 0), 1, '', $MAXEVENT, '', $morehtmlcenter);
1727 
1728  print '</div>';
1729  print '</div>';
1730  }
1731 }
1732 
1733 // End of page
1734 llxFooter();
1735 $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:45
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.