dolibarr 24.0.0-beta
card-rec.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2002-2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2023 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
6 * Copyright (C) 2013-2023 Juanjo Menent <jmenent@2byte.es>
7 * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
8 * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
9 * Copyright (C) 2015 Alexandre Spangaro <aspangaro@open-dsi.fr>
10 * Copyright (C) 2016 Meziane Sof <virtualsof@yahoo.fr>
11 * Copyright (C) 2017-2026 Frédéric France <frederic.france@free.fr>
12 * Copyright (C) 2023 Nick Fragoulis
13 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
14 * Copyright (C) 2026 Joris Le Blansch <ping@apio.systems>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <https://www.gnu.org/licenses/>.
28 */
29
36// Load Dolibarr environment
37require '../../main.inc.php';
47require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php';
48require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
49require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
50if (isModEnabled('project')) {
51 include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
52}
53require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
54require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
55require_once DOL_DOCUMENT_ROOT.'/core/lib/invoice.lib.php';
56
57// Load translation files required by the page
58$langs->loadLangs(array('bills', 'companies', 'compta', 'admin', 'other', 'products', 'banks'));
59
60$action = GETPOST('action', 'aZ09');
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:int');
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:int');
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
119// fetch optionals attributes and labels
120$extrafields->fetch_name_optionals_label($object->table_element);
121
122$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
123
124$permissiontoadd = $user->hasRight('facture', 'creer');
125$permissionnote = $user->hasRight('facture', 'creer'); // Used by the include of actions_setnotes.inc.php
126$permissiondellink = $user->hasRight('facture', 'creer'); // Used by the include of actions_dellink.inc.php
127$permissiontoedit = $user->hasRight('facture', 'creer'); // Used by the include of actions_lineupdonw.inc.php
128$permissiontoeditextra = $permissiontoadd;
129if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
130 // For action 'update_extras', is there a specific permission set for the attribute to update
131 $permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
132}
133
134$usercanread = $user->hasRight('facture', 'lire');
135$usercancreate = $user->hasRight('facture', 'creer');
136$usercanissuepayment = $user->hasRight('facture', 'paiement');
137$usercandelete = $user->hasRight('facture', 'supprimer');
138
139// Advanced permissions
140$usercanvalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $usercancreate) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('facture', 'invoice_advance', 'validate')));
141$usercansend = (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || $user->hasRight('facture', 'invoice_advance', 'send'));
142$usercanreopen = (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || $user->hasRight('facture', 'invoice_advance', 'reopen'));
143$usercanunvalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !empty($usercancreate)) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('facture', 'invoice_advance', 'unvalidate')));
144$usermustrespectpricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !$user->hasRight('produit', 'ignore_price_min_advance')) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
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->fk_email_template = GETPOSTINT('auto_send_model_mail');
274 $object->generate_pdf = GETPOSTINT('generate_pdf');
275 $object->fk_project = $projectid;
276
277 $date_next_execution = dol_mktime($rehour, $remin, 0, $remonth, $reday, $reyear);
278 $object->date_when = $date_next_execution;
279
280 $ret = $extrafields->setOptionalsFromPost(null, $object);
281 if ($ret < 0) {
282 setEventMessages($extrafields->error, $extrafields->errors, 'errors');
283 $error++;
284 }
285
286 // Get first contract linked to invoice (or order or proposal) used to generate template (facid is id of source invoice)
287 if (GETPOSTINT('facid') > 0) {
288 $srcObject = new Facture($db);
289 $srcObject->fetch(GETPOSTINT('facid'));
290
291 $srcObject->fetchObjectLinked();
292
293 if (!empty($srcObject->linkedObjectsIds['contrat'])) {
294 $contractidid = reset($srcObject->linkedObjectsIds['contrat']);
295
296 $object->origin_type = 'contrat';
297 $object->origin_id = $contractidid;
298 $object->linked_objects[$object->origin_type] = $object->origin_id;
299 } elseif (!empty($srcObject->linkedObjectsIds['commande'])) {
300 $orderid = reset($srcObject->linkedObjectsIds['commande']);
301
302 $object->linked_objects['commande'] = $orderid;
303 } elseif (!empty($srcObject->linkedObjectsIds['propal'])) {
304 $proposalid = reset($srcObject->linkedObjectsIds['propal']);
305 $object->linked_objects['propal'] = $proposalid;
306 }
307 }
308
309 $db->begin();
310
311 $oldinvoice = new Facture($db);
312 $oldinvoice->fetch(GETPOSTINT('facid'));
313
314 $onlylines = GETPOST('toselect', 'array:int');
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 == 'setEmailTemplate' && $usercancreate) {
412 // Set Email Template
413 $object->setMailTemplate(GETPOSTINT('auto_send_model_mail'));
414 } elseif ($action == 'setgenerate_pdf' && $usercancreate) {
415 // Set generate pdf
416 $object->setGeneratepdf(GETPOSTINT('generate_pdf'));
417 } elseif ($action == 'setmodelpdf' && $usercancreate) {
418 // Set model pdf
419 $object->setModelpdf(GETPOST('modelpdf', 'alpha'));
420 } elseif ($action == 'disable' && $usercancreate) {
421 // Set status disabled
422 $db->begin();
423
424 $object->context['actionmsg'] = $langs->trans("RecordDisabled");
425
426 $res = $object->setValueFrom('suspended', 1, '', null, 'text', '', $user, 'BILLREC_MODIFY');
427 if ($res <= 0) {
428 $error++;
429 }
430
431 if (!$error) {
432 $db->commit();
433 } else {
434 $db->rollback();
435 setEventMessages($object->error, $object->errors, 'errors');
436 }
437 } elseif ($action == 'enable' && $usercancreate) {
438 // Set status enabled
439 $db->begin();
440
441 $object->context['actionmsg'] = $langs->trans("RecordEnabled");
442
443 $res = $object->setValueFrom('suspended', 0, '', null, 'text', '', $user, 'BILLREC_MODIFY');
444 if ($res <= 0) {
445 $error++;
446 }
447
448 if (!$error) {
449 $db->commit();
450 } else {
451 $db->rollback();
452 setEventMessages($object->error, $object->errors, 'errors');
453 }
454 } elseif ($action == 'setmulticurrencycode' && $usercancreate) {
455 // Multicurrency Code
456 $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha'));
457 $object->fetch($object->id); // Reload all.
458 } elseif ($action == 'setmulticurrencyrate' && $usercancreate) {
459 // Multicurrency rate
460 $result = $object->setMulticurrencyRate(GETPOSTFLOAT('multicurrency_tx'), GETPOSTINT('calculation_mode'));
461 $object->fetch($object->id); // Reload all.
462 } elseif ($action == 'setruleforlinesdates' && $usercancreate) {
463 $object->context['actionmsg'] = $langs->trans("FieldXModified", $langs->transnoentitiesnoconv("RuleForLinesDates"));
464 $ruleForLinesDates = GETPOSTISSET('rule_for_lines_dates') ? GETPOST('rule_for_lines_dates', 'alpha') : 'prepaid';
465 $object->setValueFrom('rule_for_lines_dates', $ruleForLinesDates);
466 }
467
468 // Delete line
469 if ($action == 'confirm_deleteline' && $confirm == 'yes' && $usercancreate) {
470 $object->fetch($id);
471 $object->fetch_thirdparty();
472
473 $db->begin();
474
475 $line = new FactureLigneRec($db);
476
477 // For triggers
478 $line->id = $lineid;
479
480 if ($line->delete($user) > 0) {
481 $result = $object->update_price(1);
482
483 if ($result > 0) {
484 $db->commit();
485 $object->fetch($object->id); // Reload lines
486 } else {
487 $db->rollback();
488 setEventMessages($db->lasterror(), null, 'errors');
489 }
490 } else {
491 $db->rollback();
492 setEventMessages($line->error, $line->errors, 'errors');
493 }
494 } elseif ($action == 'confirm_delete_subtotalline' && $confirm == 'yes' && $usercancreate) {
495 // Delete line
496 $object->fetch($id);
497 $object->fetch_thirdparty();
498
499 $result = $object->deleteSubtotalLine($langs, GETPOSTINT('lineid'), (bool) GETPOST('deletecorrespondingsubtotalline'), $user);
500 if ($result > 0) {
501 $result = $object->update_price(1);
502
503 if ($result > 0) {
504 $db->commit();
505 $object->fetch($object->id); // Reload lines
506 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$id);
507 exit();
508 } else {
509 $db->rollback();
510 setEventMessages($db->lasterror(), null, 'errors');
511 }
512 } else {
513 setEventMessages($object->error, $object->errors, 'errors');
514 $action = '';
515 }
516 } elseif ($action == 'update_extras' && $permissiontoeditextra) {
517 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
518
519 $attribute_name = GETPOST('attribute', 'aZ09');
520
521 // Fill array 'array_options' with data from update form
522 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
523 if ($ret < 0) {
524 $error++;
525 }
526
527 if (!$error) {
528 $result = $object->updateExtraField($attribute_name, 'BILLREC_MODIFY');
529 if ($result < 0) {
530 setEventMessages($object->error, $object->errors, 'errors');
531 $error++;
532 }
533 }
534
535 if ($error) {
536 $action = 'edit_extras';
537 }
538 }
539
540 // Add a new line
541 if ($action == 'addline' && $usercancreate) {
542 $langs->load('errors');
543 $error = 0;
544
545 // Set if we used free entry or predefined product
546 $predef = '';
547 $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
548 $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
549 $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU', 2);
550 $prod_entry_mode = GETPOST('prod_entry_mode', 'alpha');
551 if ($prod_entry_mode == 'free') {
552 $idprod = 0;
553 } else {
554 $idprod = GETPOSTINT('idprod');
555
556 if (getDolGlobalString('MAIN_DISABLE_FREE_LINES') && $idprod <= 0) {
557 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")), null, 'errors');
558 $error++;
559 }
560 }
561
562 $tva_tx = (GETPOST('tva_tx', 'alpha') ? GETPOST('tva_tx', 'alpha') : 0);
563
564 $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS', 2);
565 $remise_percent = price2num(GETPOST('remise_percent'.$predef), '', 2);
566 if (empty($remise_percent)) {
567 $remise_percent = 0;
568 }
569
570 // Extrafields
571 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
572 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
573 // Unset extrafield
574 if (is_array($extralabelsline)) {
575 // Get extra fields
576 foreach ($extralabelsline as $key => $value) {
577 unset($_POST["options_".$key.$predef]);
578 }
579 }
580
581 if ((empty($idprod) || $idprod < 0) && ($price_ht < 0) && ((float) $qty < 0)) {
582 setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), null, 'errors');
583 $error++;
584 }
585 if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && GETPOST('type') < 0) {
586 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
587 $error++;
588 }
589 if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && (!($price_ht >= 0) || $price_ht == '')) { // Unit price can be 0 but not ''
590 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
591 $error++;
592 }
593 if ($qty == '') {
594 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
595 $error++;
596 }
597 if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && empty($product_desc)) {
598 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
599 $error++;
600 }
601 if ($qty < 0) {
602 $langs->load("errors");
603 setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
604 $error++;
605 }
606
607 if (!$error && ($qty >= 0) && (!empty($product_desc) || (!empty($idprod) && $idprod > 0))) {
608 $ret = $object->fetch($id);
609 if ($ret < 0) {
610 dol_print_error($db, $object->error);
611 exit();
612 }
613 $ret = $object->fetch_thirdparty();
614
615 // Clean parameters
616 $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'));
617 $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'));
618 $price_base_type = (GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT');
619 $tva_npr = "";
620
621 // Define special_code for special lines
622 $special_code = 0;
623 // if (!GETPOST('qty')) $special_code=3; // Options should not exists on invoices
624
625 // Ecrase $pu par celui du produit
626 // Ecrase $desc par celui du produit
627 // Ecrase $base_price_type par celui du produit
628 // Replaces $fk_unit with the product's
629 if (!empty($idprod) && $idprod > 0) {
630 $prod = new Product($db);
631 $prod->fetch($idprod);
632
633 $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
634
635 // Update if prices fields are defined
636 //$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
637 //$tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
638 //if (empty($tva_tx)) {
639 // $tva_npr = 0;
640 //}
641
642 // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
643 $pqp = (GETPOSTINT('pbq') ? GETPOSTINT('pbq') : 0);
644
645 $datapriceofproduct = $prod->getSellPrice($mysoc, $object->thirdparty, $pqp);
646
647 $pu_ht = $datapriceofproduct['pu_ht'];
648 $pu_ttc = $datapriceofproduct['pu_ttc'];
649 $price_min = $datapriceofproduct['price_min'];
650 $price_base_type = empty($datapriceofproduct['price_base_type']) ? 'HT' : $datapriceofproduct['price_base_type'];
651 //$tva_tx = $datapriceofproduct['tva_tx'];
652 //$tva_npr = $datapriceofproduct['tva_npr'];
653
654 $tmpvat = (float) price2num(preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx));
655 $tmpprodvat = price2num(preg_replace('/\s*\‍(.*\‍)/', '', (string) $prod->tva_tx));
656
657 // if price ht was forced (ie: from gui when calculated by margin rate and cost price). TODO Why this ?
658 if (!empty($price_ht)) {
659 $pu_ht = price2num($price_ht, 'MU');
660 $pu_ttc = price2num((float) $pu_ht * (1 + ($tmpvat / 100)), 'MU');
661 } elseif ($tmpvat != $tmpprodvat) {
662 // We reevaluate the price according to vat rate because vat rate of transactionmay differs from
663 // the one oth the product by default (for example when country of seller and buyer are different).
664 if ($price_base_type != 'HT') {
665 $pu_ht = price2num((float) $pu_ttc / (1 + ($tmpvat / 100)), 'MU');
666 } else {
667 $pu_ttc = price2num((float) $pu_ht * (1 + ($tmpvat / 100)), 'MU');
668 }
669 }
670
671 $outputlangs = $langs;
672 $newlang = '';
673 $desc = '';
674
675 // Define output language
676 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
677 if (/* empty($newlang) && */ GETPOST('lang_id', 'aZ09')) {
678 $newlang = GETPOST('lang_id', 'aZ09');
679 }
680 if (empty($newlang)) {
681 $newlang = $object->thirdparty->default_lang;
682 }
683 if (!empty($newlang)) {
684 $outputlangs = new Translate("", $conf);
685 $outputlangs->setDefaultLang($newlang);
686 $outputlangs->load('products');
687 }
688
689 $desc = (!empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
690 } else {
691 $desc = $prod->description;
692 }
693
694 // Add custom code and origin country into description
695 if (!getDolGlobalString('MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE') && (!empty($prod->customcode) || !empty($prod->country_code))) {
696 $tmptxt = '(';
697 // Define output language
698 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
699 if (!empty($prod->customcode)) {
700 $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomsCode").': '.$prod->customcode;
701 }
702 if (!empty($prod->customcode) && !empty($prod->country_code)) {
703 $tmptxt .= ' - ';
704 }
705 if (!empty($prod->country_code)) {
706 $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, '', $db, $outputlangs, 0);
707 }
708 } else {
709 if (!empty($prod->customcode)) {
710 $tmptxt .= $langs->transnoentitiesnoconv("CustomsCode").': '.$prod->customcode;
711 }
712 if (!empty($prod->customcode) && !empty($prod->country_code)) {
713 $tmptxt .= ' - ';
714 }
715 if (!empty($prod->country_code)) {
716 $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, '', $db, $langs, 0);
717 }
718 }
719 $tmptxt .= ')';
720 $desc = dol_concatdesc($desc, $tmptxt);
721 }
722
723 $type = $prod->type;
724 $fk_unit = $prod->fk_unit;
725 } else {
726 $pu_ht = price2num($price_ht, 'MU');
727 $pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
728 $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
729 $tva_tx = str_replace('*', '', $tva_tx);
730 if (empty($tva_tx)) {
731 $tva_npr = 0;
732 }
733 $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
734 $desc = $product_desc;
735 $type = GETPOST('type');
736 $fk_unit = GETPOSTINT('units');
737 }
738
739 $date_start_fill = GETPOSTINT('date_start_fill');
740 $date_end_fill = GETPOSTINT('date_end_fill');
741
742 // Margin
743 $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
744 $buyingprice = price2num(GETPOST('buying_price'.$predef) != '' ? GETPOST('buying_price'.$predef) : ''); // If buying_price is '0', we must keep this value
745
746 // Local Taxes
747 $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $mysoc, $tva_npr);
748 $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $mysoc, $tva_npr);
749
750 $info_bits = 0;
751 if ($tva_npr) {
752 $info_bits |= 0x01;
753 }
754
755 $fk_parent_line = GETPOSTINT('fk_parent_line');
756
757 if ($usercanproductignorepricemin && (!empty($price_min) && ((float) price2num($pu_ht) * (1 - (float) price2num($remise_percent) / 100) < (float) price2num($price_min)))) {
758 $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
759 setEventMessages($mesg, null, 'errors');
760 } else {
761 // Insert line
762 $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, (float) $buyingprice, $fk_parent_line);
763
764 if ($result > 0) {
765 // TODO add "insert" function into FactureLigneRec or add "invoicerecline.class.php" (same of "factureligne.class.php")
766 $objectline = new FactureLigneRec($db);
767 if ($objectline->fetch($result)) {
768 $objectline->array_options = $array_options;
769 $result = $objectline->insertExtraFields();
770 if ($result < 0) {
771 setEventMessages($langs->trans('Error').$result, null, 'errors');
772 }
773 }
774
775 // Define output language and generate document
776 /*if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
777 {
778 // Define output language
779 $outputlangs = $langs;
780 $newlang = '';
781 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
782 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) $newlang = $object->thirdparty->default_lang;
783 if (!empty($newlang)) {
784 $outputlangs = new Translate("", $conf);
785 $outputlangs->setDefaultLang($newlang);
786 }
787 $model=$object->model_pdf;
788 $ret = $object->fetch($id); // Reload to get new records
789
790 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
791 if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
792 }*/
793 $object->fetch($object->id); // Reload lines
794
795 unset($_POST['prod_entry_mode']);
796
797 unset($_POST['qty']);
798 unset($_POST['type']);
799 unset($_POST['remise_percent']);
800 unset($_POST['price_ht']);
801 unset($_POST['multicurrency_price_ht']);
802 unset($_POST['price_ttc']);
803 unset($_POST['tva_tx']);
804 unset($_POST['product_ref']);
805 unset($_POST['product_label']);
806 unset($_POST['product_desc']);
807 unset($_POST['fournprice']);
808 unset($_POST['buying_price']);
809 unset($_POST['np_marginRate']);
810 unset($_POST['np_markRate']);
811 unset($_POST['dp_desc']);
812 unset($_POST['idprod']);
813 unset($_POST['units']);
814
815 unset($_POST['date_starthour']);
816 unset($_POST['date_startmin']);
817 unset($_POST['date_startsec']);
818 unset($_POST['date_startday']);
819 unset($_POST['date_startmonth']);
820 unset($_POST['date_startyear']);
821 unset($_POST['date_endhour']);
822 unset($_POST['date_endmin']);
823 unset($_POST['date_endsec']);
824 unset($_POST['date_endday']);
825 unset($_POST['date_endmonth']);
826 unset($_POST['date_endyear']);
827
828 unset($_POST['date_start_fill']);
829 unset($_POST['date_end_fill']);
830
831 unset($_POST['situations']);
832 unset($_POST['progress']);
833 } else {
834 setEventMessages($object->error, $object->errors, 'errors');
835 }
836
837 $action = '';
838 }
839 }
840 } elseif ($action == 'confirm_addtitleline' && $usercancreate) {
841 // Handling adding a new title line for subtotals module
842
843 $langs->load('subtotals');
844
845 $desc = GETPOST('subtotallinedesc', 'alphanohtml');
846 $depth = GETPOSTINT('subtotallinelevel') ?? 1;
847
848 $subtotal_options = array();
849
850 foreach (FactureRec::$TITLE_OPTIONS as $option) {
851 $value = GETPOST($option, 'alphanohtml');
852 if ($value) {
853 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
854 }
855 }
856
857 // Insert line
858 $result = $object->addSubtotalLine($langs, $desc, (int) $depth, $subtotal_options);
859
860 if ($result >= 0) {
861 if ($result == 0) {
862 setEventMessages($object->error, $object->errors, 'warnings');
863 }
864 $ret = $object->fetch($object->id); // Reload to get new records
865 $object->fetch_thirdparty();
866 } else {
867 setEventMessages($object->error, $object->errors, 'errors');
868 }
869 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$id);
870 exit();
871 } elseif ($action == 'confirm_addsubtotalline' && $usercancreate) {
872 // Handling adding a new subtotal line for subtotals module
873
874 $langs->load('subtotals');
875
876 $choosen_line = GETPOST('subtotaltitleline', 'alphanohtml');
877 foreach ($object->lines as $line) {
878 if ($line->desc == $choosen_line && $line->special_code == SUBTOTALS_SPECIAL_CODE) {
879 $desc = $line->desc;
880 $depth = -$line->qty;
881 }
882 }
883
884 $subtotal_options = array();
885
886 foreach (FactureRec::$SUBTOTAL_OPTIONS as $option) {
887 $value = GETPOST($option, 'alphanohtml');
888 if ($value) {
889 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
890 }
891 }
892
893 // Insert line
894 if (isset($desc) && isset($depth)) {
895 $result = $object->addSubtotalLine($langs, $desc, (int) $depth, $subtotal_options);
896 } else {
897 $result = -1;
898 $object->errors[] = $langs->trans("CorrespondingTitleNotFound");
899 }
900
901 if ($result >= 0) {
902 $ret = $object->fetch($object->id); // Reload to get new records
903 $object->fetch_thirdparty();
904 } else {
905 setEventMessages($object->error, $object->errors, 'errors');
906 }
907 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$id);
908 exit();
909 } elseif ($action == 'updateline' && $usercancreate && !GETPOST('cancel', 'alpha')) {
910 if (!$object->fetch($id) > 0) {
912 }
913 $object->fetch_thirdparty();
914
915 // Clean parameters
916 $date_start = '';
917 $date_end = '';
918 //$date_start = dol_mktime(GETPOSTINT('date_starthour'), GETPOSTINT('date_startmin'), GETPOSTINT('date_startsec'), GETPOSTINT('date_startmonth'), GETPOSTINT('date_startday'), GETPOSTINT('date_startyear'));
919 //$date_end = dol_mktime(GETPOSTINT('date_endhour'), GETPOSTINT('date_endmin'), GETPOSTINT('date_endsec'), GETPOSTINT('date_endmonth'), GETPOSTINT('date_endday'), GETPOSTINT('date_endyear'));
920 $description = dol_htmlcleanlastbr(GETPOST('product_desc', 'restricthtml') ? GETPOST('product_desc', 'restricthtml') : GETPOST('desc', 'restricthtml'));
921 $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
922
923 $pu_ht = price2num(GETPOST('price_ht'), '', 2);
924 $pu_ttc = price2num(GETPOST('price_ttc'), '', 2);
925
926 $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), '', 2);
927 $pu_ttc_devise = price2num(GETPOST('multicurrency_subprice_ttc'), '', 2);
928
929 $qty = (float) price2num(GETPOST('qty', 'alpha'), 'MS');
930
931 // Define info_bits
932 $info_bits = 0;
933 if (preg_match('/\*/', $vat_rate)) {
934 $info_bits |= 0x01;
935 }
936
937 // Define vat_rate
938 $vat_rate = str_replace('*', '', $vat_rate);
939 $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty);
940 $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty);
941
942 // Add buying price
943 $fournprice = (int) (GETPOST('fournprice') ? GETPOST('fournprice') : '');
944 $buyingprice = price2num(GETPOST('buying_price') != '' ? GETPOST('buying_price') : ''); // If buying_price is '0', we must keep this value
945
946 // Prepare a price equivalent for minimum price check
947 $pu_equivalent = $pu_ht;
948 $pu_equivalent_ttc = $pu_ttc;
949
950 $currency_tx = $object->multicurrency_tx;
951
952 // Check if we have a foreign currency
953 // If so, we update the pu_equiv as the equivalent price in base currency
954 if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '' && !empty((float) $currency_tx)) {
955 $pu_equivalent = (float) $pu_ht_devise / (float) $currency_tx;
956 }
957 if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '' && !empty((float) $currency_tx)) {
958 $pu_equivalent_ttc = (float) $pu_ttc_devise / (float) $currency_tx;
959 }
960
961 // TODO $pu_equivalent or $pu_equivalent_ttc must be calculated from the one not null taking into account all taxes
962 /*
963 if ($pu_equivalent) {
964 $tmp = calcul_price_total(1, $pu_equivalent, 0, $vat_rate, -1, -1, 0, 'HT', $info_bits, $type);
965 $pu_equivalent_ttc = ...
966 } else {
967 $tmp = calcul_price_total(1, $pu_equivalent_ttc, 0, $vat_rate, -1, -1, 0, 'TTC', $info_bits, $type);
968 $pu_equivalent_ht = ...
969 }
970 */
971
972 // Extrafields
973 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
974 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
975
976 $objectline = new FactureLigneRec($db);
977 if ($objectline->fetch(GETPOSTINT('lineid'))) {
978 $objectline->array_options = $array_options;
979 $result = $objectline->insertExtraFields();
980 if ($result < 0) {
981 setEventMessages($langs->trans('Error').$result, null, 'errors');
982 }
983 }
984 $position = ($objectline->rang >= 0 ? $objectline->rang : 0);
985
986 // Unset extrafield
987 if (is_array($extralabelsline)) {
988 // Get extra fields
989 foreach ($extralabelsline as $key => $value) {
990 unset($_POST["options_".$key]);
991 }
992 }
993
994 // Define special_code for special lines
995 $special_code = GETPOSTINT('special_code');
996 if ($special_code == 3) {
997 $special_code = 0; // Options should not exists on invoices
998 }
999
1000 /*
1001 $line = new FactureLigne($db);
1002 $line->fetch(GETPOST('lineid', 'int'));
1003 $percent = $line->get_prev_progress($object->id);
1004
1005 ...
1006 */
1007
1008 $remise_percent = price2num(GETPOST('remise_percent'), '', 2);
1009 if (empty($remise_percent)) {
1010 $remise_percent = 0;
1011 }
1012
1013 $price_base_type = 'HT';
1014 $pu = $pu_ht;
1015 if (empty($pu) && !empty($pu_ttc)) {
1016 $pu = $pu_ttc;
1017 $price_base_type = 'TTC';
1018 }
1019
1020 // Check minimum price
1021 $productid = GETPOSTINT('productid');
1022 if (!empty($productid)) {
1023 $product = new Product($db);
1024 $product->fetch($productid);
1025
1026 $type = $product->type;
1027
1028 $price_min = $product->price_min;
1029 if ((getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) && !empty($object->thirdparty->price_level)) {
1030 $price_min = $product->multiprices_min[$object->thirdparty->price_level];
1031 }
1032 $price_min_ttc = $product->price_min_ttc;
1033 if ((getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) && !empty($object->thirdparty->price_level)) {
1034 $price_min_ttc = $product->multiprices_min_ttc[$object->thirdparty->price_level];
1035 }
1036
1037 $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : '');
1038
1039 $typeinvoice = Facture::TYPE_STANDARD;
1040
1041 // Check price is not lower than minimum (check is done only for standard or replacement invoices)
1042 if ($usermustrespectpricemin && ($typeinvoice == Facture::TYPE_STANDARD || $typeinvoice == Facture::TYPE_REPLACEMENT)) {
1043 if ($pu_equivalent && $price_min && (((float) price2num($pu_equivalent) * (1 - (float) $remise_percent / 100)) < (float) price2num($price_min)) && $price_base_type == 'HT') {
1044 $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1045 setEventMessages($mesg, null, 'errors');
1046 $error++;
1047 $action = 'editline';
1048 } elseif ($pu_equivalent_ttc && $price_min_ttc && (((float) price2num($pu_equivalent_ttc) * (1 - (float) $remise_percent / 100)) < (float) price2num($price_min_ttc)) && $price_base_type == 'TTC') {
1049 $mesg = $langs->trans("CantBeLessThanMinPriceInclTax", price(price2num($price_min_ttc, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1050 setEventMessages($mesg, null, 'errors');
1051 $error++;
1052 $action = 'editline';
1053 }
1054 }
1055 } else {
1056 $type = GETPOSTINT('type');
1057 $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
1058
1059 // Check parameters
1060 if (GETPOSTINT('type') < 0) {
1061 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
1062 $error++;
1063 }
1064 }
1065 if ($qty < 0) {
1066 $langs->load("errors");
1067 setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
1068 $error++;
1069 }
1070
1071 $date_start_fill = GETPOSTINT('date_start_fill');
1072 $date_end_fill = GETPOSTINT('date_end_fill');
1073 $fk_parent_line = GETPOST('fk_parent_line', 'int');
1074
1075 // Update line
1076 if (!$error) {
1077 $result = $object->updateline(
1078 GETPOSTINT('lineid'),
1079 $description,
1080 (float) $pu_ht,
1081 (float) $qty,
1082 $vat_rate,
1083 $localtax1_rate,
1084 $localtax1_rate,
1085 GETPOSTINT('productid'),
1086 $remise_percent,
1087 'HT',
1088 $info_bits,
1089 0,
1090 0,
1091 $type,
1092 $position,
1093 $special_code,
1094 $label,
1095 GETPOSTINT('units'),
1096 (float) $pu_ht_devise,
1097 0,
1098 $date_start_fill,
1099 $date_end_fill,
1100 (int) $fournprice,
1101 (float) $buyingprice,
1102 (int) $fk_parent_line
1103 );
1104
1105 if ($result >= 0) {
1106 /*if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
1107 // Define output language
1108 $outputlangs = $langs;
1109 $newlang = '';
1110 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id','aZ09')) {
1111 $newlang = GETPOST('lang_id','aZ09');
1112 }
1113 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1114 $newlang = $object->thirdparty->default_lang;
1115 }
1116 if (!empty($newlang)) {
1117 $outputlangs = new Translate("", $conf);
1118 $outputlangs->setDefaultLang($newlang);
1119 }
1120 $ret = $object->fetch($id); // Reload to get new records
1121 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1122 }*/
1123
1124 $object->fetch($object->id); // Reload lines
1125
1126 unset($_POST['qty']);
1127 unset($_POST['type']);
1128 unset($_POST['productid']);
1129 unset($_POST['remise_percent']);
1130 unset($_POST['price_ht']);
1131 unset($_POST['multicurrency_price_ht']);
1132 unset($_POST['price_ttc']);
1133 unset($_POST['tva_tx']);
1134 unset($_POST['product_ref']);
1135 unset($_POST['product_label']);
1136 unset($_POST['product_desc']);
1137 unset($_POST['fournprice']);
1138 unset($_POST['buying_price']);
1139 unset($_POST['np_marginRate']);
1140 unset($_POST['np_markRate']);
1141
1142 unset($_POST['dp_desc']);
1143 unset($_POST['idprod']);
1144 unset($_POST['units']);
1145
1146 unset($_POST['date_starthour']);
1147 unset($_POST['date_startmin']);
1148 unset($_POST['date_startsec']);
1149 unset($_POST['date_startday']);
1150 unset($_POST['date_startmonth']);
1151 unset($_POST['date_startyear']);
1152 unset($_POST['date_endhour']);
1153 unset($_POST['date_endmin']);
1154 unset($_POST['date_endsec']);
1155 unset($_POST['date_endday']);
1156 unset($_POST['date_endmonth']);
1157 unset($_POST['date_endyear']);
1158
1159 unset($_POST['situations']);
1160 unset($_POST['progress']);
1161 } else {
1162 setEventMessages($object->error, $object->errors, 'errors');
1163 }
1164 }
1165 } elseif ($action == 'updatetitleline' && GETPOSTISSET("save") && $usercancreate && !GETPOST('cancel', 'alpha')) {
1166 // Handling updating a title line for subtotals module
1167
1168 $langs->load('subtotals');
1169
1170 $desc = GETPOST('line_desc', 'alphanohtml') ?? $langs->trans("Title");
1171 $depth = GETPOSTINT('line_depth') ?? 1;
1172
1173 $subtotal_options = array();
1174
1175 foreach (Facture::$TITLE_OPTIONS as $option) {
1176 $value = GETPOST($option, 'alphanohtml');
1177 if ($value) {
1178 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
1179 }
1180 }
1181
1182 // Update line
1183 $result = $object->updateSubtotalLine($langs, GETPOSTINT('lineid'), $desc, $depth, $subtotal_options);
1184
1185 if ($result >= 0) {
1186 if ($result == 0) {
1187 setEventMessages($object->error, $object->errors, 'warnings');
1188 }
1189 $ret = $object->fetch($object->id); // Reload to get new records
1190 $object->fetch_thirdparty();
1191 } else {
1192 setEventMessages($object->error, $object->errors, 'errors');
1193 }
1194 } elseif ($action == 'updatesubtotalline' && GETPOSTISSET("save") && $usercancreate && !GETPOST('cancel', 'alpha')) {
1195 // Handling updating a subtotal line for subtotals module
1196
1197 $langs->load('subtotals');
1198
1199 $desc = GETPOST('line_desc', 'alphanohtml');
1200 $depth = GETPOSTINT('line_depth');
1201
1202 $subtotal_options = array();
1203
1204 foreach (Facture::$SUBTOTAL_OPTIONS as $option) {
1205 $value = GETPOST($option, 'alphanohtml');
1206 if ($value) {
1207 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
1208 }
1209 }
1210
1211 // Update line
1212 $result = $object->updateSubtotalLine($langs, GETPOSTINT('lineid'), $desc, $depth, $subtotal_options);
1213
1214 if ($result > 0) {
1215 $ret = $object->fetch($object->id); // Reload to get new records
1216 $object->fetch_thirdparty();
1217 } else {
1218 setEventMessages($object->error, $object->errors, 'errors');
1219 }
1220 }
1221}
1222
1223
1224/*
1225 * View
1226 */
1227
1228$title = $object->ref." - ".$langs->trans('Card');
1229$help_url = '';
1230
1231llxHeader('', $title, $help_url);
1232
1233$form = new Form($db);
1234$formother = new FormOther($db);
1235if (isModEnabled('project')) {
1236 $formproject = new FormProjets($db);
1237} else {
1238 $formproject = null;
1239}
1240$companystatic = new Societe($db);
1241$invoicerectmp = new FactureRec($db);
1242
1243$now = dol_now();
1244$nowlasthour = dol_get_last_hour($now);
1245
1246
1247// Create mode
1248if ($action == 'create') {
1249 print load_fiche_titre($langs->trans("CreateRepeatableInvoice"), '', 'bill');
1250
1251 $sourceInvoice = new Facture($db); // Source invoice
1252 $factureRec = new FactureRec($db);
1253 $product_static = new Product($db);
1254
1255 if ($sourceInvoice->fetch($id, $ref) > 0) {
1256 $result = $sourceInvoice->getLinesArray();
1257
1258 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1259 print '<input type="hidden" name="token" value="'.newToken().'">';
1260 print '<input type="hidden" name="action" value="add">';
1261 print '<input type="hidden" name="facid" value="'.$sourceInvoice->id.'">';
1262
1263
1264 print dol_get_fiche_head([], '', '', 0);
1265
1266 $rowspan = 4;
1267 if (isModEnabled('project')) {
1268 $rowspan++;
1269 }
1270 if ($sourceInvoice->fk_account > 0) {
1271 $rowspan++;
1272 }
1273
1274 print '<table class="border centpercent">';
1275
1276 $sourceInvoice->fetch_thirdparty();
1277
1278 // Title
1279 print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Title").'</td><td>';
1280 print '<input class="flat quatrevingtpercent" type="text" name="title" value="'.dol_escape_htmltag(GETPOST("title", 'alphanohtml')).'" autofocus>';
1281 print '</td></tr>';
1282
1283 // Third party
1284 print '<tr><td class="titlefieldcreate">'.$langs->trans("Customer").'</td><td>'.$sourceInvoice->thirdparty->getNomUrl(1, 'customer').'</td>';
1285 print '</tr>';
1286
1287 // Invoice subtype
1288 if (getDolGlobalInt('INVOICE_SUBTYPE_ENABLED')) {
1289 print "<tr><td>".$langs->trans("InvoiceSubtype")."</td><td>";
1290 print $form->getSelectInvoiceSubtype(GETPOSTISSET('subtype') ? GETPOSTINT('subtype') : $sourceInvoice->subtype, 'subtype', 0, 0, '');
1291 print "</td></tr>";
1292 }
1293
1294 $note_public = GETPOSTISSET('note_public') ? GETPOST('note_public', 'restricthtml') : $sourceInvoice->note_public;
1295 $note_private = GETPOSTISSET('note_private') ? GETPOST('note_private', 'restricthtml') : $sourceInvoice->note_private;
1296
1297 // Help of substitution key
1298 $substitutionarray = getCommonSubstitutionArray($langs, 2, null, $sourceInvoice);
1299
1300 $substitutionarray['__INVOICE_PREVIOUS_MONTH__'] = $langs->trans("PreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, -1, 'm'), '%m').')';
1301 $substitutionarray['__INVOICE_MONTH__'] = $langs->trans("MonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($sourceInvoice->date, '%m').')';
1302 $substitutionarray['__INVOICE_NEXT_MONTH__'] = $langs->trans("NextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, 1, 'm'), '%m').')';
1303 $substitutionarray['__INVOICE_PREVIOUS_MONTH_TEXT__'] = $langs->trans("TextPreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, -1, 'm'), '%B').')';
1304 $substitutionarray['__INVOICE_MONTH_TEXT__'] = $langs->trans("TextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($sourceInvoice->date, '%B').')';
1305 $substitutionarray['__INVOICE_NEXT_MONTH_TEXT__'] = $langs->trans("TextNextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, 1, 'm'), '%B').')';
1306 $substitutionarray['__INVOICE_PREVIOUS_YEAR__'] = $langs->trans("PreviousYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, -1, 'y'), '%Y').')';
1307 $substitutionarray['__INVOICE_YEAR__'] = $langs->trans("YearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($sourceInvoice->date, '%Y').')';
1308 $substitutionarray['__INVOICE_NEXT_YEAR__'] = $langs->trans("NextYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($sourceInvoice->date, 1, 'y'), '%Y').')';
1309 // Only on template invoices
1310 $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').')';
1311 $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').')';
1312 $substitutionarray['__INVOICE_COUNTER_CURRENT__'] = $langs->trans("Count");
1313 $substitutionarray['__INVOICE_COUNTER_MAX__'] = $langs->trans("MaxPeriodNumber");
1314
1315 $htmltext = '<i>'.$langs->trans("FollowingConstantsWillBeSubstituted").':<br>';
1316 foreach ($substitutionarray as $key => $val) {
1317 $htmltext .= $key.' = '.$langs->trans($val).'<br>';
1318 }
1319 $htmltext .= '</i>';
1320
1321 // Author
1322 print "<tr><td>".$langs->trans("Author")."</td><td>".$user->getFullName($langs)."</td></tr>";
1323
1324 // Payment term
1325 print "<tr><td>".$langs->trans("PaymentConditions")."</td><td>";
1326 print $form->getSelectConditionsPaiements(GETPOSTISSET('cond_reglement_id') ? GETPOSTINT('cond_reglement_id') : $sourceInvoice->cond_reglement_id, 'cond_reglement_id', -1, 0, 0, '');
1327 //$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id');
1328 print "</td></tr>";
1329
1330 // Payment mode
1331 print "<tr><td>".$langs->trans("PaymentMode")."</td><td>";
1332 print img_picto('', 'payment', 'class="pictofixedwidth"');
1333 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);
1334 //$form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', '', 1);
1335 print "</td></tr>";
1336
1337 // Customer Bank Account
1338 print "<tr><td>".$langs->trans('DebitBankAccount')."</td><td>";
1339 $defaultRibId = $sourceInvoice->thirdparty->getDefaultRib();
1340 $form->selectRib(GETPOSTISSET('accountcustomerid') ? GETPOSTINT('accountcustomerid') : $defaultRibId, 'accountcustomerid', '(fk_soc:=:'.$sourceInvoice->socid.")", 1, '', 1);
1341 print "</td></tr>";
1342
1343 print '<script>
1344 $(document).ready(function() {
1345 if($("#selectmode_reglement_id option:selected").data("code") != "' . $factureRec::PAYMENTCODETOEDITSOCIETERIB . '") {
1346 hideselectfksocieterib();
1347 }
1348 $("#selectmode_reglement_id").change(function() {
1349 if($("#selectmode_reglement_id option:selected").data("code") != "'. $factureRec::PAYMENTCODETOEDITSOCIETERIB .'") {
1350 hideselectfksocieterib(1);
1351 } else {
1352 showselectfksocieterib();
1353 }
1354 });
1355 });
1356
1357 function hideselectfksocieterib(empty = 0){
1358 $("#selectaccountcustomerid").closest("tr").hide();
1359 if(empty == 1){
1360 $("#selectaccountcustomerid").val("-1").change();
1361 }
1362 }
1363
1364 function showselectfksocieterib(){
1365 $("#selectaccountcustomerid").closest("tr").show();
1366 }
1367 </script>';
1368
1369 // Bank account
1370 if ($sourceInvoice->fk_account > 0) {
1371 print "<tr><td>".$langs->trans('BankAccount')."</td><td>";
1372 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$sourceInvoice->id, (string) $sourceInvoice->fk_account, 'none');
1373 print "</td></tr>";
1374 }
1375
1376 // Rule for lines dates
1377 if (getDolGlobalInt("FACTUREREC_SUPPORT_RULE_FOR_LINES")) {
1378 print "<tr><td>".$langs->trans("RuleForLinesDates")."</td><td>";
1379 print $form->getSelectRuleForLinesDates(GETPOSTISSET('rule_for_lines_dates') ? GETPOST('rule_for_lines_dates', 'alpha') : $factureRec->rule_for_lines_dates);
1380 print "</td></tr>";
1381 }
1382
1383 //extrafields
1384 $draft = new Facture($db);
1385 $draft->fetch(GETPOSTINT('facid'));
1386
1387 $extralabels = $extrafields->fetch_name_optionals_label($draft->table_element);
1388 if ($draft->fetch_optionals() > 0) {
1389 $sourceInvoice->array_options = array_merge($sourceInvoice->array_options, $draft->array_options);
1390 }
1391
1392 print $sourceInvoice->showOptionals($extrafields, 'create', $parameters);
1393
1394 // Project
1395 if (isModEnabled('project') && is_object($sourceInvoice->thirdparty) && $sourceInvoice->thirdparty->id > 0 && is_object($formproject)) {
1396 $projectid = GETPOST('projectid') ? GETPOST('projectid') : $sourceInvoice->fk_project;
1397 $langs->load('projects');
1398 print '<tr><td>'.$langs->trans('Project').'</td><td>';
1399 print img_picto('', 'project', 'class="pictofixedwidth"');
1400 $numprojet = $formproject->select_projects($sourceInvoice->thirdparty->id, $projectid, 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 0, 0, '');
1401 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>';
1402 print '</td></tr>';
1403 }
1404
1405 // Model pdf
1406 print "<tr><td>".$langs->trans('Model')."</td><td>";
1407 include_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php';
1409 print img_picto('', 'generic', 'class="pictofixedwidth"');
1410 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1411 print $form->selectarray('modelpdf', $list, $conf->global->FACTURE_ADDON_PDF);
1412 print "</td></tr>";
1413
1414 // Public note
1415 print '<tr>';
1416 print '<td class="tdtop">';
1417 print $form->textwithpicto($langs->trans('NotePublic'), $htmltext, 1, 'help', '', 0, 2, 'notepublic');
1418 print '</td>';
1419 print '<td>';
1420 $doleditor = new DolEditor('note_public', $note_public, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
1421 print $doleditor->Create(1);
1422
1423 // Private note
1424 if (empty($user->socid)) {
1425 print '<tr>';
1426 print '<td class="tdtop">';
1427 print $form->textwithpicto($langs->trans('NotePrivate'), $htmltext, 1, 'help', '', 0, 2, 'noteprivate');
1428 print '</td>';
1429 print '<td>';
1430 $doleditor = new DolEditor('note_private', $note_private, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
1431 print $doleditor->Create(1);
1432 // print '<textarea name="note_private" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'.</textarea>
1433 print '</td></tr>';
1434 }
1435
1436 print "</table>";
1437
1438 print dol_get_fiche_end();
1439
1440 // Autogeneration
1441 $title = $langs->trans("Recurrence");
1442 print load_fiche_titre(img_picto('', 'recurring', 'class="pictofixedwidth"').$title, '', '');
1443
1444 print '<span class="opacitymedium">'.$langs->trans("ToCreateARecurringInvoiceGeneAuto", $langs->transnoentitiesnoconv('Module2300Name')).'</span><br><br>';
1445
1446 print dol_get_fiche_head([], '', '', 0);
1447
1448 print '<table class="border centpercent">';
1449
1450 // Frequency + unit
1451 print '<tr><td class="titlefieldcreate">'.$form->textwithpicto($langs->trans("Frequency"), $langs->transnoentitiesnoconv('toolTipFrequency'))."</td><td>";
1452 print '<input type="text" class="width50" name="frequency" value="'.GETPOST('frequency', 'int').'">&nbsp;';
1453 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'));
1454 print "</td></tr>";
1455
1456 // Date next run
1457 print "<tr><td>".$form->textwithpicto($langs->trans('NextDateToExecution'), $langs->trans("NextDateToExecutionHelp"))."</td><td>";
1458 $date_next_execution = isset($date_next_execution) ? $date_next_execution : (GETPOSTINT('remonth') ? dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear')) : -1);
1459 print $form->selectDate($date_next_execution, '', 1, 1, 0, "add", 1, 1);
1460 print "</td></tr>";
1461
1462 // Number max of generation
1463 print "<tr><td>".$langs->trans("MaxPeriodNumber")."</td><td>";
1464 print '<input type="text" class="width50" name="nb_gen_max" value="'.GETPOSTINT('nb_gen_max').'">';
1465 print "</td></tr>";
1466
1467 // Auto validate the invoice
1468 print "<tr><td>".$langs->trans("StatusOfAutoGeneratedInvoices")."</td><td>";
1469 $select = array('0' => $langs->trans('BillStatusDraft'), '1' => $langs->trans('BillStatusValidated'), '2' => $langs->trans('BillStatusValidatedWithSendind'));
1470 print $form->selectarray('auto_validate', $select, GETPOSTINT('auto_validate'));
1471 print "</td></tr>";
1472
1473 // Email template for auto sending invoices
1474 print "<tr id='col_auto_send_model_mail' class='".(GETPOSTINT('auto_validate') != 2 ? 'hidden' : '')."'><td>" . $langs->trans("EmailTemplateForAutoSend") . "</td><td>";
1475 print $form->selectModelMail("auto_send_", "facture_send", 1, 0, GETPOSTINT('auto_send_model_mail'));
1476 print "</td></tr>";
1477 print " <script>
1478 $(document).ready(function() {
1479 $('#auto_validate').on('change', function () {
1480 if(+$(this).val() === 2) {
1481 $('#col_auto_send_model_mail').show();
1482 } else {
1483 $('#col_auto_send_model_mail').hide();
1484 $('#select_auto_send_model_mail').val(0);
1485 }
1486 });
1487 });
1488 </script>";
1489
1490 // Auto generate document
1491 if (getDolGlobalString('INVOICE_REC_CAN_DISABLE_DOCUMENT_FILE_GENERATION')) {
1492 print "<tr><td>".$langs->trans("StatusOfGeneratedDocuments")."</td><td>";
1493 $select = array('0' => $langs->trans('DoNotGenerateDoc'), '1' => $langs->trans('AutoGenerateDoc'));
1494 print $form->selectarray('generate_pdf', $select, GETPOSTINT('generate_pdf'));
1495 print "</td></tr>";
1496 } else {
1497 print '<input type="hidden" name="generate_pdf" value="1">';
1498 }
1499
1500 print "</table>";
1501
1502 print dol_get_fiche_end();
1503
1504
1505 $title = $langs->trans("ProductsAndServices");
1506 if (!isModEnabled('service')) {
1507 $title = $langs->trans("Products");
1508 } elseif (!isModEnabled('product')) {
1509 $title = $langs->trans("Services");
1510 }
1511
1512 print load_fiche_titre($title, '', '');
1513
1514 /*
1515 * Invoice lines
1516 */
1517 print '<div class="div-table-responsive-no-min">';
1518 print '<table id="tablelines" class="noborder noshadow centpercent nomarginbottom">';
1519
1520 // Show object lines
1521 if (!empty($sourceInvoice->lines)) {
1522 $sourceInvoice->printOriginLinesList('', $selectedLines);
1523 }
1524
1525 print "</table>\n";
1526 print '<div>';
1527
1528 print '</td></tr>';
1529
1530 $flag_price_may_change = getDolGlobalString('INVOICE_REC_PRICE_MAY_CHANGE');
1531 if (!empty($flag_price_may_change)) {
1532 print '<tr><td colspan="3" class="left">';
1533 print '<select name="usenewprice" class="flat">';
1534 print '<option value="0">'.$langs->trans("AlwaysUseFixedPrice").'</option>';
1535 print '<option value="1" disabled>'.$langs->trans("AlwaysUseNewPrice").'</option>';
1536 print '</select>';
1537 print '</td></tr>';
1538 }
1539 print "</table>\n";
1540
1541 print '<br>';
1542
1543 print $form->buttonsSaveCancel("Create");
1544
1545 print "</form>\n";
1546 } else {
1547 dol_print_error(null, "Error, no invoice ".$sourceInvoice->id);
1548 }
1549} else {
1550 // View mode
1551 if ($object->id > 0) {
1552 $object->fetch_thirdparty();
1553
1554 $formconfirm = '';
1555 // Confirmation of deletion of product line
1556 if ($action == 'ask_deleteline') {
1557 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 'no', 1);
1558 }
1559 // Confirm delete of repeatable invoice
1560 if ($action == 'delete') {
1561 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteRepeatableInvoice'), $langs->trans('ConfirmDeleteRepeatableInvoice'), 'confirm_delete', '', 'no', 1);
1562 }
1563 // Confirmation of deletion of the subtotal line
1564 if ($action == 'ask_subtotal_deleteline') {
1565 $langs->load("subtotals");
1566 $title = "DeleteSubtotalLine";
1567 $question = "ConfirmDeleteSubtotalLine";
1568 if (GETPOST('type') == 'title') {
1569 $formconfirm = array(array('type' => 'checkbox', 'name' => 'deletecorrespondingsubtotalline', 'label' => $langs->trans("DeleteCorrespondingSubtotalLine"), 'value' => 0));
1570 $title = "DeleteTitleLine";
1571 $question = "ConfirmDeleteTitleLine";
1572 }
1573 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans($title), $langs->trans($question), 'confirm_delete_subtotalline', $formconfirm, 'no', 1);
1574 }
1575
1576 // Subtotal line form
1577 if ($action == 'add_title_line') {
1578 $langs->load('subtotals');
1579 $type = 'title';
1580 $depth_array = $object->getPossibleLevels($langs);
1581 require dol_buildpath('/core/tpl/subtotal_create.tpl.php');
1582 } elseif ($action == 'add_subtotal_line') {
1583 $langs->load('subtotals');
1584 $type = 'subtotal';
1585 $titles = $object->getPossibleTitles();
1586 require dol_buildpath('/core/tpl/subtotal_create.tpl.php');
1587 }
1588
1589 // Call Hook formConfirm
1590 $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
1591 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1592 if (empty($reshook)) {
1593 $formconfirm .= $hookmanager->resPrint;
1594 } elseif ($reshook > 0) {
1595 $formconfirm = $hookmanager->resPrint;
1596 }
1597
1598 print $formconfirm;
1599
1600 $author = new User($db);
1601 $author->fetch($object->user_creation_id);
1602
1603 $head = invoice_rec_prepare_head($object);
1604
1605 print dol_get_fiche_head($head, 'card', $langs->trans("RepeatableInvoice"), -1, $object->picto); // Add a div
1606
1607 // Recurring invoice content
1608
1609 $linkback = '<a href="'.DOL_URL_ROOT.'/compta/facture/invoicetemplate_list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
1610
1611 $morehtmlref = '';
1612 if ($action != 'editref') {
1613 $morehtmlref .= $form->editfieldkey($object->ref, 'ref', $object->ref, $object, $user->hasRight('facture', 'creer'), '', '', 0, 2);
1614 } else {
1615 $morehtmlref .= $form->editfieldval('', 'ref', $object->ref, $object, $user->hasRight('facture', 'creer'), 'string');
1616 }
1617
1618 $morehtmlref .= '<div class="refidno">';
1619 // Ref customer
1620 //$morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_customer, $object, $user->hasRight('facture', 'creer'), 'string', '', 0, 1);
1621 //$morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_customer, $object, $user->hasRight('facture', 'creer'), 'string', '', null, null, '', 1);
1622 // Thirdparty
1623 $morehtmlref .= $object->thirdparty->getNomUrl(1, 'customer');
1624 // Project
1625 if (isModEnabled('project')) {
1626 $langs->load("projects");
1627 $morehtmlref .= '<br>';
1628 if ($user->hasRight('facture', 'creer')) {
1629 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
1630 if ($action != 'classify') {
1631 $morehtmlref .= '<a class="editfielda" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'classify', 'id' => $object->id], true).'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
1632 }
1633 $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');
1634 } else {
1635 if (!empty($object->fk_project)) {
1636 $proj = new Project($db);
1637 $proj->fetch($object->fk_project);
1638 $morehtmlref .= ' : '.$proj->getNomUrl(1);
1639 if ($proj->title) {
1640 $morehtmlref .= ' - '.$proj->title;
1641 }
1642 } else {
1643 $morehtmlref .= '';
1644 }
1645 }
1646 }
1647 $morehtmlref .= '</div>';
1648
1649 $morehtmlstatus = '';
1650
1651 dol_banner_tab($object, 'ref', $linkback, 1, 'title', 'none', $morehtmlref, '', 0, '', $morehtmlstatus);
1652
1653 print '<div class="fichecenter">';
1654 print '<div class="fichehalfleft">';
1655 print '<div class="underbanner clearboth"></div>';
1656
1657 print '<table class="border centpercent tableforfield">';
1658
1659 // Invoice subtype
1660 if (getDolGlobalInt('INVOICE_SUBTYPE_ENABLED')) {
1661 print "<tr><td>".$langs->trans("InvoiceSubtype")."</td><td>";
1662 if ($object->subtype > 0) {
1663 print $object->getSubtypeLabel('facture_rec');
1664 }
1665 print "</td></tr>";
1666 }
1667
1668 // Author
1669 print '<tr><td class="titlefieldmiddle">'.$langs->trans("Author").'</td><td>';
1670 print $author->getNomUrl(-1);
1671 print "</td></tr>";
1672
1673 // Payment term
1674 print '<tr><td>';
1675 print '<table class="nobordernopadding centpercent"><tr><td>';
1676 print $langs->trans('PaymentConditionsShort');
1677 print '</td>';
1678 if ($action != 'editconditions' && $user->hasRight('facture', 'creer')) {
1679 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>';
1680 }
1681 print '</tr></table>';
1682 print '</td><td>';
1683 if ($action == 'editconditions') {
1684 $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->cond_reglement_id, 'cond_reglement_id');
1685 } else {
1686 $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->cond_reglement_id, 'none');
1687 }
1688 print '</td></tr>';
1689
1690 // Payment mode
1691 print '<tr><td>';
1692 print '<table class="nobordernopadding" width="100%"><tr><td>';
1693 print $langs->trans('PaymentMode');
1694 print '</td>';
1695 if ($action != 'editmode' && $user->hasRight('facture', 'creer')) {
1696 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>';
1697 }
1698 print '</tr></table>';
1699 print '</td><td>';
1700 if ($action == 'editmode') {
1701 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
1702 } else {
1703 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->mode_reglement_id, 'none');
1704 }
1705 print '</td></tr>';
1706
1707
1708 // Bank Account Customer
1709 if ($object->mode_reglement_code == $object::PAYMENTCODETOEDITSOCIETERIB) {
1710 print '<tr><td class="nowrap">';
1711 print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
1712 print $langs->trans('DebitBankAccount');
1713 print '<td>';
1714
1715 if (($action != 'editbankaccountcustomer') && $user->hasRight('facture', 'creer') && $object->statut == FactureRec::STATUS_DRAFT) {
1716 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>';
1717 }
1718 print '</tr></table>';
1719 print '</td><td>';
1720
1721 if ($action == 'editbankaccountcustomer') {
1722 $form->formRib($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->fk_societe_rib, 'accountcustomerid', 'fk_soc='.$object->socid, 1, 1);
1723 } else {
1724 $form->formRib($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->fk_societe_rib, 'none', '', 0, 1);
1725 }
1726 print "</td>";
1727 print '</tr>';
1728 }
1729
1730 // Bank Account
1731 print '<tr><td class="nowrap">';
1732 print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
1733 print $langs->trans('BankAccount');
1734 print '<td>';
1735 if (($action != 'editbankaccount') && $user->hasRight('facture', 'creer') && $object->statut == FactureRec::STATUS_DRAFT) {
1736 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>';
1737 }
1738 print '</tr></table>';
1739 print '</td><td>';
1740 if ($action == 'editbankaccount') {
1741 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'fk_account', 1);
1742 } else {
1743 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'none');
1744 }
1745 print "</td>";
1746 print '</tr>';
1747
1748 // Rule for line date. Need a hidden const as this generate unexpected dates into substitution variables
1749 if (getDolGlobalInt("FACTUREREC_SUPPORT_RULE_FOR_LINES")) {
1750 print '<tr><td>';
1751 print '<table class="nobordernopadding centpercent"><tr><td>';
1752 print $langs->trans('RuleForLinesDates');
1753 print '</td>';
1754 if ($action != 'editruleforlinesdates' && $user->hasRight('facture', 'creer')) {
1755 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>';
1756 }
1757 print '</tr></table>';
1758 print '</td><td>';
1759 if ($action == 'editruleforlinesdates') {
1760 $form->form_rule_for_lines_dates($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->rule_for_lines_dates, 'rule_for_lines_dates');
1761 } else {
1762 $form->form_rule_for_lines_dates($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->rule_for_lines_dates, 'none');
1763 }
1764 print '</td></tr>';
1765 }
1766
1767 // Extrafields
1768 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1769
1770 // Model pdf
1771 print '<tr><td class="nowrap">';
1772 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
1773 print $langs->trans('Model');
1774 print '<td>';
1775 if (($action != 'editmodelpdf') && $user->hasRight('facture', 'creer') && $object->statut == FactureRec::STATUS_DRAFT) {
1776 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>';
1777 }
1778 print '</tr></table>';
1779 print '</td><td>';
1780 if ($action == 'editmodelpdf') {
1781 include_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php';
1782 $list = array();
1784 foreach ($models as $k => $model) {
1785 $list[] = str_replace(':', '|', $k).':'.$model;
1786 }
1787 $select = 'select;'.implode(',', $list);
1788 print $form->editfieldval($langs->trans("Model"), 'modelpdf', $object->model_pdf, $object, $user->hasRight('facture', 'creer'), $select);
1789 } else {
1790 print $object->model_pdf;
1791 }
1792 print "</td>";
1793 print '</tr>';
1794
1795 // Other attributes
1796 $cols = 2;
1797
1798
1799 print '</table>';
1800
1801 print '</div>';
1802 print '<div class="fichehalfright">';
1803
1804 print '<!-- amounts -->'."\n";
1805 print '<div class="underbanner clearboth"></div>'."\n";
1806
1807 // Recurrence
1808 $title = $langs->trans("Recurrence");
1809
1810 print '<table class="border tableforfield centpercent">';
1811
1812 include DOL_DOCUMENT_ROOT.'/core/tpl/object_currency_amount.tpl.php';
1813
1814 $sign = 1;
1815 if (getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE_SCREEN') && $object->type == $object::TYPE_CREDIT_NOTE) {
1816 $sign = -1; // We invert sign for output
1817 }
1818
1819 // Amount (excl. tax)
1820 print '<tr><td class="titlefieldmiddle">'.$langs->trans("AmountHT").'</td>';
1821 print '<td class="nowraponall amountcard right">'.price($sign * $object->total_ht, 0, $langs, 1, -1, -1, $conf->currency).'</td>';
1822 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1823 // Multicurrency Amount HT
1824 print '<td class="nowraponall amountcard right">' . price($sign * $object->multicurrency_total_ht, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
1825 }
1826 print '</tr>';
1827
1828 // Amount tax
1829 print '<tr><td>'.$langs->trans("AmountVAT").'</td>';
1830 print '<td class="nowrap amountcard right">'.price($sign * $object->total_tva, 0, $langs, 1, -1, -1, $conf->currency).'</td>';
1831 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1832 // Multicurrency Amount VAT
1833 print '<td class="nowraponall amountcard right">' . price($sign * $object->multicurrency_total_tva, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
1834 }
1835 print '</tr>';
1836
1837 // Amount Local Taxes
1838 if (($mysoc->localtax1_assuj == "1" && $mysoc->useLocalTax(1)) || $object->total_localtax1 != 0) { // Localtax1
1839 print '<tr>';
1840 print '<td class="titlefieldmiddle">'.$langs->transcountry("AmountLT1", $mysoc->country_code).'</td>';
1841 print '<td class="nowraponall amountcard right">'.price($sign * $object->total_localtax1, 1, '', 1, - 1, - 1, $conf->currency).'</td></tr>';
1842 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1843 $object->multicurrency_total_localtax1 = (float) price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT');
1844
1845 print '<td class="nowraponall amountcard right">' . price($sign * $object->multicurrency_total_localtax1, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
1846 }
1847 print '</tr>';
1848 }
1849
1850 if (($mysoc->localtax2_assuj == "1" && $mysoc->useLocalTax(2)) || $object->total_localtax2 != 0) { // Localtax2
1851 print '<tr>';
1852 print '<td>'.$langs->transcountry("AmountLT2", $mysoc->country_code).'</td>';
1853 print '<td class=nowraponall amountcard right">'.price($sign * $object->total_localtax2, 1, '', 1, - 1, - 1, $conf->currency).'</td></tr>';
1854 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1855 $object->multicurrency_total_localtax2 = (float) price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT');
1856
1857 print '<td class="nowraponall amountcard right">' . price($sign * $object->multicurrency_total_localtax2, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
1858 }
1859 print '</tr>';
1860 }
1861
1862 // Add the revenue stamp
1863 /*
1864 if ($selleruserevenustamp) {
1865 print '<tr><td class="titlefieldmiddle">';
1866 print '<table class="nobordernopadding centpercent"><tr><td>';
1867 print $langs->trans('RevenueStamp');
1868 print '</td>';
1869 if ($action != 'editrevenuestamp' && $object->status == $object::STATUS_DRAFT && $usercancreate) {
1870 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>';
1871 }
1872 print '</tr></table>';
1873 print '</td><td class="nowrap amountcard right">';
1874 if ($action == 'editrevenuestamp') {
1875 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1876 print '<input type="hidden" name="token" value="'.newToken().'">';
1877 print '<input type="hidden" name="action" value="setrevenuestamp">';
1878 print '<input type="hidden" name="revenuestamp" id="revenuestamp_val" value="'.price2num($object->revenuestamp).'">';
1879 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1880 print $formother->select_revenue_stamp('', 'revenuestamp_type', $mysoc->country_code);
1881 print ' &rarr; <span id="revenuestamp_span"></span>';
1882 print ' <input type="submit" class="button buttongen button-save small" value="'.$langs->trans('Modify').'">';
1883 print '</form>';
1884 print " <script>
1885 $(document).ready(function(){
1886 js_recalculate_revenuestamp();
1887 $('select[name=revenuestamp_type]').on('change',function(){
1888 js_recalculate_revenuestamp();
1889 });
1890 });
1891 function js_recalculate_revenuestamp(){
1892 var valselected = $('select[name=revenuestamp_type]').val();
1893 console.log('Calculate revenue stamp from '+valselected);
1894 var revenue = 0;
1895 if (valselected.indexOf('%') == -1)
1896 {
1897 revenue = valselected;
1898 }
1899 else
1900 {
1901 var revenue_type = parseFloat(valselected);
1902 var amount_net = ".round($object->total_ht, 2).";
1903 revenue = revenue_type * amount_net / 100;
1904 revenue = revenue.toFixed(2);
1905 }
1906 $('#revenuestamp_val').val(revenue);
1907 $('#revenuestamp_span').html(revenue);
1908 }
1909 </script>";
1910 } else {
1911 print price($object->revenuestamp, 1, '', 1, -1, -1, $conf->currency);
1912 }
1913 print '</td></tr>';
1914 }
1915 */
1916
1917 // Amount TTC
1918 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>';
1919 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1920 // Multicurrency Amount TTC
1921 print '<td class="nowrap amountcard right">' . price($sign * $object->multicurrency_total_ttc, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
1922 }
1923 print '</tr>';
1924
1925 // Recurring info
1926 print '<tr class="liste_titre"><td class="liste_titre">'.img_picto('', 'recurring', 'class="pictofixedwidth"').$title.'</td>';
1927 print '<td></td>';
1928 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1929 print '<td></td>';
1930 }
1931 print '</tr>';
1932
1933 // if "frequency" is empty or = 0, the recurrence is disabled
1934 print '<tr><td style="width: 50%">';
1935 print '<table class="nobordernopadding" width="100%"><tr><td>';
1936 print $langs->trans('Frequency');
1937 print '</td>';
1938 if ($action != 'editfrequency' && $user->hasRight('facture', 'creer')) {
1939 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>';
1940 }
1941 print '</tr></table>';
1942 print '</td><td>';
1943 if ($action == 'editfrequency') {
1944 print '<form method="post" action="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'">';
1945 print '<input type="hidden" name="action" value="setfrequency">';
1946 print '<input type="hidden" name="token" value="'.newToken().'">';
1947 print '<table class="nobordernopadding">';
1948 print '<tr><td>';
1949 print '<input type="text" name="frequency" class="width50 marginrightonly right" value="'.$object->frequency.'">';
1950 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'));
1951 print '</td>';
1952 print '<td class="left"><input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans("Modify").'"></td>';
1953 print '</tr></table></form>';
1954 } else {
1955 if ($object->frequency > 0) {
1956 print $langs->trans('FrequencyPer_'.$object->unit_frequency, $object->frequency);
1957 } else {
1958 print '<span class="opacitymedium">'.$langs->trans("NotARecurringInvoiceTemplate").'</span>';
1959 }
1960 }
1961 print '</td>';
1962 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1963 print '<td></td>';
1964 }
1965 print '</tr>';
1966
1967 if ($object->frequency > 0) {
1968 // Date when (next invoice generation)
1969 print '<tr><td>';
1970 if ($action == 'date_when' || $object->frequency > 0) {
1971 print $form->editfieldkey($form->textwithpicto($langs->trans("NextDateToExecution"), $langs->trans("NextDateToExecutionHelp")), 'date_when', $object->date_when, $object, $user->hasRight('facture', 'creer'), 'day');
1972 } else {
1973 print $form->textwithpicto($langs->trans("NextDateToExecution"), $langs->trans("NextDateToExecutionHelp"));
1974 }
1975 print '</td><td>';
1976 if ($action == 'date_when' || $object->frequency > 0) {
1977 print $form->editfieldval($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->hasRight('facture', 'creer'), 'day', $object->date_when, null, '', '', 0, 'strikeIfMaxNbGenReached');
1978 }
1979 //var_dump(dol_print_date($object->date_when+60, 'dayhour').' - '.dol_print_date($now, 'dayhour'));
1980 if (!$object->isMaxNbGenReached()) {
1981 if (!$object->suspended && $action != 'editdate_when' && $object->frequency > 0 && $object->date_when && $object->date_when < $now) {
1982 print img_warning($langs->trans("Late"));
1983 }
1984 } else {
1985 print img_info($langs->trans("MaxNumberOfGenerationReached"));
1986 }
1987 print '</td>';
1988 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
1989 print '<td></td>';
1990 }
1991 print '</tr>';
1992
1993 // Max period / Rest period
1994 print '<tr><td>';
1995 if ($action == 'nb_gen_max' || $object->frequency > 0) {
1996 print $form->editfieldkey($langs->trans("MaxPeriodNumber"), 'nb_gen_max', (string) $object->nb_gen_max, $object, $user->hasRight('facture', 'creer'));
1997 } else {
1998 print $langs->trans("MaxPeriodNumber");
1999 }
2000 print '</td><td>';
2001 if ($action == 'nb_gen_max' || $object->frequency > 0) {
2002 print $form->editfieldval($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max ? $object->nb_gen_max : '', $object, $user->hasRight('facture', 'creer'));
2003 } else {
2004 print '';
2005 }
2006 print '</td>';
2007 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2008 print '<td></td>';
2009 }
2010 print '</tr>';
2011
2012 // Status of auto generated invoices
2013 print '<tr><td>';
2014 if ($action == 'auto_validate' || $object->frequency > 0) {
2015 print $form->editfieldkey($langs->trans("StatusOfAutoGeneratedInvoices"), 'auto_validate', (string) $object->auto_validate, $object, $user->hasRight('facture', 'creer'));
2016 } else {
2017 print $langs->trans("StatusOfAutoGeneratedInvoices");
2018 }
2019 print '</td><td>';
2020 $select = 'select;0:' . $langs->trans('BillStatusDraft') . ',1:' . $langs->trans('BillStatusValidated') . ',2:' . $langs->trans('BillStatusValidatedWithSendind');
2021 if ($action == 'auto_validate' || $object->frequency > 0) {
2022 print $form->editfieldval($langs->trans("StatusOfAutoGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $user->hasRight('facture', 'creer'), $select);
2023 }
2024 print '</td>';
2025 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2026 print '<td></td>';
2027 }
2028 print '</tr>';
2029
2030 // Email template for auto sending invoices
2031 if ($object->frequency > 0 && $object->auto_validate == 2) {
2032 print '<tr><td style="width: 50%">';
2033 print '<table class="nobordernopadding" width="100%"><tr><td>';
2034 print $langs->trans("EmailTemplateForAutoSend");
2035 print '</td>';
2036 if ($action != 'editEmailTemplate' && $user->hasRight('facture', 'creer')) {
2037 print '<td class="right"><a class="editfielda" href="' . $_SERVER["PHP_SELF"] . '?action=editEmailTemplate&token=' . newToken() . '&facid=' . $object->id . '">' . img_edit($langs->trans('Edit'), 1) . '</a></td>';
2038 }
2039 print '</tr></table>';
2040 print '</td><td>';
2041
2042 if ($action == 'editEmailTemplate') {
2043 // Edit
2044 print '<form method="POST" action="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '">';
2045 print '<input type="hidden" name="token" value="' . newToken() . '">';
2046 print '<input type="hidden" name="action" value="setEmailTemplate">';
2047 print $form->selectModelMail("auto_send_", "facture_send", 1, 0, $object->fk_email_template);
2048 print '<input type="submit" class="button valignmiddle smallpaddingimp" name="modify" value="' . $langs->trans("Modify") . '">';
2049 print '<input type="submit" class="button button-cancel valignmiddle smallpaddingimp" name="cancel" value="' . $langs->trans("Cancel") . '">';
2050 print '</form>';
2051 } else {
2052 // Show
2053 if (!empty($object->fk_email_template)) {
2054 $sql = "SELECT label
2055 FROM ".$db->prefix()."c_email_templates
2056 WHERE rowid = ".((int) $object->fk_email_template);
2057 $result = $db->query($sql);
2058 if ($result) {
2059 if ($obj = $db->fetch_object($result)) {
2060 print $obj->label;
2061 }
2062 }
2063 } else {
2064 print $langs->trans('DefaultMailModel');
2065 }
2066 }
2067
2068 print '</td>';
2069 print '</tr>';
2070 }
2071
2072 // Auto generate documents
2073 if (getDolGlobalString('INVOICE_REC_CAN_DISABLE_DOCUMENT_FILE_GENERATION')) {
2074 print '<tr>';
2075 print '<td>';
2076 if ($action == 'generate_pdf' || $object->frequency > 0) {
2077 print $form->editfieldkey($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', (string) $object->generate_pdf, $object, $user->hasRight('facture', 'creer'));
2078 } else {
2079 print $langs->trans("StatusOfGeneratedDocuments");
2080 }
2081 print '</td>';
2082 print '<td>';
2083 $select = 'select;0:'.$langs->trans('DoNotGenerateDoc').',1:'.$langs->trans('AutogenerateDoc');
2084 if ($action == 'generate_pdf' || $object->frequency > 0) {
2085 print $form->editfieldval($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', $object->generate_pdf, $object, $user->hasRight('facture', 'creer'), $select);
2086 }
2087 print '</td>';
2088 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2089 print '<td></td>';
2090 }
2091 print '</tr>';
2092 } else {
2093 print '<input type="hidden" name="generate_pdf" value="1">';
2094 }
2095 }
2096
2097 print '</table>';
2098
2099 // Frequencry/Recurring section
2100 if ($object->frequency > 0) {
2101 print '<br>';
2102
2103 if (!isModEnabled('cron')) {
2104 print info_admin($langs->trans("EnableAndSetupModuleCron", $langs->transnoentitiesnoconv("Module2300Name")));
2105 }
2106
2107 print '<div class="underbanner clearboth"></div>';
2108 print '<table class="border centpercent tableforfield">';
2109
2110 // Nb of generation already done
2111 print '<tr><td style="width: 50%">'.$langs->trans("NbOfGenerationDone").'</td>';
2112 print '<td>';
2113 print $object->nb_gen_done ? $object->nb_gen_done : '0';
2114 print '</td>';
2115 print '</tr>';
2116
2117 // Date last
2118 print '<tr><td>';
2119 print $langs->trans("DateLastGeneration");
2120 print '</td><td>';
2121 print dol_print_date($object->date_last_gen, 'dayhour');
2122 print '</td>';
2123 print '</tr>';
2124
2125 print '</table>';
2126
2127 print '<br>';
2128 }
2129
2130 print '</div>';
2131 print '</div>';
2132
2133 print '<div class="clearboth"></div><br>';
2134
2135
2136 // Lines
2137 print '<form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline') ? '#add' : '#line_'.GETPOSTINT('lineid')).'" method="POST">';
2138 print '<input type="hidden" name="token" value="' . newToken().'">';
2139 print '<input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">';
2140 print '<input type="hidden" name="mode" value="">';
2141 print '<input type="hidden" name="id" value="' . $object->id.'">';
2142 print '<input type="hidden" name="page_y" value="">';
2143
2144 if (!empty($conf->use_javascript_ajax) && $object->statut == 0) {
2145 if (isModEnabled('subtotals')) {
2146 include DOL_DOCUMENT_ROOT.'/core/tpl/subtotal_ajaxrow.tpl.php';
2147 } else {
2148 include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
2149 }
2150 }
2151
2152 print '<div class="div-table-responsive-no-min">';
2153 print '<table id="tablelines" class="noborder noshadow centpercent nomarginbottom">';
2154 // Show object lines
2155 if (!empty($object->lines)) {
2156 $canchangeproduct = 1;
2157 $object->printObjectLines($action, $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice
2158 }
2159
2160 // Form to add new line
2161 if ($object->status == $object::STATUS_DRAFT && $user->hasRight('facture', 'creer') && $action != 'valid' && $action != 'editline') {
2162 if ($action != 'editline') {
2163 // Add free products/services
2164
2165 $parameters = array();
2166 $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2167 if ($reshook < 0) {
2168 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2169 }
2170 if (empty($reshook)) {
2171 $object->formAddObjectLine(0, $mysoc, $object->thirdparty);
2172 } // No date selector for template invoice
2173 }
2174 }
2175
2176 print "</table>\n";
2177 print '</div>';
2178
2179 print "</form>\n";
2180
2181 print dol_get_fiche_end();
2182
2183
2184 /*
2185 * Action bar
2186 */
2187 print '<div class="tabsAction">';
2188
2189 $parameters = array();
2190 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2191 if (empty($reshook)) {
2192 $params = array(
2193 'attr' => array(
2194 'class' => 'classfortooltip',
2195 ),
2196 );
2197
2198 // Subtotal
2199 if (empty($object->suspended) && isModEnabled('subtotals')
2200 && (getDolGlobalInt('SUBTOTAL_TITLE_'.strtoupper($object->element)) || getDolGlobalInt('SUBTOTAL_'.strtoupper($object->element)))) {
2201 $langs->load("subtotals");
2202
2203 $url_button = array();
2204
2205 $url_button[] = array(
2206 'lang' => 'subtotals',
2207 'enabled' => (isModEnabled('invoice') && $object->status == Facture::STATUS_DRAFT && getDolGlobalInt('SUBTOTAL_TITLE_'.strtoupper($object->element))),
2208 'perm' => (bool) $usercancreate,
2209 'label' => $langs->trans('AddTitleLine'),
2210 'url' => '/compta/facture/card-rec.php?id='.$object->id.'&action=add_title_line&token='.newToken()
2211 );
2212
2213 $url_button[] = array(
2214 'lang' => 'subtotals',
2215 'enabled' => (isModEnabled('invoice') && $object->status == Facture::STATUS_DRAFT && getDolGlobalInt('SUBTOTAL_'.strtoupper($object->element))),
2216 'perm' => (bool) $usercancreate,
2217 'label' => $langs->trans('AddSubtotalLine'),
2218 'url' => '/compta/facture/card-rec.php?id='.$object->id.'&action=add_subtotal_line&token='.newToken()
2219 );
2220 print dolGetButtonAction('', $langs->trans('Subtotal'), 'default', $url_button, '', true);
2221 }
2222
2223 if (empty($object->suspended)) {
2224 if ($user->hasRight('facture', 'creer')) {
2225 if (!empty($object->frequency) && $object->nb_gen_max > 0 && ($object->nb_gen_done >= $object->nb_gen_max)) {
2226 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("MaxGenerationReached")) . '">' . $langs->trans("CreateBill") . '</a></div>';
2227 } else {
2228 if (empty($object->frequency) || $object->date_when <= $nowlasthour) {
2229 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>';
2230 } else {
2231 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("DateIsNotEnough")) . '">' . $langs->trans("CreateBill") . '</a></div>';
2232 }
2233 }
2234 } else {
2235 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#">' . $langs->trans("CreateBill") . '</a></div>';
2236 }
2237 }
2238
2239 if ($user->hasRight('facture', 'creer')) {
2240 if (empty($object->suspended)) {
2241 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>';
2242 } else {
2243 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>';
2244 }
2245 }
2246
2247 // Delete
2248 print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=delete&token=' . newToken(), 'delete', $user->hasRight('facture', 'supprimer'));
2249 }
2250 print '</div>';
2251
2252
2253
2254 print '<div class="fichecenter"><div class="fichehalfleft">';
2255 print '<a name="builddoc"></a>'; // ancre
2256
2257
2258 // Show links to link elements
2259 $tmparray = $form->showLinkToObjectBlock($object, array(), array('invoice'), 1);
2260 $linktoelem = $tmparray['linktoelem'];
2261 $htmltoenteralink = $tmparray['htmltoenteralink'];
2262 print $htmltoenteralink;
2263
2264 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
2265
2266
2267 print '</div>';
2268 print '<div class="fichehalfright">';
2269
2270 $MAXEVENT = 10;
2271
2272 $morehtmlcenter = '<div class="nowraponall">';
2273 //$morehtmlcenter .= dolGetButtonTitle($langs->trans('FullConversation'), '', 'fa fa-comments imgforviewmode', DOL_URL_ROOT.'/compta/facture/messaging.php?id='.$object->id);
2274 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullList'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/compta/facture/agenda-rec.php?id='.$object->id);
2275 $morehtmlcenter .= '</div>';
2276
2277 // List of actions on element
2278 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
2279 $formactions = new FormActions($db);
2280 $somethingshown = $formactions->showactions($object, $object->element, (is_object($object->thirdparty) ? $object->thirdparty->id : 0), 1, '', $MAXEVENT, '', $morehtmlcenter);
2281
2282 print '</div>';
2283 print '</div>';
2284 } else {
2285 print $langs->trans("NoRecordFound");
2286 }
2287}
2288
2289// End of page
2290llxFooter();
2291$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
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 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 to help generate other html components 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.
global $mysoc
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:650
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:126
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.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
$date_start
Variables from include:
dol_now($mode='gmt')
Return date for now.
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...
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.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='')
Show information in HTML for admin users or standard users.
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.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
GETPOSTFLOAT($paramname, $rounding='', $option=2)
Return the value of a $_GET or $_POST supervariable, converted into float.
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_clone($srcobject, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
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 rate, 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.
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
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.