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