dolibarr  19.0.0-dev
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  $tva_tx = (GETPOST('tva_tx', 'alpha') ? GETPOST('tva_tx', 'alpha') : 0);
433  } else {
434  $idprod = GETPOST('idprod', 'int');
435  $tva_tx = '';
436 
437  if (!empty($conf->global->MAIN_DISABLE_FREE_LINES) && $idprod <= 0) {
438  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")), null, 'errors');
439  $error++;
440  }
441  }
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 
499  // Define special_code for special lines
500  $special_code = 0;
501  // if (!GETPOST('qty')) $special_code=3; // Options should not exists on invoices
502 
503  // Ecrase $pu par celui du produit
504  // Ecrase $desc par celui du produit
505  // Ecrase $tva_tx 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 = $datapriceofproduct['price_base_type'];
530  $tva_tx = $datapriceofproduct['tva_tx'];
531  $tva_npr = $datapriceofproduct['tva_npr'];
532 
533  $tmpvat = 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 $title = $object->ref." - ".$langs->trans('Card');
937 $help_url = '';
938 
939 llxHeader('', $title, $help_url);
940 
941 $form = new Form($db);
942 $formother = new FormOther($db);
943 if (isModEnabled('project')) {
944  $formproject = new FormProjets($db);
945 }
946 $companystatic = new Societe($db);
947 $invoicerectmp = new FactureRec($db);
948 
949 $now = dol_now();
950 $nowlasthour = dol_get_last_hour($now);
951 
952 
953 /*
954  * Create mode
955  */
956 if ($action == 'create') {
957  print load_fiche_titre($langs->trans("CreateRepeatableInvoice"), '', 'bill');
958 
959  $object = new Facture($db); // Source invoice
960  $product_static = new Product($db);
961 
962  if ($object->fetch($id, $ref) > 0) {
963  $result = $object->getLinesArray();
964 
965  print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
966  print '<input type="hidden" name="token" value="'.newToken().'">';
967  print '<input type="hidden" name="action" value="add">';
968  print '<input type="hidden" name="facid" value="'.$object->id.'">';
969 
970  print dol_get_fiche_head(null, '', '', 0);
971 
972  $rowspan = 4;
973  if (isModEnabled('project')) {
974  $rowspan++;
975  }
976  if ($object->fk_account > 0) {
977  $rowspan++;
978  }
979 
980  print '<table class="border centpercent">';
981 
982  $object->fetch_thirdparty();
983 
984  // Title
985  print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Title").'</td><td>';
986  print '<input class="flat quatrevingtpercent" type="text" name="title" value="'.dol_escape_htmltag(GETPOST("title", 'alphanohtml')).'" autofocus>';
987  print '</td></tr>';
988 
989  // Third party
990  print '<tr><td class="titlefieldcreate">'.$langs->trans("Customer").'</td><td>'.$object->thirdparty->getNomUrl(1, 'customer').'</td>';
991  print '</tr>';
992 
993  $note_public = GETPOSTISSET('note_public') ? GETPOST('note_public', 'restricthtml') : $object->note_public;
994  $note_private = GETPOSTISSET('note_private') ? GETPOST('note_private', 'restricthtml') : $object->note_private;
995 
996  // Help of substitution key
997  $substitutionarray = getCommonSubstitutionArray($langs, 2, null, $object);
998 
999  $substitutionarray['__INVOICE_PREVIOUS_MONTH__'] = $langs->trans("PreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, -1, 'm'), '%m').')';
1000  $substitutionarray['__INVOICE_MONTH__'] = $langs->trans("MonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($object->date, '%m').')';
1001  $substitutionarray['__INVOICE_NEXT_MONTH__'] = $langs->trans("NextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, 1, 'm'), '%m').')';
1002  $substitutionarray['__INVOICE_PREVIOUS_MONTH_TEXT__'] = $langs->trans("TextPreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, -1, 'm'), '%B').')';
1003  $substitutionarray['__INVOICE_MONTH_TEXT__'] = $langs->trans("TextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($object->date, '%B').')';
1004  $substitutionarray['__INVOICE_NEXT_MONTH_TEXT__'] = $langs->trans("TextNextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, 1, 'm'), '%B').')';
1005  $substitutionarray['__INVOICE_PREVIOUS_YEAR__'] = $langs->trans("PreviousYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, -1, 'y'), '%Y').')';
1006  $substitutionarray['__INVOICE_YEAR__'] = $langs->trans("YearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($object->date, '%Y').')';
1007  $substitutionarray['__INVOICE_NEXT_YEAR__'] = $langs->trans("NextYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($object->date, 1, 'y'), '%Y').')';
1008  // Only on template invoices
1009  $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').')';
1010  $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').')';
1011  $substitutionarray['__INVOICE_COUNTER_CURRENT__'] = $langs->trans("Count");
1012  $substitutionarray['__INVOICE_COUNTER_MAX__'] = $langs->trans("MaxPeriodNumber");
1013 
1014  $htmltext = '<i>'.$langs->trans("FollowingConstantsWillBeSubstituted").':<br>';
1015  foreach ($substitutionarray as $key => $val) {
1016  $htmltext .= $key.' = '.$langs->trans($val).'<br>';
1017  }
1018  $htmltext .= '</i>';
1019 
1020  // Public note
1021  print '<tr>';
1022  print '<td class="tdtop">';
1023  print $form->textwithpicto($langs->trans('NotePublic'), $htmltext, 1, 'help', '', 0, 2, 'notepublic');
1024  print '</td>';
1025  print '<td>';
1026  $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%');
1027  print $doleditor->Create(1);
1028 
1029  // Private note
1030  if (empty($user->socid)) {
1031  print '<tr>';
1032  print '<td class="tdtop">';
1033  print $form->textwithpicto($langs->trans('NotePrivate'), $htmltext, 1, 'help', '', 0, 2, 'noteprivate');
1034  print '</td>';
1035  print '<td>';
1036  $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%');
1037  print $doleditor->Create(1);
1038  // print '<textarea name="note_private" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'.</textarea>
1039  print '</td></tr>';
1040  }
1041 
1042  // Author
1043  print "<tr><td>".$langs->trans("Author")."</td><td>".$user->getFullName($langs)."</td></tr>";
1044 
1045  // Payment term
1046  print "<tr><td>".$langs->trans("PaymentConditions")."</td><td>";
1047  print $form->getSelectConditionsPaiements(GETPOSTISSET('cond_reglement_id') ? GETPOST('cond_reglement_id', 'int') : $object->cond_reglement_id, 'cond_reglement_id', -1, 0, 0, '');
1048  //$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id');
1049  print "</td></tr>";
1050 
1051  // Payment mode
1052  print "<tr><td>".$langs->trans("PaymentMode")."</td><td>";
1053  print img_picto('', 'payment', 'class="pictofixedwidth"');
1054  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);
1055  //$form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', '', 1);
1056  print "</td></tr>";
1057 
1058  // Bank account
1059  if ($object->fk_account > 0) {
1060  print "<tr><td>".$langs->trans('BankAccount')."</td><td>";
1061  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
1062  print "</td></tr>";
1063  }
1064 
1065  // Project
1066  if (isModEnabled('project') && is_object($object->thirdparty) && $object->thirdparty->id > 0) {
1067  $projectid = GETPOST('projectid') ?GETPOST('projectid') : $object->fk_project;
1068  $langs->load('projects');
1069  print '<tr><td>'.$langs->trans('Project').'</td><td>';
1070  print img_picto('', 'project', 'class="pictofixedwidth"');
1071  $numprojet = $formproject->select_projects($object->thirdparty->id, $projectid, 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 0, 0, '');
1072  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>';
1073  print '</td></tr>';
1074  }
1075 
1076  // Model pdf
1077  print "<tr><td>".$langs->trans('Model')."</td><td>";
1078  include_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php';
1079  $list = ModelePDFFactures::liste_modeles($db);
1080  print img_picto('', 'generic', 'class="pictofixedwidth"');
1081  print $form->selectarray('modelpdf', $list, $conf->global->FACTURE_ADDON_PDF);
1082  print "</td></tr>";
1083 
1084  print "</table>";
1085 
1086  print dol_get_fiche_end();
1087 
1088 
1089  // Autogeneration
1090  $title = $langs->trans("Recurrence");
1091  print load_fiche_titre(img_picto('', 'recurring', 'class="pictofixedwidth"').$title, '', '');
1092 
1093  print dol_get_fiche_head(null, '', '', 0);
1094 
1095  print '<table class="border centpercent">';
1096 
1097  // Frequency + unit
1098  print '<tr><td class="titlefieldcreate">'.$form->textwithpicto($langs->trans("Frequency"), $langs->transnoentitiesnoconv('toolTipFrequency'))."</td><td>";
1099  print "<input type='text' name='frequency' value='".GETPOST('frequency', 'int')."' size='4' />&nbsp;";
1100  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'));
1101  print "</td></tr>";
1102 
1103  // Date next run
1104  print "<tr><td>".$langs->trans('NextDateToExecution')."</td><td>";
1105  $date_next_execution = isset($date_next_execution) ? $date_next_execution : (GETPOST('remonth') ? dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')) : -1);
1106  print $form->selectDate($date_next_execution, '', 1, 1, '', "add", 1, 1);
1107  print "</td></tr>";
1108 
1109  // Number max of generation
1110  print "<tr><td>".$langs->trans("MaxPeriodNumber")."</td><td>";
1111  print '<input type="text" name="nb_gen_max" value="'.GETPOST('nb_gen_max').'" size="5" />';
1112  print "</td></tr>";
1113 
1114  // Auto validate the invoice
1115  print "<tr><td>".$langs->trans("StatusOfGeneratedInvoices")."</td><td>";
1116  $select = array('0'=>$langs->trans('BillStatusDraft'), '1'=>$langs->trans('BillStatusValidated'));
1117  print $form->selectarray('auto_validate', $select, GETPOST('auto_validate'));
1118  print "</td></tr>";
1119 
1120  // Auto generate document
1121  if (!empty($conf->global->INVOICE_REC_CAN_DISABLE_DOCUMENT_FILE_GENERATION)) {
1122  print "<tr><td>".$langs->trans("StatusOfGeneratedDocuments")."</td><td>";
1123  $select = array('0'=>$langs->trans('DoNotGenerateDoc'), '1'=>$langs->trans('AutoGenerateDoc'));
1124  print $form->selectarray('generate_pdf', $select, GETPOST('generate_pdf'));
1125  print "</td></tr>";
1126  } else {
1127  print '<input type="hidden" name="generate_pdf" value="1">';
1128  }
1129 
1130  print "</table>";
1131 
1132  print dol_get_fiche_end();
1133 
1134 
1135  $title = $langs->trans("ProductsAndServices");
1136  if (!isModEnabled('service')) {
1137  $title = $langs->trans("Products");
1138  } elseif (!isModEnabled('product')) {
1139  $title = $langs->trans("Services");
1140  }
1141 
1142  print load_fiche_titre($title, '', '');
1143 
1144  /*
1145  * Invoice lines
1146  */
1147  print '<div class="div-table-responsive-no-min">';
1148  print '<table id="tablelines" class="noborder noshadow" width="100%">';
1149  // Show object lines
1150  if (!empty($object->lines)) {
1151  $disableedit = 1;
1152  $disablemove = 1;
1153  $disableremove = 1;
1154  $object->printObjectLines('', $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice
1155  }
1156 
1157  print "</table>\n";
1158  print '<div>';
1159 
1160  print '</td></tr>';
1161 
1162  if ($flag_price_may_change) {
1163  print '<tr><td colspan="3" class="left">';
1164  print '<select name="usenewprice" class="flat">';
1165  print '<option value="0">'.$langs->trans("AlwaysUseFixedPrice").'</option>';
1166  print '<option value="1" disabled>'.$langs->trans("AlwaysUseNewPrice").'</option>';
1167  print '</select>';
1168  print '</td></tr>';
1169  }
1170  print "</table>\n";
1171 
1172  print $form->buttonsSaveCancel("Create");
1173 
1174  print "</form>\n";
1175  } else {
1176  dol_print_error('', "Error, no invoice ".$object->id);
1177  }
1178 } else {
1179  /*
1180  * View mode
1181  */
1182  if ($object->id > 0) {
1183  $object->fetch_thirdparty();
1184 
1185  // Confirmation de la suppression d'une ligne produit
1186  if ($action == 'ask_deleteline') {
1187  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 'no', 1);
1188  }
1189 
1190  // Confirm delete of repeatable invoice
1191  if ($action == 'delete') {
1192  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteRepeatableInvoice'), $langs->trans('ConfirmDeleteRepeatableInvoice'), 'confirm_delete', '', 'no', 1);
1193  }
1194 
1195  // Call Hook formConfirm
1196  $parameters = array('formConfirm' => $formconfirm);
1197  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1198  if (empty($reshook)) {
1199  $formconfirm .= $hookmanager->resPrint;
1200  } elseif ($reshook > 0) {
1201  $formconfirm = $hookmanager->resPrint;
1202  }
1203 
1204  print $formconfirm;
1205 
1206  $author = new User($db);
1207  $author->fetch($object->user_author);
1208 
1209  $head = invoice_rec_prepare_head($object);
1210 
1211  print dol_get_fiche_head($head, 'card', $langs->trans("RepeatableInvoice"), -1, 'bill'); // Add a div
1212 
1213  // Recurring invoice content
1214 
1215  $linkback = '<a href="'.DOL_URL_ROOT.'/compta/facture/invoicetemplate_list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
1216 
1217  $morehtmlref = '';
1218  if ($action != 'editref') {
1219  $morehtmlref .= $form->editfieldkey($object->ref, 'ref', $object->ref, $object, $user->hasRight('facture', 'creer'), '', '', 0, 2);
1220  } else {
1221  $morehtmlref .= $form->editfieldval('', 'ref', $object->ref, $object, $user->hasRight('facture', 'creer'), 'string');
1222  }
1223 
1224  $morehtmlref .= '<div class="refidno">';
1225  // Ref customer
1226  //$morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $user->hasRight('facture', 'creer'), 'string', '', 0, 1);
1227  //$morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->hasRight('facture', 'creer'), 'string', '', null, null, '', 1);
1228  // Thirdparty
1229  $morehtmlref .= $object->thirdparty->getNomUrl(1, 'customer');
1230  // Project
1231  if (isModEnabled('project')) {
1232  $langs->load("projects");
1233  $morehtmlref .= '<br>';
1234  if ($user->hasRight('facture', 'creer')) {
1235  $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
1236  if ($action != 'classify') {
1237  $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
1238  }
1239  $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
1240  } else {
1241  if (!empty($object->fk_project)) {
1242  $proj = new Project($db);
1243  $proj->fetch($object->fk_project);
1244  $morehtmlref .= ' : '.$proj->getNomUrl(1);
1245  if ($proj->title) {
1246  $morehtmlref .= ' - '.$proj->title;
1247  }
1248  } else {
1249  $morehtmlref .= '';
1250  }
1251  }
1252  }
1253  $morehtmlref .= '</div>';
1254 
1255  $morehtmlright = '';
1256 
1257  dol_banner_tab($object, 'ref', $linkback, 1, 'title', 'none', $morehtmlref, '', 0, '', $morehtmlright);
1258 
1259  print '<div class="fichecenter">';
1260  print '<div class="fichehalfleft">';
1261  print '<div class="underbanner clearboth"></div>';
1262 
1263  print '<table class="border centpercent tableforfield">';
1264 
1265  print '<tr><td class="titlefield">'.$langs->trans("Author").'</td><td>';
1266  print $author->getNomUrl(-1);
1267  print "</td></tr>";
1268 
1269  print '<tr><td>'.$langs->trans("AmountHT").'</td>';
1270  print '<td>'.price($object->total_ht, '', $langs, 1, -1, -1, $conf->currency).'</td>';
1271  print '</tr>';
1272 
1273  print '<tr><td>'.$langs->trans("AmountVAT").'</td><td>'.price($object->total_tva, '', $langs, 1, -1, -1, $conf->currency).'</td>';
1274  print '</tr>';
1275 
1276  // Amount Local Taxes
1277  if (($mysoc->localtax1_assuj == "1" && $mysoc->useLocalTax(1)) || $object->total_localtax1 != 0) { // Localtax1
1278  print '<tr><td>'.$langs->transcountry("AmountLT1", $mysoc->country_code).'</td>';
1279  print '<td class="nowrap">'.price($object->total_localtax1, 1, '', 1, - 1, - 1, $conf->currency).'</td></tr>';
1280  }
1281  if (($mysoc->localtax2_assuj == "1" && $mysoc->useLocalTax(2)) || $object->total_localtax2 != 0) { // Localtax2
1282  print '<tr><td>'.$langs->transcountry("AmountLT2", $mysoc->country_code).'</td>';
1283  print '<td class=nowrap">'.price($object->total_localtax2, 1, '', 1, - 1, - 1, $conf->currency).'</td></tr>';
1284  }
1285 
1286  print '<tr><td>'.$langs->trans("AmountTTC").'</td><td colspan="3">'.price($object->total_ttc, '', $langs, 1, -1, -1, $conf->currency).'</td>';
1287  print '</tr>';
1288 
1289 
1290  // Payment term
1291  print '<tr><td>';
1292  print '<table class="nobordernopadding centpercent"><tr><td>';
1293  print $langs->trans('PaymentConditionsShort');
1294  print '</td>';
1295  if ($action != 'editconditions' && $user->hasRight('facture', 'creer')) {
1296  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>';
1297  }
1298  print '</tr></table>';
1299  print '</td><td>';
1300  if ($object->type != Facture::TYPE_CREDIT_NOTE) {
1301  if ($action == 'editconditions') {
1302  $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->cond_reglement_id, 'cond_reglement_id');
1303  } else {
1304  $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->cond_reglement_id, 'none');
1305  }
1306  } else {
1307  print '&nbsp;';
1308  }
1309  print '</td></tr>';
1310 
1311  // Payment mode
1312  print '<tr><td>';
1313  print '<table class="nobordernopadding" width="100%"><tr><td>';
1314  print $langs->trans('PaymentMode');
1315  print '</td>';
1316  if ($action != 'editmode' && $user->hasRight('facture', 'creer')) {
1317  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>';
1318  }
1319  print '</tr></table>';
1320  print '</td><td>';
1321  if ($action == 'editmode') {
1322  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
1323  } else {
1324  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'none');
1325  }
1326  print '</td></tr>';
1327 
1328  // Multicurrency
1329  if (isModEnabled('multicurrency')) {
1330  // Multicurrency code
1331  print '<tr>';
1332  print '<td>';
1333  print '<table class="nobordernopadding" width="100%"><tr><td>';
1334  print $form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0);
1335  print '</td>';
1336  if ($usercancreate && $action != 'editmulticurrencycode' && !empty($object->brouillon)) {
1337  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>';
1338  }
1339  print '</tr></table>';
1340  print '</td><td>';
1341  $htmlname = (($usercancreate && $action == 'editmulticurrencycode') ? 'multicurrency_code' : 'none');
1342  $form->form_multicurrency_code($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_code, $htmlname);
1343  print '</td></tr>';
1344 
1345  // Multicurrency rate
1346  if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) {
1347  print '<tr>';
1348  print '<td>';
1349  print '<table class="nobordernopadding" width="100%"><tr><td>';
1350  print $form->editfieldkey('CurrencyRate', 'multicurrency_tx', '', $object, 0);
1351  print '</td>';
1352  if ($usercancreate && $action != 'editmulticurrencyrate' && !empty($object->brouillon) && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
1353  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>';
1354  }
1355  print '</tr></table>';
1356  print '</td><td>';
1357  if ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') {
1358  if ($action == 'actualizemulticurrencyrate') {
1359  list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
1360  }
1361  $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, ($usercancreate ? 'multicurrency_tx' : 'none'), $object->multicurrency_code);
1362  } else {
1363  $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
1364  if ($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
1365  print '<div class="inline-block"> &nbsp; &nbsp; &nbsp; &nbsp; ';
1366  print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=actualizemulticurrencyrate">'.$langs->trans("ActualizeCurrency").'</a>';
1367  print '</div>';
1368  }
1369  }
1370  print '</td></tr>';
1371  }
1372  }
1373 
1374  // Help of substitution key
1375  $dateexample = dol_now();
1376  if (!empty($object->frequency) && !empty($object->date_when)) {
1377  $dateexample = $object->date_when;
1378  }
1379 
1380  // Help of substitution key
1381  $substitutionarray = getCommonSubstitutionArray($langs, 2, null, $object);
1382 
1383  $substitutionarray['__INVOICE_PREVIOUS_MONTH__'] = $langs->trans("PreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%m').')';
1384  $substitutionarray['__INVOICE_MONTH__'] = $langs->trans("MonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%m').')';
1385  $substitutionarray['__INVOICE_NEXT_MONTH__'] = $langs->trans("NextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%m').')';
1386  $substitutionarray['__INVOICE_PREVIOUS_MONTH_TEXT__'] = $langs->trans("TextPreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%B').')';
1387  $substitutionarray['__INVOICE_MONTH_TEXT__'] = $langs->trans("TextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%B').')';
1388  $substitutionarray['__INVOICE_NEXT_MONTH_TEXT__'] = $langs->trans("TextNextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%B').')';
1389  $substitutionarray['__INVOICE_PREVIOUS_YEAR__'] = $langs->trans("PreviousYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'y'), '%Y').')';
1390  $substitutionarray['__INVOICE_YEAR__'] = $langs->trans("YearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%Y').')';
1391  $substitutionarray['__INVOICE_NEXT_YEAR__'] = $langs->trans("NextYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'y'), '%Y').')';
1392  // Only on template invoices
1393  $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').')';
1394  $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').')';
1395  $substitutionarray['__INVOICE_COUNTER_CURRENT__'] = $object->nb_gen_done;
1396  $substitutionarray['__INVOICE_COUNTER_MAX__'] = $object->nb_gen_max;
1397 
1398  $htmltext = '<i>'.$langs->trans("FollowingConstantsWillBeSubstituted").':<br>';
1399  foreach ($substitutionarray as $key => $val) {
1400  $htmltext .= $key.' = '.$langs->trans($val).'<br>';
1401  }
1402  $htmltext .= '</i>';
1403 
1404  // Note public
1405  print '<tr><td>';
1406  print $form->editfieldkey($form->textwithpicto($langs->trans('NotePublic'), $htmltext, 1, 'help', '', 0, 2, 'notepublic'), 'note_public', $object->note_public, $object, $user->hasRight('facture', 'creer'));
1407  print '</td><td class="wordbreak">';
1408  print $form->editfieldval($langs->trans("NotePublic"), 'note_public', $object->note_public, $object, $user->hasRight('facture', 'creer'), 'textarea:'.ROWS_4.':90%', '', null, null, '', 1);
1409  print '</td>';
1410  print '</tr>';
1411 
1412  // Note private
1413  print '<tr><td>';
1414  print $form->editfieldkey($form->textwithpicto($langs->trans("NotePrivate"), $htmltext, 1, 'help', '', 0, 2, 'noteprivate'), 'note_private', $object->note_private, $object, $user->hasRight('facture', 'creer'));
1415  print '</td><td class="wordbreak">';
1416  print $form->editfieldval($langs->trans("NotePrivate"), 'note_private', $object->note_private, $object, $user->hasRight('facture', 'creer'), 'textarea:'.ROWS_4.':90%', '', null, null, '', 1);
1417  print '</td>';
1418  print '</tr>';
1419 
1420  // Bank Account
1421  print '<tr><td class="nowrap">';
1422  print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
1423  print $langs->trans('BankAccount');
1424  print '<td>';
1425  if (($action != 'editbankaccount') && $user->hasRight('facture', 'creer') && $object->statut == FactureRec::STATUS_DRAFT) {
1426  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>';
1427  }
1428  print '</tr></table>';
1429  print '</td><td>';
1430  if ($action == 'editbankaccount') {
1431  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1);
1432  } else {
1433  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
1434  }
1435  print "</td>";
1436  print '</tr>';
1437 
1438  // Model pdf
1439  print '<tr><td class="nowrap">';
1440  print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
1441  print $langs->trans('Model');
1442  print '<td>';
1443  if (($action != 'editmodelpdf') && $user->hasRight('facture', 'creer') && $object->statut == FactureRec::STATUS_DRAFT) {
1444  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>';
1445  }
1446  print '</tr></table>';
1447  print '</td><td>';
1448  if ($action == 'editmodelpdf') {
1449  include_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php';
1450  $list = array();
1451  $models = ModelePDFFactures::liste_modeles($db);
1452  foreach ($models as $k => $model) {
1453  $list[] = str_replace(':', '|', $k).':'.$model;
1454  }
1455  $select = 'select;'.implode(',', $list);
1456  print $form->editfieldval($langs->trans("Model"), 'modelpdf', $object->model_pdf, $object, $user->hasRight('facture', 'creer'), $select);
1457  } else {
1458  print $object->model_pdf;
1459  }
1460  print "</td>";
1461  print '</tr>';
1462 
1463  // Other attributes
1464  $cols = 2;
1465  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1466 
1467  print '</table>';
1468 
1469  print '</div>';
1470  print '<div class="fichehalfright">';
1471  print '<div class="underbanner clearboth"></div>';
1472 
1473 
1474  /*
1475  * Recurrence
1476  */
1477  $title = $langs->trans("Recurrence");
1478  //print load_fiche_titre($title, '', 'calendar');
1479 
1480  print '<table class="border centpercent tableforfield">';
1481 
1482  print '<tr><td colspan="2">'.img_picto('', 'recurring', 'class="pictofixedwidth"').$title.'</td></tr>';
1483 
1484  // if "frequency" is empty or = 0, the reccurence is disabled
1485  print '<tr><td style="width: 50%">';
1486  print '<table class="nobordernopadding" width="100%"><tr><td>';
1487  print $langs->trans('Frequency');
1488  print '</td>';
1489  if ($action != 'editfrequency' && $user->hasRight('facture', 'creer')) {
1490  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>';
1491  }
1492  print '</tr></table>';
1493  print '</td><td>';
1494  if ($action == 'editfrequency') {
1495  print '<form method="post" action="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'">';
1496  print '<input type="hidden" name="action" value="setfrequency">';
1497  print '<input type="hidden" name="token" value="'.newToken().'">';
1498  print '<table class="nobordernopadding">';
1499  print '<tr><td>';
1500  print "<input type='text' name='frequency' value='".$object->frequency."' size='5' />&nbsp;";
1501  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'));
1502  print '</td>';
1503  print '<td class="left"><input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans("Modify").'"></td>';
1504  print '</tr></table></form>';
1505  } else {
1506  if ($object->frequency > 0) {
1507  print $langs->trans('FrequencyPer_'.$object->unit_frequency, $object->frequency);
1508  } else {
1509  print '<span class="opacitymedium">'.$langs->trans("NotARecurringInvoiceTemplate").'</span>';
1510  }
1511  }
1512  print '</td></tr>';
1513 
1514  // Date when (next invoice generation)
1515  print '<tr><td>';
1516  if ($action == 'date_when' || $object->frequency > 0) {
1517  print $form->editfieldkey($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->hasRight('facture', 'creer'), 'day');
1518  } else {
1519  print $langs->trans("NextDateToExecution");
1520  }
1521  print '</td><td>';
1522  if ($action == 'date_when' || $object->frequency > 0) {
1523  print $form->editfieldval($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->hasRight('facture', 'creer'), 'day', $object->date_when, null, '', '', 0, 'strikeIfMaxNbGenReached');
1524  }
1525  //var_dump(dol_print_date($object->date_when+60, 'dayhour').' - '.dol_print_date($now, 'dayhour'));
1526  if (!$object->isMaxNbGenReached()) {
1527  if (!$object->suspended && $action != 'editdate_when' && $object->frequency > 0 && $object->date_when && $object->date_when < $now) {
1528  print img_warning($langs->trans("Late"));
1529  }
1530  } else {
1531  print img_info($langs->trans("MaxNumberOfGenerationReached"));
1532  }
1533  print '</td>';
1534  print '</tr>';
1535 
1536  // Max period / Rest period
1537  print '<tr><td>';
1538  if ($action == 'nb_gen_max' || $object->frequency > 0) {
1539  print $form->editfieldkey($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max, $object, $user->hasRight('facture', 'creer'));
1540  } else {
1541  print $langs->trans("MaxPeriodNumber");
1542  }
1543  print '</td><td>';
1544  if ($action == 'nb_gen_max' || $object->frequency > 0) {
1545  print $form->editfieldval($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max ? $object->nb_gen_max : '', $object, $user->hasRight('facture', 'creer'));
1546  } else {
1547  print '';
1548  }
1549  print '</td>';
1550  print '</tr>';
1551 
1552  // Status of generated invoices
1553  print '<tr><td>';
1554  if ($action == 'auto_validate' || $object->frequency > 0) {
1555  print $form->editfieldkey($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $user->hasRight('facture', 'creer'));
1556  } else {
1557  print $langs->trans("StatusOfGeneratedInvoices");
1558  }
1559  print '</td><td>';
1560  $select = 'select;0:'.$langs->trans('BillStatusDraft').',1:'.$langs->trans('BillStatusValidated');
1561  if ($action == 'auto_validate' || $object->frequency > 0) {
1562  print $form->editfieldval($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $user->hasRight('facture', 'creer'), $select);
1563  }
1564  print '</td>';
1565  // Auto generate documents
1566  if (!empty($conf->global->INVOICE_REC_CAN_DISABLE_DOCUMENT_FILE_GENERATION)) {
1567  print '<tr>';
1568  print '<td>';
1569  if ($action == 'generate_pdf' || $object->frequency > 0) {
1570  print $form->editfieldkey($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', $object->generate_pdf, $object, $user->hasRight('facture', 'creer'));
1571  } else {
1572  print $langs->trans("StatusOfGeneratedDocuments");
1573  }
1574  print '</td>';
1575  print '<td>';
1576  $select = 'select;0:'.$langs->trans('DoNotGenerateDoc').',1:'.$langs->trans('AutogenerateDoc');
1577  if ($action == 'generate_pdf' || $object->frequency > 0) {
1578  print $form->editfieldval($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', $object->generate_pdf, $object, $user->hasRight('facture', 'creer'), $select);
1579  }
1580  print '</td>';
1581  print '</tr>';
1582  } else {
1583  print '<input type="hidden" name="generate_pdf" value="1">';
1584  }
1585 
1586  print '</table>';
1587 
1588  // Frequencry/Recurring section
1589  if ($object->frequency > 0) {
1590  print '<br>';
1591 
1592  if (!isModEnabled('cron')) {
1593  print info_admin($langs->trans("EnableAndSetupModuleCron", $langs->transnoentitiesnoconv("Module2300Name")));
1594  }
1595 
1596  print '<div class="underbanner clearboth"></div>';
1597  print '<table class="border centpercent tableforfield">';
1598 
1599  // Nb of generation already done
1600  print '<tr><td style="width: 50%">'.$langs->trans("NbOfGenerationDone").'</td>';
1601  print '<td>';
1602  print $object->nb_gen_done ? $object->nb_gen_done : '0';
1603  print '</td>';
1604  print '</tr>';
1605 
1606  // Date last
1607  print '<tr><td>';
1608  print $langs->trans("DateLastGeneration");
1609  print '</td><td>';
1610  print dol_print_date($object->date_last_gen, 'dayhour');
1611  print '</td>';
1612  print '</tr>';
1613 
1614  print '</table>';
1615 
1616  print '<br>';
1617  }
1618 
1619  print '</div>';
1620  print '</div>';
1621 
1622  print '<div class="clearboth"></div><br>';
1623 
1624 
1625  // Lines
1626  print '<form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline') ? '#add' : '#line_'.GETPOST('lineid', 'int')).'" method="POST">';
1627  print '<input type="hidden" name="token" value="' . newToken().'">';
1628  print '<input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">';
1629  print '<input type="hidden" name="mode" value="">';
1630  print '<input type="hidden" name="id" value="' . $object->id.'">';
1631  print '<input type="hidden" name="page_y" value="">';
1632 
1633  if (!empty($conf->use_javascript_ajax) && $object->statut == 0) {
1634  include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
1635  }
1636 
1637  print '<div class="div-table-responsive-no-min">';
1638  print '<table id="tablelines" class="noborder noshadow centpercent">';
1639  // Show object lines
1640  if (!empty($object->lines)) {
1641  $canchangeproduct = 1;
1642  $object->printObjectLines($action, $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice
1643  }
1644 
1645  // Form to add new line
1646  if ($object->statut == $object::STATUS_DRAFT && $user->hasRight('facture', 'creer') && $action != 'valid' && $action != 'editline') {
1647  if ($action != 'editline') {
1648  // Add free products/services
1649 
1650  $parameters = array();
1651  $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1652  if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1653  if (empty($reshook))
1654  $object->formAddObjectLine(0, $mysoc, $object->thirdparty); // No date selector for template invoice
1655  }
1656  }
1657 
1658  print "</table>\n";
1659  print '</div>';
1660 
1661  print "</form>\n";
1662 
1663  print dol_get_fiche_end();
1664 
1665 
1666  /*
1667  * Action bar
1668  */
1669  print '<div class="tabsAction">';
1670 
1671  $parameters = array();
1672  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1673  if (empty($reshook)) {
1674  $params = array(
1675  'attr' => array(
1676  'class' => 'classfortooltip',
1677  ),
1678  );
1679  if (empty($object->suspended)) {
1680  if ($user->hasRight('facture', 'creer')) {
1681  if (!empty($object->frequency) && $object->nb_gen_max > 0 && ($object->nb_gen_done >= $object->nb_gen_max)) {
1682  print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("MaxGenerationReached")) . '">' . $langs->trans("CreateBill") . '</a></div>';
1683  } else {
1684  if (empty($object->frequency) || $object->date_when <= $nowlasthour) {
1685  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>';
1686  } else {
1687  print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("DateIsNotEnough")) . '">' . $langs->trans("CreateBill") . '</a></div>';
1688  }
1689  }
1690  } else {
1691  print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#">' . $langs->trans("CreateBill") . '</a></div>';
1692  }
1693  }
1694 
1695  if ($user->hasRight('facture', 'creer')) {
1696  if (empty($object->suspended)) {
1697  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>';
1698  } else {
1699  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>';
1700  }
1701  }
1702 
1703  // Delete
1704  print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=delete&token=' . newToken(), 'delete', $user->hasRight('facture', 'supprimer'));
1705  }
1706  print '</div>';
1707 
1708 
1709 
1710  print '<div class="fichecenter"><div class="fichehalfleft">';
1711  print '<a name="builddoc"></a>'; // ancre
1712 
1713 
1714  // Show links to link elements
1715  $linktoelem = $form->showLinkToObjectBlock($object, null, array('invoice'));
1716 
1717  $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
1718 
1719 
1720  print '</div>';
1721  print '<div class="fichehalfright">';
1722 
1723  $MAXEVENT = 10;
1724 
1725  //$morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', dol_buildpath('/mymodule/myobject_agenda.php', 1).'?id='.$object->id);
1726 
1727  // List of actions on element
1728  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
1729  $formactions = new FormActions($db);
1730  $somethingshown = $formactions->showactions($object, $object->element, (is_object($object->thirdparty) ? $object->thirdparty->id : 0), 1, '', $MAXEVENT, '', $morehtmlcenter);
1731 
1732  print '</div>';
1733  print '</div>';
1734  }
1735 }
1736 
1737 // End of page
1738 llxFooter();
1739 $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:622
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.
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that returns whether VAT must be recoverable collected VAT (e.g.
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.
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.
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:921
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.