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