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