dolibarr 22.0.5
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-2025 Frédéric France <frederic.france@free.fr>
12 * Copyright (C) 2023 Nick Fragoulis
13 * Copyright (C) 2024-2025 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}
43require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
44require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
45require_once DOL_DOCUMENT_ROOT.'/core/lib/invoice.lib.php';
46require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
47
57// Load translation files required by the page
58$langs->loadLangs(array('bills', 'companies', 'compta', 'admin', 'other', 'products', 'banks'));
59
60$action = GETPOST('action', 'alpha');
61$massaction = GETPOST('massaction', 'alpha');
62$show_files = GETPOSTINT('show_files');
63$confirm = GETPOST('confirm', 'alpha');
64$cancel = GETPOST('cancel', 'alpha');
65$toselect = GETPOST('toselect', 'array');
66$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'invoicetemplatelist'; // To manage different context of search
67$backtopage = GETPOST('backtopage', 'alpha'); // if not set, a default page will be used
68$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); // if not set, $backtopage will be used
69
70
71$id = (GETPOSTINT('facid') ? GETPOSTINT('facid') : GETPOSTINT('id'));
72$lineid = GETPOSTINT('lineid');
73$ref = GETPOST('ref', 'alpha');
74$socid = 0;
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$permissiontoadd = $user->hasRight('facture', 'creer');
126$permissionnote = $user->hasRight('facture', 'creer'); // Used by the include of actions_setnotes.inc.php
127$permissiondellink = $user->hasRight('facture', 'creer'); // Used by the include of actions_dellink.inc.php
128$permissiontoedit = $user->hasRight('facture', 'creer'); // Used by the include of actions_lineupdonw.inc.php
129$permissiontoeditextra = $permissiontoadd;
130if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
131 // For action 'update_extras', is there a specific permission set for the attribute to update
132 $permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
133}
134
135$usercanread = $user->hasRight('facture', 'lire');
136$usercancreate = $user->hasRight('facture', 'creer');
137$usercanissuepayment = $user->hasRight('facture', 'paiement');
138$usercandelete = $user->hasRight('facture', 'supprimer');
139
140// Advanced permissions
141$usercanvalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $usercancreate) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('facture', 'invoice_advance', 'validate')));
142$usercansend = (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || $user->hasRight('facture', 'invoice_advance', 'send'));
143$usercanreopen = (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || $user->hasRight('facture', 'invoice_advance', 'reopen'));
144$usercanunvalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !empty($usercancreate)) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('facture', 'invoice_advance', 'unvalidate')));
145
146// Other permissions
147$usercanproductignorepricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !$user->hasRight('produit', 'ignore_price_min_advance')) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
148$usercancreatemargin = $user->hasRight("margins", "creer");
149$usercanreadallmargin = $user->hasRight("margins", "liretous");
150$usercancreatewithdrarequest = $user->hasRight("prelevement", "bons", "creer");
151
152$now = dol_now();
153
154$error = 0;
155
156// Security check
157$result = restrictedArea($user, 'facture', $object->id, $objecttype);
158
159
160/*
161 * Actions
162 */
163
164if (GETPOST('cancel', 'alpha')) {
165 if ($action != 'updateline') {
166 $action = 'list';
167 $massaction = '';
168 } else {
169 $action = '';
170 $cancel = '';
171 }
172}
173if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
174 $massaction = '';
175}
176
177$parameters = array('socid' => $socid);
178$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
179if ($reshook < 0) {
180 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
181}
182
183if (empty($reshook)) {
184 $backurlforlist = DOL_URL_ROOT.'/compta/facture/invoicetemplate_list.php';
185
186 if (empty($backtopage) || ($cancel && empty($id))) {
187 if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
188 if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
189 $backtopage = $backurlforlist;
190 } else {
191 $backtopage = DOL_URL_ROOT.'/compta/facture/invoicetemplate_list.php?id='.((!empty($id) && $id > 0) ? $id : '__ID__');
192 }
193 }
194 }
195
196 // include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php';
197 if ($cancel) {
198 /*var_dump($cancel);var_dump($backtopage);var_dump($backtopageforcancel);exit;*/
199 if (!empty($backtopageforcancel)) {
200 header("Location: ".$backtopageforcancel);
201 exit;
202 } elseif (!empty($backtopage)) {
203 header("Location: ".$backtopage);
204 exit;
205 }
206 $action = '';
207 }
208
209 // Selection of new fields
210 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
211
212 // Set note
213 include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be 'include', not 'include_once'
214
215 include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
216
217 include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; // Must be 'include', not 'include_once'
218
219 // Mass actions
220 /*$objectclass='MyObject';
221 $objectlabel='MyObject';
222 $uploaddir = $conf->mymodule->dir_output;
223 include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';*/
224
225 // Create predefined invoice
226 if ($action == 'add' && $usercancreate) {
227 if (!GETPOST('title', 'alphanohtml')) {
228 setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->trans("Title")), null, 'errors');
229 $action = "create";
230 $error++;
231 }
232
233 $frequency = GETPOSTINT('frequency');
234 $reyear = GETPOSTINT('reyear');
235 $remonth = GETPOSTINT('remonth');
236 $reday = GETPOSTINT('reday');
237 $rehour = GETPOSTINT('rehour');
238 $remin = GETPOSTINT('remin');
239 $nb_gen_max = GETPOSTINT('nb_gen_max');
240 //if (empty($nb_gen_max)) $nb_gen_max =0;
241
242 if (GETPOSTINT('frequency')) {
243 if (empty($reyear) || empty($remonth) || empty($reday)) {
244 setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->trans("Date")), null, 'errors');
245 $action = "create";
246 $error++;
247 }
248 /*if ($nb_gen_max === '') {
249 setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->trans("MaxPeriodNumber")), null, 'errors');
250 $action = "create";
251 $error++;
252 }*/
253 }
254
255 if (!$error) {
256 $object->subtype = GETPOSTINT('subtype');
257 $object->title = GETPOST('title', 'alphanohtml');
258
259 $object->note_private = GETPOST('note_private', 'restricthtml');
260 $object->note_public = GETPOST('note_public', 'restricthtml');
261 $object->model_pdf = GETPOST('modelpdf', 'alphanohtml');
262 $object->usenewprice = GETPOSTINT('usenewprice');
263
264 $object->mode_reglement_id = GETPOSTINT('mode_reglement_id');
265 $object->cond_reglement_id = GETPOSTINT('cond_reglement_id');
266 $object->fk_societe_rib = GETPOSTINT('accountcustomerid');
267 $object->rule_for_lines_dates = GETPOST('rule_for_lines_dates', 'alpha');
268
269 $object->frequency = $frequency;
270 $object->unit_frequency = GETPOST('unit_frequency', 'alpha');
271 $object->nb_gen_max = $nb_gen_max;
272 $object->auto_validate = GETPOSTINT('auto_validate');
273 $object->generate_pdf = GETPOSTINT('generate_pdf');
274 $object->fk_project = $projectid;
275
276 $date_next_execution = dol_mktime($rehour, $remin, 0, $remonth, $reday, $reyear);
277 $object->date_when = $date_next_execution;
278
279 $ret = $extrafields->setOptionalsFromPost(null, $object);
280 if ($ret < 0) {
281 setEventMessages($extrafields->error, $extrafields->errors, 'errors');
282 $error++;
283 }
284
285 // Get first contract linked to invoice (or order or proposal) used to generate template (facid is id of source invoice)
286 if (GETPOSTINT('facid') > 0) {
287 $srcObject = new Facture($db);
288 $srcObject->fetch(GETPOSTINT('facid'));
289
290 $srcObject->fetchObjectLinked();
291
292 if (!empty($srcObject->linkedObjectsIds['contrat'])) {
293 $contractidid = reset($srcObject->linkedObjectsIds['contrat']);
294
295 $object->origin_type = 'contrat';
296 $object->origin_id = $contractidid;
297 $object->linked_objects[$object->origin_type] = $object->origin_id;
298 } elseif (!empty($srcObject->linkedObjectsIds['commande'])) {
299 $orderid = reset($srcObject->linkedObjectsIds['commande']);
300
301 $object->linked_objects['commande'] = $orderid;
302 } elseif (!empty($srcObject->linkedObjectsIds['propal'])) {
303 $proposalid = reset($srcObject->linkedObjectsIds['propal']);
304
305 $object->linked_objects['commande'] = $proposalid;
306 }
307 }
308
309 $db->begin();
310
311 $oldinvoice = new Facture($db);
312 $oldinvoice->fetch(GETPOSTINT('facid'));
313
314 $onlylines = GETPOST('toselect', 'array');
315
316 $result = $object->create($user, $oldinvoice->id, 0, $onlylines);
317 if ($result > 0) {
318 $result = $oldinvoice->delete($user, 1);
319 if ($result < 0) {
320 $error++;
321 setEventMessages($oldinvoice->error, $oldinvoice->errors, 'errors');
322 $action = "create";
323 }
324 } else {
325 $error++;
326 setEventMessages($object->error, $object->errors, 'errors');
327 $action = "create";
328 }
329
330 if (!$error) {
331 $db->commit();
332
333 header("Location: ".$_SERVER['PHP_SELF'].'?facid='.$object->id);
334 exit;
335 } else {
336 $db->rollback();
337
338 $action = "create";
339 }
340 }
341 }
342
343 // Delete
344 if ($action == 'confirm_delete' && $confirm == 'yes' && $user->hasRight('facture', 'supprimer')) {
345 $object->delete($user);
346
347 header("Location: ".DOL_URL_ROOT.'/compta/facture/invoicetemplate_list.php');
348 exit;
349 }
350
351
352 // Update field
353 if ($action == 'setconditions' && $usercancreate) {
354 // Set condition
355 $object->context['actionmsg'] = $langs->trans("FieldXModified", $langs->transnoentitiesnoconv("PaymentTerm"));
356 $result = $object->setPaymentTerms(GETPOSTINT('cond_reglement_id'));
357 } elseif ($action == 'setmode' && $usercancreate) {
358 // Set mode
359 $object->context['actionmsg'] = $langs->trans("FieldXModified", $langs->transnoentitiesnoconv("PaymentMode"));
360 $object->setPaymentMethods(GETPOSTINT('mode_reglement_id'));
361 $object->setValueFrom('fk_societe_rib', 0);
362
363 //Need to reload to display bank customer account field
364 header("Location: ".$_SERVER['PHP_SELF'].'?facid='.$object->id);
365 exit;
366 } elseif ($action == 'classin' && $usercancreate) {
367 // Set project
368 $object->context['actionmsg'] = $langs->trans("FieldXModified", $langs->transnoentitiesnoconv("Project"));
369 $object->setProject(GETPOSTINT('projectid'));
370 } elseif ($action == 'setref' && $usercancreate) {
371 // Set bank account
372 $object->context['actionmsg'] = $langs->trans("FieldXModifiedFromYToZ", $langs->transnoentitiesnoconv("Title"), $object->title, $ref);
373 $result = $object->setValueFrom('titre', $ref, '', null, 'text', '', $user, 'BILLREC_MODIFY');
374 if ($result > 0) {
375 $object->title = $ref;
376 $object->ref = $object->title;
377 } else {
378 $error++;
379 if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
380 $langs->load("errors");
381 setEventMessages($langs->trans('ErrorRefAlreadyExists', $ref), null, 'errors');
382 } else {
383 setEventMessages($object->error, $object->errors, 'errors');
384 }
385 }
386 } elseif ($action == 'setbankaccount' && $usercancreate) {
387 // Set bank account
388 $object->context['actionmsg'] = $langs->trans("FieldXModified", $langs->transnoentitiesnoconv("Bank"));
389 $result = $object->setBankAccount(GETPOSTINT('fk_account'));
390 } elseif ($action == 'setbankaccountcustomer' && $usercancreate) {
391 // Set bank account customer
392 $object->context['actionmsg'] = $langs->trans("FieldXModified", $langs->transnoentitiesnoconv("DebitBankAccount"));
393 $fk_societe_rib = (GETPOSTINT('accountcustomerid') != "-1") ? GETPOSTINT('accountcustomerid') : 0;
394 $result = $object->setValueFrom('fk_societe_rib', $fk_societe_rib);
395 } elseif ($action == 'setfrequency' && $usercancreate) {
396 // Set frequency and unit frequency
397 $object->context['actionmsg'] = $langs->trans("FieldXModified", $langs->transnoentitiesnoconv("Frequency"));
398 $object->setFrequencyAndUnit(GETPOSTINT('frequency'), GETPOST('unit_frequency'));
399 } elseif ($action == 'setdate_when' && $usercancreate) {
400 // Set next date of execution
401 $date = dol_mktime(GETPOSTINT('date_whenhour'), GETPOSTINT('date_whenmin'), 0, GETPOSTINT('date_whenmonth'), GETPOSTINT('date_whenday'), GETPOSTINT('date_whenyear'));
402 if (!empty($date)) {
403 $object->setNextDate($date);
404 }
405 } elseif ($action == 'setnb_gen_max' && $usercancreate) {
406 // Set max period
407 $object->setMaxPeriod(GETPOSTINT('nb_gen_max'));
408 } elseif ($action == 'setauto_validate' && $usercancreate) {
409 // Set auto validate
410 $object->setAutoValidate(GETPOSTINT('auto_validate'));
411 } elseif ($action == 'setgenerate_pdf' && $usercancreate) {
412 // Set generate pdf
413 $object->setGeneratepdf(GETPOSTINT('generate_pdf'));
414 } elseif ($action == 'setmodelpdf' && $usercancreate) {
415 // Set model pdf
416 $object->setModelpdf(GETPOST('modelpdf', 'alpha'));
417 } elseif ($action == 'disable' && $usercancreate) {
418 // Set status disabled
419 $db->begin();
420
421 $object->context['actionmsg'] = $langs->trans("RecordDisabled");
422
423 $res = $object->setValueFrom('suspended', 1, '', null, 'text', '', $user, 'BILLREC_MODIFY');
424 if ($res <= 0) {
425 $error++;
426 }
427
428 if (!$error) {
429 $db->commit();
430 } else {
431 $db->rollback();
432 setEventMessages($object->error, $object->errors, 'errors');
433 }
434 } elseif ($action == 'enable' && $usercancreate) {
435 // Set status enabled
436 $db->begin();
437
438 $object->context['actionmsg'] = $langs->trans("RecordEnabled");
439
440 $res = $object->setValueFrom('suspended', 0, '', null, 'text', '', $user, 'BILLREC_MODIFY');
441 if ($res <= 0) {
442 $error++;
443 }
444
445 if (!$error) {
446 $db->commit();
447 } else {
448 $db->rollback();
449 setEventMessages($object->error, $object->errors, 'errors');
450 }
451 } elseif ($action == 'setmulticurrencycode' && $usercancreate) {
452 // Multicurrency Code
453 $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha'));
454 $object->fetch($object->id); // Reload all.
455 } elseif ($action == 'setmulticurrencyrate' && $usercancreate) {
456 // Multicurrency rate
457 $result = $object->setMulticurrencyRate(GETPOSTFLOAT('multicurrency_tx'), GETPOSTINT('calculation_mode'));
458 $object->fetch($object->id); // Reload all.
459 } elseif ($action == 'setruleforlinesdates' && $usercancreate) {
460 $object->context['actionmsg'] = $langs->trans("FieldXModified", $langs->transnoentitiesnoconv("RuleForLinesDates"));
461 $ruleForLinesDates = GETPOSTISSET('rule_for_lines_dates') ? GETPOST('rule_for_lines_dates', 'alpha') : 'prepaid';
462 $object->setValueFrom('rule_for_lines_dates', $ruleForLinesDates);
463 }
464
465 // Delete line
466 if ($action == 'confirm_deleteline' && $confirm == 'yes' && $usercancreate) {
467 $object->fetch($id);
468 $object->fetch_thirdparty();
469
470 $db->begin();
471
472 $line = new FactureLigneRec($db);
473
474 // For triggers
475 $line->id = $lineid;
476
477 if ($line->delete($user) > 0) {
478 $result = $object->update_price(1);
479
480 if ($result > 0) {
481 $db->commit();
482 $object->fetch($object->id); // Reload lines
483 } else {
484 $db->rollback();
485 setEventMessages($db->lasterror(), null, 'errors');
486 }
487 } else {
488 $db->rollback();
489 setEventMessages($line->error, $line->errors, 'errors');
490 }
491 } elseif ($action == 'confirm_delete_subtotalline' && $confirm == 'yes' && $usercancreate) {
492 // Delete line
493 $object->fetch($id);
494 $object->fetch_thirdparty();
495
496 $result = $object->deleteSubtotalLine($langs, GETPOSTINT('lineid'), (bool) GETPOST('deletecorrespondingsubtotalline'), $user);
497 if ($result > 0) {
498 $result = $object->update_price(1);
499
500 if ($result > 0) {
501 $db->commit();
502 $object->fetch($object->id); // Reload lines
503 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$id);
504 exit();
505 } else {
506 $db->rollback();
507 setEventMessages($db->lasterror(), null, 'errors');
508 }
509 } else {
510 setEventMessages($object->error, $object->errors, 'errors');
511 $action = '';
512 }
513 } elseif ($action == 'update_extras' && $permissiontoeditextra) {
514 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
515
516 $attribute_name = GETPOST('attribute', 'aZ09');
517
518 // Fill array 'array_options' with data from update form
519 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
520 if ($ret < 0) {
521 $error++;
522 }
523
524 if (!$error) {
525 $result = $object->updateExtraField($attribute_name, 'BILLREC_MODIFY');
526 if ($result < 0) {
527 setEventMessages($object->error, $object->errors, 'errors');
528 $error++;
529 }
530 }
531
532 if ($error) {
533 $action = 'edit_extras';
534 }
535 }
536
537 // Add a new line
538 if ($action == 'addline' && $usercancreate) {
539 $langs->load('errors');
540 $error = 0;
541
542 // Set if we used free entry or predefined product
543 $predef = '';
544 $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
545 $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
546 $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU', 2);
547 $prod_entry_mode = GETPOST('prod_entry_mode', 'alpha');
548 if ($prod_entry_mode == 'free') {
549 $idprod = 0;
550 } else {
551 $idprod = GETPOSTINT('idprod');
552
553 if (getDolGlobalString('MAIN_DISABLE_FREE_LINES') && $idprod <= 0) {
554 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")), null, 'errors');
555 $error++;
556 }
557 }
558
559 $tva_tx = (GETPOST('tva_tx', 'alpha') ? GETPOST('tva_tx', 'alpha') : 0);
560
561 $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS', 2);
562 $remise_percent = price2num(GETPOST('remise_percent'.$predef), '', 2);
563 if (empty($remise_percent)) {
564 $remise_percent = 0;
565 }
566
567 // Extrafields
568 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
569 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
570 // Unset extrafield
571 if (is_array($extralabelsline)) {
572 // Get extra fields
573 foreach ($extralabelsline as $key => $value) {
574 unset($_POST["options_".$key.$predef]);
575 }
576 }
577
578 if ((empty($idprod) || $idprod < 0) && ($price_ht < 0) && ((float) $qty < 0)) {
579 setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), null, 'errors');
580 $error++;
581 }
582 if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && GETPOST('type') < 0) {
583 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
584 $error++;
585 }
586 if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && (!($price_ht >= 0) || $price_ht == '')) { // Unit price can be 0 but not ''
587 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
588 $error++;
589 }
590 if ($qty == '') {
591 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
592 $error++;
593 }
594 if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && empty($product_desc)) {
595 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
596 $error++;
597 }
598 if ($qty < 0) {
599 $langs->load("errors");
600 setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
601 $error++;
602 }
603
604 if (!$error && ($qty >= 0) && (!empty($product_desc) || (!empty($idprod) && $idprod > 0))) {
605 $ret = $object->fetch($id);
606 if ($ret < 0) {
607 dol_print_error($db, $object->error);
608 exit();
609 }
610 $ret = $object->fetch_thirdparty();
611
612 // Clean parameters
613 $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'));
614 $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'));
615 $price_base_type = (GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT');
616 $tva_npr = "";
617
618 // Define special_code for special lines
619 $special_code = 0;
620 // if (!GETPOST('qty')) $special_code=3; // Options should not exists on invoices
621
622 // Ecrase $pu par celui du produit
623 // Ecrase $desc par celui du produit
624 // Ecrase $base_price_type par celui du produit
625 // Replaces $fk_unit with the product's
626 if (!empty($idprod) && $idprod > 0) {
627 $prod = new Product($db);
628 $prod->fetch($idprod);
629
630 $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
631
632 // Update if prices fields are defined
633 //$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
634 //$tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
635 //if (empty($tva_tx)) {
636 // $tva_npr = 0;
637 //}
638
639 // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
640 $pqp = (GETPOSTINT('pbq') ? GETPOSTINT('pbq') : 0);
641
642 $datapriceofproduct = $prod->getSellPrice($mysoc, $object->thirdparty, $pqp);
643
644 $pu_ht = $datapriceofproduct['pu_ht'];
645 $pu_ttc = $datapriceofproduct['pu_ttc'];
646 $price_min = $datapriceofproduct['price_min'];
647 $price_base_type = empty($datapriceofproduct['price_base_type']) ? 'HT' : $datapriceofproduct['price_base_type'];
648 //$tva_tx = $datapriceofproduct['tva_tx'];
649 //$tva_npr = $datapriceofproduct['tva_npr'];
650
651 $tmpvat = (float) price2num(preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx));
652 $tmpprodvat = price2num(preg_replace('/\s*\‍(.*\‍)/', '', (string) $prod->tva_tx));
653
654 // if price ht was forced (ie: from gui when calculated by margin rate and cost price). TODO Why this ?
655 if (!empty($price_ht)) {
656 $pu_ht = price2num($price_ht, 'MU');
657 $pu_ttc = price2num((float) $pu_ht * (1 + ($tmpvat / 100)), 'MU');
658 } elseif ($tmpvat != $tmpprodvat) {
659 // On reevalue prix selon taux tva car taux tva transaction peut etre different
660 // de ceux du produit par default (par example si pays different entre vendeur et acheteur).
661 if ($price_base_type != 'HT') {
662 $pu_ht = price2num((float) $pu_ttc / (1 + ($tmpvat / 100)), 'MU');
663 } else {
664 $pu_ttc = price2num((float) $pu_ht * (1 + ($tmpvat / 100)), 'MU');
665 }
666 }
667
668 $outputlangs = $langs;
669 $newlang = '';
670 $desc = '';
671
672 // Define output language
673 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
674 if (/* empty($newlang) && */ GETPOST('lang_id', 'aZ09')) {
675 $newlang = GETPOST('lang_id', 'aZ09');
676 }
677 if (empty($newlang)) {
678 $newlang = $object->thirdparty->default_lang;
679 }
680 if (!empty($newlang)) {
681 $outputlangs = new Translate("", $conf);
682 $outputlangs->setDefaultLang($newlang);
683 $outputlangs->load('products');
684 }
685
686 $desc = (!empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
687 } else {
688 $desc = $prod->description;
689 }
690
691 $desc = dol_concatdesc($desc, $product_desc);
692
693 // Add custom code and origin country into description
694 if (!getDolGlobalString('MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE') && (!empty($prod->customcode) || !empty($prod->country_code))) {
695 $tmptxt = '(';
696 // Define output language
697 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
698 if (!empty($prod->customcode)) {
699 $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomsCode").': '.$prod->customcode;
700 }
701 if (!empty($prod->customcode) && !empty($prod->country_code)) {
702 $tmptxt .= ' - ';
703 }
704 if (!empty($prod->country_code)) {
705 $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, '', $db, $outputlangs, 0);
706 }
707 } else {
708 if (!empty($prod->customcode)) {
709 $tmptxt .= $langs->transnoentitiesnoconv("CustomsCode").': '.$prod->customcode;
710 }
711 if (!empty($prod->customcode) && !empty($prod->country_code)) {
712 $tmptxt .= ' - ';
713 }
714 if (!empty($prod->country_code)) {
715 $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, '', $db, $langs, 0);
716 }
717 }
718 $tmptxt .= ')';
719 $desc = dol_concatdesc($desc, $tmptxt);
720 }
721
722 $type = $prod->type;
723 $fk_unit = $prod->fk_unit;
724 } else {
725 $pu_ht = price2num($price_ht, 'MU');
726 $pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
727 $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
728 $tva_tx = str_replace('*', '', $tva_tx);
729 if (empty($tva_tx)) {
730 $tva_npr = 0;
731 }
732 $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
733 $desc = $product_desc;
734 $type = GETPOST('type');
735 $fk_unit = GETPOSTINT('units');
736 }
737
738 $date_start_fill = GETPOSTINT('date_start_fill');
739 $date_end_fill = GETPOSTINT('date_end_fill');
740
741 // Margin
742 $fournprice = (int) (GETPOST('fournprice'.$predef) ? GETPOST('fournprice'.$predef) : ''); // This can be id of supplier price, or 'pmpprice' or 'costprice', or 'inputprice', we force to keep ID only
743 $buyingprice = price2num(GETPOST('buying_price'.$predef) != '' ? GETPOST('buying_price'.$predef) : ''); // If buying_price is '0', we must keep this value
744
745 // Local Taxes
746 $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $mysoc, $tva_npr);
747 $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $mysoc, $tva_npr);
748
749 $info_bits = 0;
750 if ($tva_npr) {
751 $info_bits |= 0x01;
752 }
753
754 $fk_parent_line = GETPOSTINT('fk_parent_line');
755
756 if ($usercanproductignorepricemin && (!empty($price_min) && ((float) price2num($pu_ht) * (1 - (float) price2num($remise_percent) / 100) < (float) price2num($price_min)))) {
757 $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
758 setEventMessages($mesg, null, 'errors');
759 } else {
760 // Insert line
761 $result = $object->addline($desc, $pu_ht, (float) $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $price_base_type, $info_bits, 0, $pu_ttc, $type, -1, $special_code, $label, (int) $fk_unit, 0, $date_start_fill, $date_end_fill, (int) $fournprice, $buyingprice, $fk_parent_line);
762
763 if ($result > 0) {
764 // Define output language and generate document
765 /*if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
766 {
767 // Define output language
768 $outputlangs = $langs;
769 $newlang = '';
770 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
771 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) $newlang = $object->thirdparty->default_lang;
772 if (!empty($newlang)) {
773 $outputlangs = new Translate("", $conf);
774 $outputlangs->setDefaultLang($newlang);
775 }
776 $model=$object->model_pdf;
777 $ret = $object->fetch($id); // Reload to get new records
778
779 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
780 if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
781 }*/
782 $object->fetch($object->id); // Reload lines
783
784 unset($_POST['prod_entry_mode']);
785
786 unset($_POST['qty']);
787 unset($_POST['type']);
788 unset($_POST['remise_percent']);
789 unset($_POST['price_ht']);
790 unset($_POST['multicurrency_price_ht']);
791 unset($_POST['price_ttc']);
792 unset($_POST['tva_tx']);
793 unset($_POST['product_ref']);
794 unset($_POST['product_label']);
795 unset($_POST['product_desc']);
796 unset($_POST['fournprice']);
797 unset($_POST['buying_price']);
798 unset($_POST['np_marginRate']);
799 unset($_POST['np_markRate']);
800 unset($_POST['dp_desc']);
801 unset($_POST['idprod']);
802 unset($_POST['units']);
803
804 unset($_POST['date_starthour']);
805 unset($_POST['date_startmin']);
806 unset($_POST['date_startsec']);
807 unset($_POST['date_startday']);
808 unset($_POST['date_startmonth']);
809 unset($_POST['date_startyear']);
810 unset($_POST['date_endhour']);
811 unset($_POST['date_endmin']);
812 unset($_POST['date_endsec']);
813 unset($_POST['date_endday']);
814 unset($_POST['date_endmonth']);
815 unset($_POST['date_endyear']);
816
817 unset($_POST['date_start_fill']);
818 unset($_POST['date_end_fill']);
819
820 unset($_POST['situations']);
821 unset($_POST['progress']);
822 } else {
823 setEventMessages($object->error, $object->errors, 'errors');
824 }
825
826 $action = '';
827 }
828 }
829 } elseif ($action == 'confirm_addtitleline' && $usercancreate) {
830 // Handling adding a new title line for subtotals module
831
832 $langs->load('subtotals');
833
834 $desc = GETPOST('subtotallinedesc', 'alphanohtml');
835 $depth = GETPOSTINT('subtotallinelevel') ?? 1;
836
837 $subtotal_options = array();
838
839 foreach (FactureRec::$TITLE_OPTIONS as $option) {
840 $value = GETPOST($option, 'alphanohtml');
841 if ($value) {
842 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
843 }
844 }
845
846 // Insert line
847 $result = $object->addSubtotalLine($langs, $desc, (int) $depth, $subtotal_options);
848
849 if ($result >= 0) {
850 if ($result == 0) {
851 setEventMessages($object->error, $object->errors, 'warnings');
852 }
853 $ret = $object->fetch($object->id); // Reload to get new records
854 $object->fetch_thirdparty();
855 } else {
856 setEventMessages($object->error, $object->errors, 'errors');
857 }
858 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$id);
859 exit();
860 } elseif ($action == 'confirm_addsubtotalline' && $usercancreate) {
861 // Handling adding a new subtotal line for subtotals module
862
863 $langs->load('subtotals');
864
865 $choosen_line = GETPOST('subtotaltitleline', 'alphanohtml');
866 foreach ($object->lines as $line) {
867 if ($line->desc == $choosen_line && $line->special_code == SUBTOTALS_SPECIAL_CODE) {
868 $desc = $line->desc;
869 $depth = -$line->qty;
870 }
871 }
872
873 $subtotal_options = array();
874
875 foreach (FactureRec::$SUBTOTAL_OPTIONS as $option) {
876 $value = GETPOST($option, 'alphanohtml');
877 if ($value) {
878 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
879 }
880 }
881
882 // Insert line
883 if (isset($desc) && isset($depth)) {
884 $result = $object->addSubtotalLine($langs, $desc, (int) $depth, $subtotal_options);
885 } else {
886 $object->errors[] = $langs->trans("CorrespondingTitleNotFound");
887 }
888
889 if (isset($result) && $result >= 0) {
890 $ret = $object->fetch($object->id); // Reload to get new records
891 $object->fetch_thirdparty();
892 } else {
893 setEventMessages($object->error, $object->errors, 'errors');
894 }
895 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$id);
896 exit();
897 } elseif ($action == 'updateline' && $usercancreate && !GETPOST('cancel', 'alpha')) {
898 if (!$object->fetch($id) > 0) {
899 dol_print_error($db);
900 }
901 $object->fetch_thirdparty();
902
903 // Clean parameters
904 $date_start = '';
905 $date_end = '';
906 //$date_start = dol_mktime(GETPOSTINT('date_starthour'), GETPOSTINT('date_startmin'), GETPOSTINT('date_startsec'), GETPOSTINT('date_startmonth'), GETPOSTINT('date_startday'), GETPOSTINT('date_startyear'));
907 //$date_end = dol_mktime(GETPOSTINT('date_endhour'), GETPOSTINT('date_endmin'), GETPOSTINT('date_endsec'), GETPOSTINT('date_endmonth'), GETPOSTINT('date_endday'), GETPOSTINT('date_endyear'));
908 $description = dol_htmlcleanlastbr(GETPOST('product_desc', 'restricthtml') ? GETPOST('product_desc', 'restricthtml') : GETPOST('desc', 'restricthtml'));
909 $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
910
911 $pu_ht = price2num(GETPOST('price_ht'), '', 2);
912 $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), '', 2);
913
914 $qty = (float) price2num(GETPOST('qty', 'alpha'), 'MS');
915
916 // Define info_bits
917 $info_bits = 0;
918 if (preg_match('/\*/', $vat_rate)) {
919 $info_bits |= 0x01;
920 }
921
922 // Define vat_rate
923 $vat_rate = str_replace('*', '', $vat_rate);
924 $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty);
925 $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty);
926
927 // Add buying price
928 $fournprice = (int) (GETPOST('fournprice') ? GETPOST('fournprice') : '');
929 $buyingprice = price2num(GETPOST('buying_price') != '' ? GETPOST('buying_price') : ''); // If buying_price is '0', we must keep this value
930
931 // Extrafields
932 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
933 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
934
935 $objectline = new FactureLigneRec($db);
936 if ($objectline->fetch(GETPOSTINT('lineid'))) {
937 $objectline->array_options = $array_options;
938 $result = $objectline->insertExtraFields();
939 if ($result < 0) {
940 setEventMessages($langs->trans('Error').$result, null, 'errors');
941 }
942 }
943
944 $position = ($objectline->rang >= 0 ? $objectline->rang : 0);
945
946 // Unset extrafield
947 if (is_array($extralabelsline)) {
948 // Get extra fields
949 foreach ($extralabelsline as $key => $value) {
950 unset($_POST["options_".$key]);
951 }
952 }
953
954 // Define special_code for special lines
955 $special_code = GETPOSTINT('special_code');
956 if ($special_code == 3) {
957 $special_code = 0; // Options should not exists on invoices
958 }
959
960 /*$line = new FactureLigne($db);
961 $line->fetch(GETPOST('lineid', 'int'));
962 $percent = $line->get_prev_progress($object->id);
963
964 if (GETPOST('progress') < $percent)
965 {
966 $mesg = '<div class="warning">' . $langs->trans("CantBeLessThanMinPercent") . '</div>';
967 setEventMessages($mesg, null, 'warnings');
968 $error++;
969 $result = -1;
970 }*/
971
972 $remise_percent = price2num(GETPOST('remise_percent'), '', 2);
973 if (empty($remise_percent)) {
974 $remise_percent = 0;
975 }
976
977 // Check minimum price
978 $productid = GETPOSTINT('productid');
979 if (!empty($productid)) {
980 $product = new Product($db);
981 $product->fetch($productid);
982
983 $type = $product->type;
984
985 $price_min = $product->price_min;
986 if (getDolGlobalString('PRODUIT_MULTIPRICES') && !empty($object->thirdparty->price_level)) {
987 $price_min = $product->multiprices_min[$object->thirdparty->price_level];
988 }
989
990 $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : '');
991
992 $typeinvoice = Facture::TYPE_STANDARD;
993
994 // Check price is not lower than minimum (check is done only for standard or replacement invoices)
995 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)))) {
996 setEventMessages($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)), null, 'errors');
997 $error++;
998 }
999 } else {
1000 $type = GETPOSTINT('type');
1001 $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
1002
1003 // Check parameters
1004 if (GETPOSTINT('type') < 0) {
1005 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
1006 $error++;
1007 }
1008 }
1009 if ($qty < 0) {
1010 $langs->load("errors");
1011 setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
1012 $error++;
1013 }
1014
1015 $date_start_fill = GETPOSTINT('date_start_fill');
1016 $date_end_fill = GETPOSTINT('date_end_fill');
1017 $fk_parent_line = GETPOST('fk_parent_line', 'int');
1018
1019 // Update line
1020 if (!$error) {
1021 $result = $object->updateline(
1022 GETPOSTINT('lineid'),
1023 $description,
1024 (float) $pu_ht,
1025 (float) $qty,
1026 (float) $vat_rate,
1027 $localtax1_rate,
1028 $localtax1_rate,
1029 GETPOSTINT('productid'),
1030 $remise_percent,
1031 'HT',
1032 $info_bits,
1033 0,
1034 0,
1035 $type,
1036 $position,
1037 $special_code,
1038 $label,
1039 GETPOSTINT('units'),
1040 (float) $pu_ht_devise,
1041 0,
1042 $date_start_fill,
1043 $date_end_fill,
1044 (int) $fournprice,
1045 (float) $buyingprice,
1046 (int) $fk_parent_line
1047 );
1048
1049 if ($result >= 0) {
1050 /*if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
1051 // Define output language
1052 $outputlangs = $langs;
1053 $newlang = '';
1054 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id','aZ09'))
1055 $newlang = GETPOST('lang_id','aZ09');
1056 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang))
1057 $newlang = $object->thirdparty->default_lang;
1058 if (!empty($newlang)) {
1059 $outputlangs = new Translate("", $conf);
1060 $outputlangs->setDefaultLang($newlang);
1061 }
1062
1063 $ret = $object->fetch($id); // Reload to get new records
1064 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1065 }*/
1066
1067 $object->fetch($object->id); // Reload lines
1068
1069 unset($_POST['qty']);
1070 unset($_POST['type']);
1071 unset($_POST['productid']);
1072 unset($_POST['remise_percent']);
1073 unset($_POST['price_ht']);
1074 unset($_POST['multicurrency_price_ht']);
1075 unset($_POST['price_ttc']);
1076 unset($_POST['tva_tx']);
1077 unset($_POST['product_ref']);
1078 unset($_POST['product_label']);
1079 unset($_POST['product_desc']);
1080 unset($_POST['fournprice']);
1081 unset($_POST['buying_price']);
1082 unset($_POST['np_marginRate']);
1083 unset($_POST['np_markRate']);
1084
1085 unset($_POST['dp_desc']);
1086 unset($_POST['idprod']);
1087 unset($_POST['units']);
1088
1089 unset($_POST['date_starthour']);
1090 unset($_POST['date_startmin']);
1091 unset($_POST['date_startsec']);
1092 unset($_POST['date_startday']);
1093 unset($_POST['date_startmonth']);
1094 unset($_POST['date_startyear']);
1095 unset($_POST['date_endhour']);
1096 unset($_POST['date_endmin']);
1097 unset($_POST['date_endsec']);
1098 unset($_POST['date_endday']);
1099 unset($_POST['date_endmonth']);
1100 unset($_POST['date_endyear']);
1101
1102 unset($_POST['situations']);
1103 unset($_POST['progress']);
1104 } else {
1105 setEventMessages($object->error, $object->errors, 'errors');
1106 }
1107 }
1108 } elseif ($action == 'updatetitleline' && GETPOSTISSET("save") && $usercancreate && !GETPOST('cancel', 'alpha')) {
1109 // Handling updating a title line for subtotals module
1110
1111 $langs->load('subtotals');
1112
1113 $desc = GETPOST('line_desc', 'alphanohtml') ?? $langs->trans("Title");
1114 $depth = GETPOSTINT('line_depth') ?? 1;
1115
1116 $subtotal_options = array();
1117
1118 foreach (Facture::$TITLE_OPTIONS as $option) {
1119 $value = GETPOST($option, 'alphanohtml');
1120 if ($value) {
1121 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
1122 }
1123 }
1124
1125 // Update line
1126 $result = $object->updateSubtotalLine($langs, GETPOSTINT('lineid'), $desc, $depth, $subtotal_options);
1127
1128 if ($result >= 0) {
1129 if ($result == 0) {
1130 setEventMessages($object->error, $object->errors, 'warnings');
1131 }
1132 $ret = $object->fetch($object->id); // Reload to get new records
1133 $object->fetch_thirdparty();
1134 } else {
1135 setEventMessages($object->error, $object->errors, 'errors');
1136 }
1137 } elseif ($action == 'updatesubtotalline' && GETPOSTISSET("save") && $usercancreate && !GETPOST('cancel', 'alpha')) {
1138 // Handling updating a subtotal line for subtotals module
1139
1140 $langs->load('subtotals');
1141
1142 $desc = GETPOST('line_desc', 'alphanohtml');
1143 $depth = GETPOSTINT('line_depth');
1144
1145 $subtotal_options = array();
1146
1147 foreach (Facture::$SUBTOTAL_OPTIONS as $option) {
1148 $value = GETPOST($option, 'alphanohtml');
1149 if ($value) {
1150 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
1151 }
1152 }
1153
1154 // Update line
1155 $result = $object->updateSubtotalLine($langs, GETPOSTINT('lineid'), $desc, $depth, $subtotal_options);
1156
1157 if ($result > 0) {
1158 $ret = $object->fetch($object->id); // Reload to get new records
1159 $object->fetch_thirdparty();
1160 } else {
1161 setEventMessages($object->error, $object->errors, 'errors');
1162 }
1163 }
1164}
1165
1166
1167/*
1168 * View
1169 */
1170
1171$title = $object->ref." - ".$langs->trans('Card');
1172$help_url = '';
1173
1174llxHeader('', $title, $help_url);
1175
1176$form = new Form($db);
1177$formother = new FormOther($db);
1178if (isModEnabled('project')) {
1179 $formproject = new FormProjets($db);
1180} else {
1181 $formproject = null;
1182}
1183$companystatic = new Societe($db);
1184$invoicerectmp = new FactureRec($db);
1185
1186$now = dol_now();
1187$nowlasthour = dol_get_last_hour($now);
1188
1189
1190// Create mode
1191if ($action == 'create') {
1192 print load_fiche_titre($langs->trans("CreateRepeatableInvoice"), '', 'bill');
1193
1194 $sourceInvoice = new Facture($db); // Source invoice
1195 $factureRec = new FactureRec($db);
1196 $product_static = new Product($db);
1197
1198 if ($sourceInvoice->fetch($id, $ref) > 0) {
1199 $result = $sourceInvoice->getLinesArray();
1200
1201 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1202 print '<input type="hidden" name="token" value="'.newToken().'">';
1203 print '<input type="hidden" name="action" value="add">';
1204 print '<input type="hidden" name="facid" value="'.$sourceInvoice->id.'">';
1205
1206
1207 print dol_get_fiche_head([], '', '', 0);
1208
1209 $rowspan = 4;
1210 if (isModEnabled('project')) {
1211 $rowspan++;
1212 }
1213 if ($sourceInvoice->fk_account > 0) {
1214 $rowspan++;
1215 }
1216
1217 print '<table class="border centpercent">';
1218
1219 $sourceInvoice->fetch_thirdparty();
1220
1221 // Title
1222 print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Title").'</td><td>';
1223 print '<input class="flat quatrevingtpercent" type="text" name="title" value="'.dol_escape_htmltag(GETPOST("title", 'alphanohtml')).'" autofocus>';
1224 print '</td></tr>';
1225
1226 // Third party
1227 print '<tr><td class="titlefieldcreate">'.$langs->trans("Customer").'</td><td>'.$sourceInvoice->thirdparty->getNomUrl(1, 'customer').'</td>';
1228 print '</tr>';
1229
1230 // Invoice subtype
1231 if (getDolGlobalInt('INVOICE_SUBTYPE_ENABLED')) {
1232 print "<tr><td>".$langs->trans("InvoiceSubtype")."</td><td>";
1233 print $form->getSelectInvoiceSubtype(GETPOSTISSET('subtype') ? GETPOST('subtype') : $sourceInvoice->subtype, 'subtype', 0, 0, '');
1234 print "</td></tr>";
1235 }
1236
1237 $note_public = GETPOSTISSET('note_public') ? GETPOST('note_public', 'restricthtml') : $sourceInvoice->note_public;
1238 $note_private = GETPOSTISSET('note_private') ? GETPOST('note_private', 'restricthtml') : $sourceInvoice->note_private;
1239
1240 // Help of substitution key
1241 $substitutionarray = getCommonSubstitutionArray($langs, 2, null, $sourceInvoice);
1242
1243 $substitutionarray['__INVOICE_PREVIOUS_MONTH__'] = $langs->trans("PreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, -1, 'm'), '%m').')';
1244 $substitutionarray['__INVOICE_MONTH__'] = $langs->trans("MonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($sourceInvoice->date, '%m').')';
1245 $substitutionarray['__INVOICE_NEXT_MONTH__'] = $langs->trans("NextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, 1, 'm'), '%m').')';
1246 $substitutionarray['__INVOICE_PREVIOUS_MONTH_TEXT__'] = $langs->trans("TextPreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, -1, 'm'), '%B').')';
1247 $substitutionarray['__INVOICE_MONTH_TEXT__'] = $langs->trans("TextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($sourceInvoice->date, '%B').')';
1248 $substitutionarray['__INVOICE_NEXT_MONTH_TEXT__'] = $langs->trans("TextNextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, 1, 'm'), '%B').')';
1249 $substitutionarray['__INVOICE_PREVIOUS_YEAR__'] = $langs->trans("PreviousYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, -1, 'y'), '%Y').')';
1250 $substitutionarray['__INVOICE_YEAR__'] = $langs->trans("YearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($sourceInvoice->date, '%Y').')';
1251 $substitutionarray['__INVOICE_NEXT_YEAR__'] = $langs->trans("NextYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, 1, 'y'), '%Y').')';
1252 // Only on template invoices
1253 $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_BEFORE_GEN__'] = $langs->trans("DateNextInvoiceBeforeGen").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, 1, 'm'), 'dayhour').')';
1254 $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_AFTER_GEN__'] = $langs->trans("DateNextInvoiceAfterGen").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, 2, 'm'), 'dayhour').')';
1255 $substitutionarray['__INVOICE_COUNTER_CURRENT__'] = $langs->trans("Count");
1256 $substitutionarray['__INVOICE_COUNTER_MAX__'] = $langs->trans("MaxPeriodNumber");
1257
1258 $htmltext = '<i>'.$langs->trans("FollowingConstantsWillBeSubstituted").':<br>';
1259 foreach ($substitutionarray as $key => $val) {
1260 $htmltext .= $key.' = '.$langs->trans($val).'<br>';
1261 }
1262 $htmltext .= '</i>';
1263
1264 // Author
1265 print "<tr><td>".$langs->trans("Author")."</td><td>".$user->getFullName($langs)."</td></tr>";
1266
1267 // Payment term
1268 print "<tr><td>".$langs->trans("PaymentConditions")."</td><td>";
1269 print $form->getSelectConditionsPaiements(GETPOSTISSET('cond_reglement_id') ? GETPOSTINT('cond_reglement_id') : $sourceInvoice->cond_reglement_id, 'cond_reglement_id', -1, 0, 0, '');
1270 //$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id');
1271 print "</td></tr>";
1272
1273 // Payment mode
1274 print "<tr><td>".$langs->trans("PaymentMode")."</td><td>";
1275 print img_picto('', 'payment', 'class="pictofixedwidth"');
1276 print $form->select_types_paiements((string) (GETPOSTISSET('mode_reglement_id') ? GETPOSTINT('mode_reglement_id') : $sourceInvoice->mode_reglement_id), 'mode_reglement_id', '', 0, 1, 0, 0, 1, '', 1);
1277 //$form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', '', 1);
1278 print "</td></tr>";
1279
1280 // Customer Bank Account
1281 print "<tr><td>".$langs->trans('DebitBankAccount')."</td><td>";
1282 $defaultRibId = $sourceInvoice->thirdparty->getDefaultRib();
1283 $form->selectRib(GETPOSTISSET('accountcustomerid') ? GETPOSTINT('accountcustomerid') : $defaultRibId, 'accountcustomerid', 'fk_soc='.$sourceInvoice->socid, 1, '', 1);
1284 print "</td></tr>";
1285
1286 print '<script>
1287 $(document).ready(function() {
1288 if($("#selectmode_reglement_id option:selected").data("code") != "' . $factureRec::PAYMENTCODETOEDITSOCIETERIB . '") {
1289 hideselectfksocieterib();
1290 }
1291 $("#selectmode_reglement_id").change(function() {
1292 if($("#selectmode_reglement_id option:selected").data("code") != "'. $factureRec::PAYMENTCODETOEDITSOCIETERIB .'") {
1293 hideselectfksocieterib(1);
1294 } else {
1295 showselectfksocieterib();
1296 }
1297 });
1298 });
1299
1300 function hideselectfksocieterib(empty = 0){
1301 $("#selectaccountcustomerid").closest("tr").hide();
1302 if(empty == 1){
1303 $("#selectaccountcustomerid").val("-1").change();
1304 }
1305 }
1306
1307 function showselectfksocieterib(){
1308 $("#selectaccountcustomerid").closest("tr").show();
1309 }
1310 </script>';
1311
1312 // Bank account
1313 if ($sourceInvoice->fk_account > 0) {
1314 print "<tr><td>".$langs->trans('BankAccount')."</td><td>";
1315 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$sourceInvoice->id, (string) $sourceInvoice->fk_account, 'none');
1316 print "</td></tr>";
1317 }
1318
1319 // Rule for lines dates
1320 print "<tr><td>".$langs->trans("RuleForLinesDates")."</td><td>";
1321 print $form->getSelectRuleForLinesDates(GETPOSTISSET('rule_for_lines_dates') ? GETPOST('rule_for_lines_dates', 'alpha') : $factureRec->rule_for_lines_dates);
1322 print "</td></tr>";
1323
1324 //extrafields
1325 $draft = new Facture($db);
1326 $draft->fetch(GETPOSTINT('facid'));
1327
1328 $extralabels = new ExtraFields($db);
1329 $extralabels = $extrafields->fetch_name_optionals_label($draft->table_element);
1330 if ($draft->fetch_optionals() > 0) {
1331 $sourceInvoice->array_options = array_merge($sourceInvoice->array_options, $draft->array_options);
1332 }
1333
1334 print $sourceInvoice->showOptionals($extrafields, 'create', $parameters);
1335
1336 // Project
1337 if (isModEnabled('project') && is_object($sourceInvoice->thirdparty) && $sourceInvoice->thirdparty->id > 0 && is_object($formproject)) {
1338 $projectid = GETPOST('projectid') ? GETPOST('projectid') : $sourceInvoice->fk_project;
1339 $langs->load('projects');
1340 print '<tr><td>'.$langs->trans('Project').'</td><td>';
1341 print img_picto('', 'project', 'class="pictofixedwidth"');
1342 $numprojet = $formproject->select_projects($sourceInvoice->thirdparty->id, $projectid, 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 0, 0, '');
1343 print ' &nbsp; <a href="'.DOL_URL_ROOT.'/projet/card.php?socid='.$sourceInvoice->thirdparty->id.'&action=create&status=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create&socid='.$sourceInvoice->thirdparty->id.(!empty($id) ? '&id='.$id : '')).'">'.img_object($langs->trans("AddProject"), 'add').'</a>';
1344 print '</td></tr>';
1345 }
1346
1347 // Model pdf
1348 print "<tr><td>".$langs->trans('Model')."</td><td>";
1349 include_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php';
1351 print img_picto('', 'generic', 'class="pictofixedwidth"');
1352 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1353 print $form->selectarray('modelpdf', $list, $conf->global->FACTURE_ADDON_PDF);
1354 print "</td></tr>";
1355
1356 // Public note
1357 print '<tr>';
1358 print '<td class="tdtop">';
1359 print $form->textwithpicto($langs->trans('NotePublic'), $htmltext, 1, 'help', '', 0, 2, 'notepublic');
1360 print '</td>';
1361 print '<td>';
1362 $doleditor = new DolEditor('note_public', $note_public, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
1363 print $doleditor->Create(1);
1364
1365 // Private note
1366 if (empty($user->socid)) {
1367 print '<tr>';
1368 print '<td class="tdtop">';
1369 print $form->textwithpicto($langs->trans('NotePrivate'), $htmltext, 1, 'help', '', 0, 2, 'noteprivate');
1370 print '</td>';
1371 print '<td>';
1372 $doleditor = new DolEditor('note_private', $note_private, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
1373 print $doleditor->Create(1);
1374 // print '<textarea name="note_private" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'.</textarea>
1375 print '</td></tr>';
1376 }
1377
1378 print "</table>";
1379
1380 print dol_get_fiche_end();
1381
1382 // Autogeneration
1383 $title = $langs->trans("Recurrence");
1384 print load_fiche_titre(img_picto('', 'recurring', 'class="pictofixedwidth"').$title, '', '');
1385
1386 print '<span class="opacitymedium">'.$langs->trans("ToCreateARecurringInvoiceGeneAuto", $langs->transnoentitiesnoconv('Module2300Name')).'</span><br><br>';
1387
1388 print dol_get_fiche_head([], '', '', 0);
1389
1390 print '<table class="border centpercent">';
1391
1392 // Frequency + unit
1393 print '<tr><td class="titlefieldcreate">'.$form->textwithpicto($langs->trans("Frequency"), $langs->transnoentitiesnoconv('toolTipFrequency'))."</td><td>";
1394 print '<input type="text" class="width50" name="frequency" value="'.GETPOST('frequency', 'int').'">&nbsp;';
1395 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'));
1396 print "</td></tr>";
1397
1398 // Date next run
1399 print "<tr><td>".$langs->trans('NextDateToExecution')."</td><td>";
1400 $date_next_execution = isset($date_next_execution) ? $date_next_execution : (GETPOSTINT('remonth') ? dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear')) : -1);
1401 print $form->selectDate($date_next_execution, '', 1, 1, 0, "add", 1, 1);
1402 print "</td></tr>";
1403
1404 // Number max of generation
1405 print "<tr><td>".$langs->trans("MaxPeriodNumber")."</td><td>";
1406 print '<input type="text" class="width50" name="nb_gen_max" value="'.GETPOSTINT('nb_gen_max').'">';
1407 print "</td></tr>";
1408
1409 // Auto validate the invoice
1410 print "<tr><td>".$langs->trans("StatusOfAutoGeneratedInvoices")."</td><td>";
1411 $select = array('0' => $langs->trans('BillStatusDraft'), '1' => $langs->trans('BillStatusValidated'));
1412 print $form->selectarray('auto_validate', $select, GETPOSTINT('auto_validate'));
1413 print "</td></tr>";
1414
1415 // Auto generate document
1416 if (getDolGlobalString('INVOICE_REC_CAN_DISABLE_DOCUMENT_FILE_GENERATION')) {
1417 print "<tr><td>".$langs->trans("StatusOfGeneratedDocuments")."</td><td>";
1418 $select = array('0' => $langs->trans('DoNotGenerateDoc'), '1' => $langs->trans('AutoGenerateDoc'));
1419 print $form->selectarray('generate_pdf', $select, GETPOSTINT('generate_pdf'));
1420 print "</td></tr>";
1421 } else {
1422 print '<input type="hidden" name="generate_pdf" value="1">';
1423 }
1424
1425 print "</table>";
1426
1427 print dol_get_fiche_end();
1428
1429
1430 $title = $langs->trans("ProductsAndServices");
1431 if (!isModEnabled('service')) {
1432 $title = $langs->trans("Products");
1433 } elseif (!isModEnabled('product')) {
1434 $title = $langs->trans("Services");
1435 }
1436
1437 print load_fiche_titre($title, '', '');
1438
1439 /*
1440 * Invoice lines
1441 */
1442 print '<div class="div-table-responsive-no-min">';
1443 print '<table id="tablelines" class="noborder noshadow centpercent nomarginbottom">';
1444
1445 // Show object lines
1446 if (!empty($sourceInvoice->lines)) {
1447 $sourceInvoice->printOriginLinesList('', $selectedLines);
1448 }
1449
1450 print "</table>\n";
1451 print '<div>';
1452
1453 print '</td></tr>';
1454
1455 $flag_price_may_change = getDolGlobalString('INVOICE_REC_PRICE_MAY_CHANGE');
1456 if (!empty($flag_price_may_change)) {
1457 print '<tr><td colspan="3" class="left">';
1458 print '<select name="usenewprice" class="flat">';
1459 print '<option value="0">'.$langs->trans("AlwaysUseFixedPrice").'</option>';
1460 print '<option value="1" disabled>'.$langs->trans("AlwaysUseNewPrice").'</option>';
1461 print '</select>';
1462 print '</td></tr>';
1463 }
1464 print "</table>\n";
1465
1466 print '<br>';
1467
1468 print $form->buttonsSaveCancel("Create");
1469
1470 print "</form>\n";
1471 } else {
1472 dol_print_error(null, "Error, no invoice ".$sourceInvoice->id);
1473 }
1474} else {
1475 // View mode
1476 if ($object->id > 0) {
1477 $object->fetch_thirdparty();
1478
1479 $formconfirm = '';
1480 // Confirmation of deletion of product line
1481 if ($action == 'ask_deleteline') {
1482 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 'no', 1);
1483 }
1484 // Confirm delete of repeatable invoice
1485 if ($action == 'delete') {
1486 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteRepeatableInvoice'), $langs->trans('ConfirmDeleteRepeatableInvoice'), 'confirm_delete', '', 'no', 1);
1487 }
1488 // Confirmation de la suppression d'une ligne subtotal
1489 if ($action == 'ask_subtotal_deleteline') {
1490 $langs->load("subtotals");
1491 $title = "DeleteSubtotalLine";
1492 $question = "ConfirmDeleteSubtotalLine";
1493 if (GETPOST('type') == 'title') {
1494 $formconfirm = array(array('type' => 'checkbox', 'name' => 'deletecorrespondingsubtotalline', 'label' => $langs->trans("DeleteCorrespondingSubtotalLine"), 'value' => 0));
1495 $title = "DeleteTitleLine";
1496 $question = "ConfirmDeleteTitleLine";
1497 }
1498 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans($title), $langs->trans($question), 'confirm_delete_subtotalline', $formconfirm, 'no', 1);
1499 }
1500
1501 // Subtotal line form
1502 if ($action == 'add_title_line') {
1503 $langs->load('subtotals');
1504 $type = 'title';
1505 $depth_array = $object->getPossibleLevels($langs);
1506 require dol_buildpath('/core/tpl/subtotal_create.tpl.php');
1507 } elseif ($action == 'add_subtotal_line') {
1508 $langs->load('subtotals');
1509 $type = 'subtotal';
1510 $titles = $object->getPossibleTitles();
1511 require dol_buildpath('/core/tpl/subtotal_create.tpl.php');
1512 }
1513
1514 // Call Hook formConfirm
1515 $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
1516 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1517 if (empty($reshook)) {
1518 $formconfirm .= $hookmanager->resPrint;
1519 } elseif ($reshook > 0) {
1520 $formconfirm = $hookmanager->resPrint;
1521 }
1522
1523 print $formconfirm;
1524
1525 $author = new User($db);
1526 $author->fetch($object->user_author);
1527
1528 $head = invoice_rec_prepare_head($object);
1529
1530 print dol_get_fiche_head($head, 'card', $langs->trans("RepeatableInvoice"), -1, 'bill'); // Add a div
1531
1532 // Recurring invoice content
1533
1534 $linkback = '<a href="'.DOL_URL_ROOT.'/compta/facture/invoicetemplate_list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
1535
1536 $morehtmlref = '';
1537 if ($action != 'editref') {
1538 $morehtmlref .= $form->editfieldkey($object->ref, 'ref', $object->ref, $object, $user->hasRight('facture', 'creer'), '', '', 0, 2);
1539 } else {
1540 $morehtmlref .= $form->editfieldval('', 'ref', $object->ref, $object, $user->hasRight('facture', 'creer'), 'string');
1541 }
1542
1543 $morehtmlref .= '<div class="refidno">';
1544 // Ref customer
1545 //$morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_customer, $object, $user->hasRight('facture', 'creer'), 'string', '', 0, 1);
1546 //$morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_customer, $object, $user->hasRight('facture', 'creer'), 'string', '', null, null, '', 1);
1547 // Thirdparty
1548 $morehtmlref .= $object->thirdparty->getNomUrl(1, 'customer');
1549 // Project
1550 if (isModEnabled('project')) {
1551 $langs->load("projects");
1552 $morehtmlref .= '<br>';
1553 if ($user->hasRight('facture', 'creer')) {
1554 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
1555 if ($action != 'classify') {
1556 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
1557 }
1558 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, (string) $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
1559 } else {
1560 if (!empty($object->fk_project)) {
1561 $proj = new Project($db);
1562 $proj->fetch($object->fk_project);
1563 $morehtmlref .= ' : '.$proj->getNomUrl(1);
1564 if ($proj->title) {
1565 $morehtmlref .= ' - '.$proj->title;
1566 }
1567 } else {
1568 $morehtmlref .= '';
1569 }
1570 }
1571 }
1572 $morehtmlref .= '</div>';
1573
1574 $morehtmlstatus = '';
1575
1576 dol_banner_tab($object, 'ref', $linkback, 1, 'title', 'none', $morehtmlref, '', 0, '', $morehtmlstatus);
1577
1578 print '<div class="fichecenter">';
1579 print '<div class="fichehalfleft">';
1580 print '<div class="underbanner clearboth"></div>';
1581
1582 print '<table class="border centpercent tableforfield">';
1583
1584 // Invoice subtype
1585 if (getDolGlobalInt('INVOICE_SUBTYPE_ENABLED')) {
1586 print "<tr><td>".$langs->trans("InvoiceSubtype")."</td><td>";
1587 if ($object->subtype > 0) {
1588 print $object->getSubtypeLabel('facture_rec');
1589 }
1590 print "</td></tr>";
1591 }
1592
1593 // Author
1594 print '<tr><td class="titlefield">'.$langs->trans("Author").'</td><td>';
1595 print $author->getNomUrl(-1);
1596 print "</td></tr>";
1597
1598 // Payment term
1599 print '<tr><td>';
1600 print '<table class="nobordernopadding centpercent"><tr><td>';
1601 print $langs->trans('PaymentConditionsShort');
1602 print '</td>';
1603 if ($action != 'editconditions' && $user->hasRight('facture', 'creer')) {
1604 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>';
1605 }
1606 print '</tr></table>';
1607 print '</td><td>';
1608 if ($action == 'editconditions') {
1609 $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->cond_reglement_id, 'cond_reglement_id');
1610 } else {
1611 $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->cond_reglement_id, 'none');
1612 }
1613 print '</td></tr>';
1614
1615 // Payment mode
1616 print '<tr><td>';
1617 print '<table class="nobordernopadding" width="100%"><tr><td>';
1618 print $langs->trans('PaymentMode');
1619 print '</td>';
1620 if ($action != 'editmode' && $user->hasRight('facture', 'creer')) {
1621 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>';
1622 }
1623 print '</tr></table>';
1624 print '</td><td>';
1625 if ($action == 'editmode') {
1626 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
1627 } else {
1628 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->mode_reglement_id, 'none');
1629 }
1630 print '</td></tr>';
1631
1632
1633 // Bank Account Customer
1634 if ($object->mode_reglement_code == $object::PAYMENTCODETOEDITSOCIETERIB) {
1635 print '<tr><td class="nowrap">';
1636 print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
1637 print $langs->trans('DebitBankAccount');
1638 print '<td>';
1639
1640 if (($action != 'editbankaccountcustomer') && $user->hasRight('facture', 'creer') && $object->statut == FactureRec::STATUS_DRAFT) {
1641 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>';
1642 }
1643 print '</tr></table>';
1644 print '</td><td>';
1645
1646 if ($action == 'editbankaccountcustomer') {
1647 $form->formRib($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->fk_societe_rib, 'accountcustomerid', 'fk_soc='.$object->socid, 1, 1);
1648 } else {
1649 $form->formRib($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->fk_societe_rib, 'none', '', 0, 1);
1650 }
1651 print "</td>";
1652 print '</tr>';
1653 }
1654
1655 // Bank Account
1656 print '<tr><td class="nowrap">';
1657 print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
1658 print $langs->trans('BankAccount');
1659 print '<td>';
1660 if (($action != 'editbankaccount') && $user->hasRight('facture', 'creer') && $object->statut == FactureRec::STATUS_DRAFT) {
1661 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>';
1662 }
1663 print '</tr></table>';
1664 print '</td><td>';
1665 if ($action == 'editbankaccount') {
1666 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'fk_account', 1);
1667 } else {
1668 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'none');
1669 }
1670 print "</td>";
1671 print '</tr>';
1672
1673 // Billing Term
1674 print '<tr><td>';
1675 print '<table class="nobordernopadding centpercent"><tr><td>';
1676 print $langs->trans('RuleForLinesDates');
1677 print '</td>';
1678 if ($action != 'editruleforlinesdates' && $user->hasRight('facture', 'creer')) {
1679 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editruleforlinesdates&token='.newToken().'&facid='.$object->id.'">'.img_edit($langs->trans('SetRuleForLinesDates'), 1).'</a></td>';
1680 }
1681 print '</tr></table>';
1682 print '</td><td>';
1683 if ($action == 'editruleforlinesdates') {
1684 $form->form_rule_for_lines_dates($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->rule_for_lines_dates, 'rule_for_lines_dates');
1685 } else {
1686 $form->form_rule_for_lines_dates($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->rule_for_lines_dates, 'none');
1687 }
1688 print '</td></tr>';
1689
1690 // Extrafields
1691 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1692
1693 // Model pdf
1694 print '<tr><td class="nowrap">';
1695 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
1696 print $langs->trans('Model');
1697 print '<td>';
1698 if (($action != 'editmodelpdf') && $user->hasRight('facture', 'creer') && $object->statut == FactureRec::STATUS_DRAFT) {
1699 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>';
1700 }
1701 print '</tr></table>';
1702 print '</td><td>';
1703 if ($action == 'editmodelpdf') {
1704 include_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php';
1705 $list = array();
1706 $models = ModelePDFFactures::liste_modeles($db);
1707 foreach ($models as $k => $model) {
1708 $list[] = str_replace(':', '|', $k).':'.$model;
1709 }
1710 $select = 'select;'.implode(',', $list);
1711 print $form->editfieldval($langs->trans("Model"), 'modelpdf', $object->model_pdf, $object, $user->hasRight('facture', 'creer'), $select);
1712 } else {
1713 print $object->model_pdf;
1714 }
1715 print "</td>";
1716 print '</tr>';
1717
1718 // Other attributes
1719 $cols = 2;
1720
1721
1722 print '</table>';
1723
1724 print '</div>';
1725 print '<div class="fichehalfright">';
1726
1727 print '<!-- amounts -->'."\n";
1728 print '<div class="underbanner clearboth"></div>'."\n";
1729
1730 // Recurrence
1731 $title = $langs->trans("Recurrence");
1732
1733 print '<table class="border tableforfield centpercent">';
1734
1735 include DOL_DOCUMENT_ROOT.'/core/tpl/object_currency_amount.tpl.php';
1736
1737 $sign = 1;
1738 if (getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE_SCREEN') && $object->type == $object::TYPE_CREDIT_NOTE) {
1739 $sign = -1; // We invert sign for output
1740 }
1741
1742 // Amount (excl. tax)
1743 print '<tr><td class="titlefieldmiddle">'.$langs->trans("AmountHT").'</td>';
1744 print '<td class="nowraponall amountcard right">'.price($sign * $object->total_ht, 0, $langs, 1, -1, -1, $conf->currency).'</td>';
1745 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1746 // Multicurrency Amount HT
1747 print '<td class="nowraponall amountcard right">' . price($sign * $object->multicurrency_total_ht, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
1748 }
1749 print '</tr>';
1750
1751 // Amount tax
1752 print '<tr><td>'.$langs->trans("AmountVAT").'</td>';
1753 print '<td class="nowrap amountcard right">'.price($sign * $object->total_tva, 0, $langs, 1, -1, -1, $conf->currency).'</td>';
1754 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1755 // Multicurrency Amount VAT
1756 print '<td class="nowraponall amountcard right">' . price($sign * $object->multicurrency_total_tva, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
1757 }
1758 print '</tr>';
1759
1760 // Amount Local Taxes
1761 if (($mysoc->localtax1_assuj == "1" && $mysoc->useLocalTax(1)) || $object->total_localtax1 != 0) { // Localtax1
1762 print '<tr>';
1763 print '<td class="titlefieldmiddle">'.$langs->transcountry("AmountLT1", $mysoc->country_code).'</td>';
1764 print '<td class="nowraponall amountcard right">'.price($sign * $object->total_localtax1, 1, '', 1, - 1, - 1, $conf->currency).'</td></tr>';
1765 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1766 $object->multicurrency_total_localtax1 = (float) price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT');
1767
1768 print '<td class="nowraponall amountcard right">' . price($sign * $object->multicurrency_total_localtax1, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
1769 }
1770 print '</tr>';
1771 }
1772
1773 if (($mysoc->localtax2_assuj == "1" && $mysoc->useLocalTax(2)) || $object->total_localtax2 != 0) { // Localtax2
1774 print '<tr>';
1775 print '<td>'.$langs->transcountry("AmountLT2", $mysoc->country_code).'</td>';
1776 print '<td class=nowraponall amountcard right">'.price($sign * $object->total_localtax2, 1, '', 1, - 1, - 1, $conf->currency).'</td></tr>';
1777 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1778 $object->multicurrency_total_localtax2 = (float) price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT');
1779
1780 print '<td class="nowraponall amountcard right">' . price($sign * $object->multicurrency_total_localtax2, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
1781 }
1782 print '</tr>';
1783 }
1784
1785 // Add the revenue stamp
1786 /*
1787 if ($selleruserevenustamp) {
1788 print '<tr><td class="titlefieldmiddle">';
1789 print '<table class="nobordernopadding centpercent"><tr><td>';
1790 print $langs->trans('RevenueStamp');
1791 print '</td>';
1792 if ($action != 'editrevenuestamp' && $object->status == $object::STATUS_DRAFT && $usercancreate) {
1793 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editrevenuestamp&token='.newToken().'&facid='.$object->id.'">'.img_edit($langs->trans('SetRevenuStamp'), 1).'</a></td>';
1794 }
1795 print '</tr></table>';
1796 print '</td><td class="nowrap amountcard right">';
1797 if ($action == 'editrevenuestamp') {
1798 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1799 print '<input type="hidden" name="token" value="'.newToken().'">';
1800 print '<input type="hidden" name="action" value="setrevenuestamp">';
1801 print '<input type="hidden" name="revenuestamp" id="revenuestamp_val" value="'.price2num($object->revenuestamp).'">';
1802 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1803 print $formother->select_revenue_stamp('', 'revenuestamp_type', $mysoc->country_code);
1804 print ' &rarr; <span id="revenuestamp_span"></span>';
1805 print ' <input type="submit" class="button buttongen button-save small" value="'.$langs->trans('Modify').'">';
1806 print '</form>';
1807 print " <script>
1808 $(document).ready(function(){
1809 js_recalculate_revenuestamp();
1810 $('select[name=revenuestamp_type]').on('change',function(){
1811 js_recalculate_revenuestamp();
1812 });
1813 });
1814 function js_recalculate_revenuestamp(){
1815 var valselected = $('select[name=revenuestamp_type]').val();
1816 console.log('Calculate revenue stamp from '+valselected);
1817 var revenue = 0;
1818 if (valselected.indexOf('%') == -1)
1819 {
1820 revenue = valselected;
1821 }
1822 else
1823 {
1824 var revenue_type = parseFloat(valselected);
1825 var amount_net = ".round($object->total_ht, 2).";
1826 revenue = revenue_type * amount_net / 100;
1827 revenue = revenue.toFixed(2);
1828 }
1829 $('#revenuestamp_val').val(revenue);
1830 $('#revenuestamp_span').html(revenue);
1831 }
1832 </script>";
1833 } else {
1834 print price($object->revenuestamp, 1, '', 1, -1, -1, $conf->currency);
1835 }
1836 print '</td></tr>';
1837 }
1838 */
1839
1840 // Amount TTC
1841 print '<tr><td>'.$langs->trans("AmountTTC").'</td><td class="nowraponall amountcard right">'.price($sign * $object->total_ttc, 0, $langs, 1, -1, -1, $conf->currency).'</td>';
1842 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1843 // Multicurrency Amount TTC
1844 print '<td class="nowrap amountcard right">' . price($sign * $object->multicurrency_total_ttc, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
1845 }
1846 print '</tr>';
1847
1848 // Recurring info
1849 print '<tr class="liste_titre"><td class="liste_titre">'.img_picto('', 'recurring', 'class="pictofixedwidth"').$title.'</td>';
1850 print '<td></td>';
1851 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1852 print '<td></td>';
1853 }
1854 print '</tr>';
1855
1856 // if "frequency" is empty or = 0, the recurrence is disabled
1857 print '<tr><td style="width: 50%">';
1858 print '<table class="nobordernopadding" width="100%"><tr><td>';
1859 print $langs->trans('Frequency');
1860 print '</td>';
1861 if ($action != 'editfrequency' && $user->hasRight('facture', 'creer')) {
1862 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>';
1863 }
1864 print '</tr></table>';
1865 print '</td><td>';
1866 if ($action == 'editfrequency') {
1867 print '<form method="post" action="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'">';
1868 print '<input type="hidden" name="action" value="setfrequency">';
1869 print '<input type="hidden" name="token" value="'.newToken().'">';
1870 print '<table class="nobordernopadding">';
1871 print '<tr><td>';
1872 print '<input type="text" name="frequency" class="width50 marginrightonly right" value="'.$object->frequency.'">';
1873 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'));
1874 print '</td>';
1875 print '<td class="left"><input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans("Modify").'"></td>';
1876 print '</tr></table></form>';
1877 } else {
1878 if ($object->frequency > 0) {
1879 print $langs->trans('FrequencyPer_'.$object->unit_frequency, $object->frequency);
1880 } else {
1881 print '<span class="opacitymedium">'.$langs->trans("NotARecurringInvoiceTemplate").'</span>';
1882 }
1883 }
1884 print '</td>';
1885 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1886 print '<td></td>';
1887 }
1888 print '</tr>';
1889
1890 if ($object->frequency > 0) {
1891 // Date when (next invoice generation)
1892 print '<tr><td>';
1893 if ($action == 'date_when' || $object->frequency > 0) {
1894 print $form->editfieldkey($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->hasRight('facture', 'creer'), 'day');
1895 } else {
1896 print $langs->trans("NextDateToExecution");
1897 }
1898 print '</td><td>';
1899 if ($action == 'date_when' || $object->frequency > 0) {
1900 print $form->editfieldval($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->hasRight('facture', 'creer'), 'day', $object->date_when, null, '', '', 0, 'strikeIfMaxNbGenReached');
1901 }
1902 //var_dump(dol_print_date($object->date_when+60, 'dayhour').' - '.dol_print_date($now, 'dayhour'));
1903 if (!$object->isMaxNbGenReached()) {
1904 if (!$object->suspended && $action != 'editdate_when' && $object->frequency > 0 && $object->date_when && $object->date_when < $now) {
1905 print img_warning($langs->trans("Late"));
1906 }
1907 } else {
1908 print img_info($langs->trans("MaxNumberOfGenerationReached"));
1909 }
1910 print '</td>';
1911 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1912 print '<td></td>';
1913 }
1914 print '</tr>';
1915
1916 // Max period / Rest period
1917 print '<tr><td>';
1918 if ($action == 'nb_gen_max' || $object->frequency > 0) {
1919 print $form->editfieldkey($langs->trans("MaxPeriodNumber"), 'nb_gen_max', (string) $object->nb_gen_max, $object, $user->hasRight('facture', 'creer'));
1920 } else {
1921 print $langs->trans("MaxPeriodNumber");
1922 }
1923 print '</td><td>';
1924 if ($action == 'nb_gen_max' || $object->frequency > 0) {
1925 print $form->editfieldval($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max ? $object->nb_gen_max : '', $object, $user->hasRight('facture', 'creer'));
1926 } else {
1927 print '';
1928 }
1929 print '</td>';
1930 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1931 print '<td></td>';
1932 }
1933 print '</tr>';
1934
1935 // Status of auto generated invoices
1936 print '<tr><td>';
1937 if ($action == 'auto_validate' || $object->frequency > 0) {
1938 print $form->editfieldkey($langs->trans("StatusOfAutoGeneratedInvoices"), 'auto_validate', (string) $object->auto_validate, $object, $user->hasRight('facture', 'creer'));
1939 } else {
1940 print $langs->trans("StatusOfAutoGeneratedInvoices");
1941 }
1942 print '</td><td>';
1943 $select = 'select;0:'.$langs->trans('BillStatusDraft').',1:'.$langs->trans('BillStatusValidated');
1944 if ($action == 'auto_validate' || $object->frequency > 0) {
1945 print $form->editfieldval($langs->trans("StatusOfAutoGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $user->hasRight('facture', 'creer'), $select);
1946 }
1947 print '</td>';
1948 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1949 print '<td></td>';
1950 }
1951 print '</tr>';
1952 // Auto generate documents
1953 if (getDolGlobalString('INVOICE_REC_CAN_DISABLE_DOCUMENT_FILE_GENERATION')) {
1954 print '<tr>';
1955 print '<td>';
1956 if ($action == 'generate_pdf' || $object->frequency > 0) {
1957 print $form->editfieldkey($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', (string) $object->generate_pdf, $object, $user->hasRight('facture', 'creer'));
1958 } else {
1959 print $langs->trans("StatusOfGeneratedDocuments");
1960 }
1961 print '</td>';
1962 print '<td>';
1963 $select = 'select;0:'.$langs->trans('DoNotGenerateDoc').',1:'.$langs->trans('AutogenerateDoc');
1964 if ($action == 'generate_pdf' || $object->frequency > 0) {
1965 print $form->editfieldval($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', $object->generate_pdf, $object, $user->hasRight('facture', 'creer'), $select);
1966 }
1967 print '</td>';
1968 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1969 print '<td></td>';
1970 }
1971 print '</tr>';
1972 } else {
1973 print '<input type="hidden" name="generate_pdf" value="1">';
1974 }
1975 }
1976
1977 print '</table>';
1978
1979 // Frequencry/Recurring section
1980 if ($object->frequency > 0) {
1981 print '<br>';
1982
1983 if (!isModEnabled('cron')) {
1984 print info_admin($langs->trans("EnableAndSetupModuleCron", $langs->transnoentitiesnoconv("Module2300Name")));
1985 }
1986
1987 print '<div class="underbanner clearboth"></div>';
1988 print '<table class="border centpercent tableforfield">';
1989
1990 // Nb of generation already done
1991 print '<tr><td style="width: 50%">'.$langs->trans("NbOfGenerationDone").'</td>';
1992 print '<td>';
1993 print $object->nb_gen_done ? $object->nb_gen_done : '0';
1994 print '</td>';
1995 print '</tr>';
1996
1997 // Date last
1998 print '<tr><td>';
1999 print $langs->trans("DateLastGeneration");
2000 print '</td><td>';
2001 print dol_print_date($object->date_last_gen, 'dayhour');
2002 print '</td>';
2003 print '</tr>';
2004
2005 print '</table>';
2006
2007 print '<br>';
2008 }
2009
2010 print '</div>';
2011 print '</div>';
2012
2013 print '<div class="clearboth"></div><br>';
2014
2015
2016 // Lines
2017 print '<form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline') ? '#add' : '#line_'.GETPOSTINT('lineid')).'" method="POST">';
2018 print '<input type="hidden" name="token" value="' . newToken().'">';
2019 print '<input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">';
2020 print '<input type="hidden" name="mode" value="">';
2021 print '<input type="hidden" name="id" value="' . $object->id.'">';
2022 print '<input type="hidden" name="page_y" value="">';
2023
2024 if (!empty($conf->use_javascript_ajax) && $object->statut == 0) {
2025 if (isModEnabled('subtotals')) {
2026 include DOL_DOCUMENT_ROOT.'/core/tpl/subtotal_ajaxrow.tpl.php';
2027 } else {
2028 include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
2029 }
2030 }
2031
2032 print '<div class="div-table-responsive-no-min">';
2033 print '<table id="tablelines" class="noborder noshadow centpercent nomarginbottom">';
2034 // Show object lines
2035 if (!empty($object->lines)) {
2036 $canchangeproduct = 1;
2037 $object->printObjectLines($action, $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice
2038 }
2039
2040 // Form to add new line
2041 if ($object->status == $object::STATUS_DRAFT && $user->hasRight('facture', 'creer') && $action != 'valid' && $action != 'editline') {
2042 if ($action != 'editline') {
2043 // Add free products/services
2044
2045 $parameters = array();
2046 $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2047 if ($reshook < 0) {
2048 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2049 }
2050 if (empty($reshook)) {
2051 $object->formAddObjectLine(0, $mysoc, $object->thirdparty);
2052 } // No date selector for template invoice
2053 }
2054 }
2055
2056 print "</table>\n";
2057 print '</div>';
2058
2059 print "</form>\n";
2060
2061 print dol_get_fiche_end();
2062
2063
2064 /*
2065 * Action bar
2066 */
2067 print '<div class="tabsAction">';
2068
2069 $parameters = array();
2070 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2071 if (empty($reshook)) {
2072 $params = array(
2073 'attr' => array(
2074 'class' => 'classfortooltip',
2075 ),
2076 );
2077
2078 // Subtotal
2079 if (empty($object->suspended) && isModEnabled('subtotals')
2080 && (getDolGlobalInt('SUBTOTAL_TITLE_'.strtoupper($object->element)) || getDolGlobalInt('SUBTOTAL_'.strtoupper($object->element)))) {
2081 $langs->load("subtotals");
2082
2083 $url_button = array();
2084
2085 $url_button[] = array(
2086 'lang' => 'subtotals',
2087 'enabled' => (isModEnabled('invoice') && $object->status == Facture::STATUS_DRAFT && getDolGlobalInt('SUBTOTAL_TITLE_'.strtoupper($object->element))),
2088 'perm' => (bool) $usercancreate,
2089 'label' => $langs->trans('AddTitleLine'),
2090 'url' => '/compta/facture/card-rec.php?id='.$object->id.'&action=add_title_line&token='.newToken()
2091 );
2092
2093 $url_button[] = array(
2094 'lang' => 'subtotals',
2095 'enabled' => (isModEnabled('invoice') && $object->status == Facture::STATUS_DRAFT && getDolGlobalInt('SUBTOTAL_'.strtoupper($object->element))),
2096 'perm' => (bool) $usercancreate,
2097 'label' => $langs->trans('AddSubtotalLine'),
2098 'url' => '/compta/facture/card-rec.php?id='.$object->id.'&action=add_subtotal_line&token='.newToken()
2099 );
2100 print dolGetButtonAction('', $langs->trans('Subtotal'), 'default', $url_button, '', true);
2101 }
2102
2103 if (empty($object->suspended)) {
2104 if ($user->hasRight('facture', 'creer')) {
2105 if (!empty($object->frequency) && $object->nb_gen_max > 0 && ($object->nb_gen_done >= $object->nb_gen_max)) {
2106 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("MaxGenerationReached")) . '">' . $langs->trans("CreateBill") . '</a></div>';
2107 } else {
2108 if (empty($object->frequency) || $object->date_when <= $nowlasthour) {
2109 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>';
2110 } else {
2111 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("DateIsNotEnough")) . '">' . $langs->trans("CreateBill") . '</a></div>';
2112 }
2113 }
2114 } else {
2115 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#">' . $langs->trans("CreateBill") . '</a></div>';
2116 }
2117 }
2118
2119 if ($user->hasRight('facture', 'creer')) {
2120 if (empty($object->suspended)) {
2121 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>';
2122 } else {
2123 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>';
2124 }
2125 }
2126
2127 // Delete
2128 print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=delete&token=' . newToken(), 'delete', $user->hasRight('facture', 'supprimer'));
2129 }
2130 print '</div>';
2131
2132
2133
2134 print '<div class="fichecenter"><div class="fichehalfleft">';
2135 print '<a name="builddoc"></a>'; // ancre
2136
2137
2138 // Show links to link elements
2139 $tmparray = $form->showLinkToObjectBlock($object, array(), array('invoice'), 1);
2140 $linktoelem = $tmparray['linktoelem'];
2141 $htmltoenteralink = $tmparray['htmltoenteralink'];
2142 print $htmltoenteralink;
2143
2144 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
2145
2146
2147 print '</div>';
2148 print '<div class="fichehalfright">';
2149
2150 $MAXEVENT = 10;
2151
2152 //$morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', dol_buildpath('/mymodule/myobject_agenda.php', 1).'?id='.$object->id);
2153 $morehtmlcenter = '';
2154
2155 // List of actions on element
2156 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
2157 $formactions = new FormActions($db);
2158 $morehtmlcenter = '';
2159 $somethingshown = $formactions->showactions($object, $object->element, (is_object($object->thirdparty) ? $object->thirdparty->id : 0), 1, '', $MAXEVENT, '', $morehtmlcenter);
2160
2161 print '</div>';
2162 print '</div>';
2163 } else {
2164 print $langs->trans("NoRecordFound");
2165 }
2166}
2167
2168// End of page
2169llxFooter();
2170$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:48
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:67
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
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:73
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 STATUS_DRAFT
Draft status.
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.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
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, $morecssdiv='')
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.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
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.
GETPOSTFLOAT($paramname, $rounding='')
Return the value of a $_GET or $_POST supervariable, converted into float.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
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...
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.