dolibarr 23.0.3
card.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2003-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2019 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2014 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
6 * Copyright (C) 2010-2017 Juanjo Menent <jmenent@2byte.es>
7 * Copyright (C) 2013 Christophe Battarel <christophe.battarel@altairis.fr>
8 * Copyright (C) 2013-2014 Florian Henry <florian.henry@open-concept.pro>
9 * Copyright (C) 2014-2020 Ferran Marcet <fmarcet@2byte.es>
10 * Copyright (C) 2014-2016 Marcos García <marcosgdf@gmail.com>
11 * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
12 * Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
13 * Copyright (C) 2023 Charlene Benke <charlene@patas-monkey.com>
14 * Copyright (C) 2023 Nick Fragoulis
15 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
16 * Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 3 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program. If not, see <https://www.gnu.org/licenses/>.
30 */
31
38require "../main.inc.php";
48require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
49require_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
50require_once DOL_DOCUMENT_ROOT.'/core/lib/contract.lib.php';
51require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
52require_once DOL_DOCUMENT_ROOT.'/core/modules/contract/modules_contract.php';
53require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
54require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
55require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
56require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
57require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
58if (isModEnabled("propal")) {
59 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
60}
61if (isModEnabled('project')) {
62 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
63 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
64}
65require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
66
67// Load translation files required by the page
68$langs->loadLangs(array("contracts", "orders", "companies", "bills", "products", 'compta', 'propal'));
69
70$action = GETPOST('action', 'aZ09');
71$confirm = GETPOST('confirm', 'alpha');
72$cancel = GETPOST('cancel', 'alpha');
73$backtopage = GETPOST('backtopage', 'alpha');
74$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
75
76$socid = GETPOSTINT('socid');
77$id = GETPOSTINT('id');
78$ref = GETPOST('ref', 'alpha');
79$origin = GETPOST('origin', 'alpha');
80$originid = GETPOSTINT('originid');
81$idline = GETPOSTINT('elrowid') ? GETPOSTINT('elrowid') : GETPOSTINT('rowid');
82$attribute = GETPOST('attribute', 'aZ09');
83
84// PDF
85$hidedetails = (GETPOSTINT('hidedetails') ? GETPOSTINT('hidedetails') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 1 : 0));
86$hidedesc = (GETPOSTINT('hidedesc') ? GETPOSTINT('hidedesc') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 1 : 0));
87$hideref = (GETPOSTINT('hideref') ? GETPOSTINT('hideref') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF') ? 1 : 0));
88
89
90$datecontrat = '';
91$moreparam = '';
92$note_public = '';
93$note_private = '';
94$usehm = getDolGlobalInt('MAIN_USE_HOURMIN_IN_DATE_RANGE');
95
96// Security check
97if ($user->socid) {
98 $socid = $user->socid;
99}
100
101// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
102$hookmanager->initHooks(array('contractcard', 'globalcard'));
103
104$object = new Contrat($db);
105$extrafields = new ExtraFields($db);
106$ret = 0;
107$pu_ht = null; // Init for static analysis
108$pu_ttc = null; // Init for static analysis
109
110// Load object
111if ($id > 0 || !empty($ref) && $action != 'add') {
112 $ret = $object->fetch($id, $ref);
113 if ($ret > 0) {
114 $ret = $object->fetch_thirdparty();
115 }
116 if ($ret < 0) {
117 dol_print_error(null, $object->error);
118 }
119}
120
121// fetch optionals attributes and labels
122$extrafields->fetch_name_optionals_label($object->table_element);
123
124// fetch optionals attributes lines and labels
125$extralabelslines = $extrafields->fetch_name_optionals_label($object->table_element_line);
126
127$permissionnote = $user->hasRight('contrat', 'creer'); // Used by the include of actions_setnotes.inc.php
128$permissiondellink = $user->hasRight('contrat', 'creer'); // Used by the include of actions_dellink.inc.php
129$permissiontodelete = ($user->hasRight('contrat', 'creer') && $object->status == $object::STATUS_DRAFT) || $user->hasRight('contrat', 'supprimer');
130$permissiontoadd = $user->hasRight('contrat', 'creer'); // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
131$permissiontoedit = $permissiontoadd;
132$permissiontoactivate = $user->hasRight('contrat', 'activer');
133$permissiontodisable = $user->hasRight('contrat', 'desactiver'); // TODO use same than $permissiontoactivate
134$permissiontoeditextra = $permissiontoadd;
135if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
136 // For action 'update_extras', is there a specific permission set for the attribute to update
137 $permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
138}
139
140$error = 0;
141
142// Security check
143$result = restrictedArea($user, 'contrat', $object->id);
144
145if (!($object->id > 0) && ($action == 'view' || $action == '')) {
147}
148
149
150/*
151 * Actions
152 */
153
154$parameters = array('socid' => $socid);
155$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
156if ($reshook < 0) {
157 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
158}
159if (empty($reshook)) {
160 $backurlforlist = dolBuildUrl(DOL_URL_ROOT . '/contrat/list.php');
161
162 if (empty($backtopage) || ($cancel && empty($id))) {
163 if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
164 if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
165 $backtopage = $backurlforlist;
166 } else {
167 $backtopage = dolBuildUrl(DOL_URL_ROOT . '/contrat/card.php', ['id'=> ((!empty($id) && $id > 0) ? $id : '__ID__')]);
168 }
169 }
170 }
171
172 if ($cancel) {
173 if (!empty($backtopageforcancel)) {
174 header("Location: ".$backtopageforcancel);
175 exit;
176 } elseif (!empty($backtopage)) {
177 header("Location: ".$backtopage);
178 exit;
179 }
180 $action = '';
181 }
182
183 include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not includ_once
184
185 include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
186
187 include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; // Must be 'include', not 'include_once'
188
189 if ($action == 'confirm_active' && $confirm == 'yes' && $permissiontoactivate) {
190 $date_start = '';
191 $date_end = '';
192 if (GETPOST('startmonth') && GETPOST('startday') && GETPOST('startyear')) {
193 $date_start = dol_mktime(GETPOSTINT('starthour'), GETPOSTINT('startmin'), 0, GETPOSTINT('startmonth'), GETPOSTINT('startday'), GETPOSTINT('startyear'));
194 }
195 if (GETPOST('endmonth') && GETPOST('endday') && GETPOST('endyear')) {
196 $date_end = dol_mktime(GETPOSTINT('endhour'), GETPOSTINT('endmin'), 0, GETPOSTINT('endmonth'), GETPOSTINT('endday'), GETPOSTINT('endyear'));
197 }
198
199 $result = $object->active_line($user, GETPOSTINT('ligne'), $date_start, $date_end, GETPOST('comment'));
200
201 if ($result > 0) {
202 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
203 exit;
204 } else {
205 setEventMessages($object->error, $object->errors, 'errors');
206 }
207 } elseif ($action == 'confirm_sign' && $confirm == 'yes' && $user->hasRight('contract', 'creer')) {
208 $result = $object->setSignedStatus($user, GETPOSTINT('signed_status'), 0, 'CONTRACT_MODIFY');
209 if ($result >= 0) {
210 header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
211 exit;
212 } else {
213 setEventMessages($object->error, $object->errors, 'errors');
214 }
215 } elseif ($action == 'confirm_unsign' && $confirm == 'yes' && $user->hasRight('contract', 'creer')) {
216 $result = $object->setSignedStatus($user, Contrat::$SIGNED_STATUSES['STATUS_NO_SIGNATURE'], 0, 'CONTRACT_MODIFY');
217 if ($result >= 0) {
218 header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
219 exit;
220 } else {
221 setEventMessages($object->error, $object->errors, 'errors');
222 }
223 } elseif ($action == 'confirm_closeline' && $confirm == 'yes' && $permissiontodisable) {
224 $date_end = '';
225 if (GETPOST('endmonth') && GETPOST('endday') && GETPOST('endyear')) {
226 $date_end = dol_mktime(GETPOSTINT('endhour'), GETPOSTINT('endmin'), 0, GETPOSTINT('endmonth'), GETPOSTINT('endday'), GETPOSTINT('endyear'));
227 }
228 if (!$date_end) {
229 $error++;
230 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DateEnd")), null, 'errors');
231 }
232 if (!$error) {
233 $result = $object->close_line($user, GETPOSTINT('ligne'), $date_end, urldecode(GETPOST('comment')));
234 if ($result > 0) {
235 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
236 exit;
237 } else {
238 setEventMessages($object->error, $object->errors, 'errors');
239 }
240 }
241 }
242
243 if (GETPOST('mode') == 'predefined') {
244 $date_start = '';
245 $date_end = '';
246 if (GETPOST('date_startmonth') && GETPOST('date_startday') && GETPOST('date_startyear')) {
247 $date_start = dol_mktime(GETPOSTINT('date_starthour'), GETPOSTINT('date_startmin'), 0, GETPOSTINT('date_startmonth'), GETPOSTINT('date_startday'), GETPOSTINT('date_startyear'));
248 }
249 if (GETPOST('date_endmonth') && GETPOST('date_endday') && GETPOST('date_endyear')) {
250 $date_end = dol_mktime(GETPOSTINT('date_endhour'), GETPOSTINT('date_endmin'), 0, GETPOSTINT('date_endmonth'), GETPOSTINT('date_endday'), GETPOSTINT('date_endyear'));
251 }
252 }
253
254 // Param dates
255 $date_start_update = '';
256 $date_end_update = '';
257 $date_start_real_update = '';
258 $date_end_real_update = '';
259 if (GETPOST('date_start_updatemonth') && GETPOST('date_start_updateday') && GETPOST('date_start_updateyear')) {
260 $date_start_update = dol_mktime(GETPOSTINT('date_start_updatehour'), GETPOSTINT('date_start_updatemin'), 0, GETPOSTINT('date_start_updatemonth'), GETPOSTINT('date_start_updateday'), GETPOSTINT('date_start_updateyear'));
261 }
262 if (GETPOST('date_end_updatemonth') && GETPOST('date_end_updateday') && GETPOST('date_end_updateyear')) {
263 $date_end_update = dol_mktime(GETPOSTINT('date_end_updatehour'), GETPOSTINT('date_end_updatemin'), 0, GETPOSTINT('date_end_updatemonth'), GETPOSTINT('date_end_updateday'), GETPOSTINT('date_end_updateyear'));
264 }
265 if (GETPOST('date_start_real_updatemonth') && GETPOST('date_start_real_updateday') && GETPOST('date_start_real_updateyear')) {
266 $date_start_real_update = dol_mktime(GETPOSTINT('date_start_real_updatehour'), GETPOSTINT('date_start_real_updatemin'), 0, GETPOSTINT('date_start_real_updatemonth'), GETPOSTINT('date_start_real_updateday'), GETPOSTINT('date_start_real_updateyear'));
267 }
268 if (GETPOST('date_end_real_updatemonth') && GETPOST('date_end_real_updateday') && GETPOST('date_end_real_updateyear')) {
269 $date_end_real_update = dol_mktime(GETPOSTINT('date_end_real_updatehour'), GETPOSTINT('date_end_real_updatemin'), 0, GETPOSTINT('date_end_real_updatemonth'), GETPOSTINT('date_end_real_updateday'), GETPOSTINT('date_end_real_updateyear'));
270 }
271 if (GETPOST('remonth') && GETPOST('reday') && GETPOST('reyear')) {
272 $datecontrat = dol_mktime(GETPOSTINT('rehour'), GETPOSTINT('remin'), 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
273 }
274
275 // Add contract
276 if ($action == 'add' && $user->hasRight('contrat', 'creer')) {
277 // Check
278 if (empty($datecontrat)) {
279 $error++;
280 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
281 $action = 'create';
282 }
283
284 if ($socid < 1) {
285 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ThirdParty")), null, 'errors');
286 $action = 'create';
287 $error++;
288 }
289
290 // Fill array 'array_options' with data from add form
291 $ret = $extrafields->setOptionalsFromPost(null, $object);
292 if ($ret < 0) {
293 $error++;
294 $action = 'create';
295 }
296
297 if (!$error) {
298 $object->socid = $socid;
299 $object->date_contrat = $datecontrat;
300
301 $object->commercial_suivi_id = GETPOSTINT('commercial_suivi_id');
302 $object->commercial_signature_id = GETPOSTINT('commercial_signature_id');
303
304 $object->note_private = GETPOST('note_private', 'alpha');
305 $object->note_public = GETPOST('note_public', 'alpha');
306 $object->fk_project = GETPOSTINT('projectid');
307 $object->remise_percent = price2num(GETPOST('remise_percent'), '', 2);
308 $object->ref = GETPOST('ref', 'alpha');
309 $object->ref_customer = GETPOST('ref_customer', 'alpha');
310 $object->ref_supplier = GETPOST('ref_supplier', 'alpha');
311
312 // If creation from another object of another module (Example: origin=propal, originid=1)
313 if (!empty($origin) && !empty($originid)) {
314 // Parse element/subelement (ex: project_task)
315 $element = $subelement = $origin;
316 if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
317 $element = $regs[1];
318 $subelement = $regs[2];
319 }
320
321 // For compatibility
322 $classname = '';
323 if ($element == 'order') {
324 $element = $subelement = 'commande';
325 }
326 if ($element == 'propal') {
327 $element = 'comm/propal';
328 $subelement = 'propal';
329 }
330 if ($element == 'invoice' || $element == 'facture') {
331 $element = 'compta/facture';
332 $subelement = 'facture';
333 }
334 if ($element == 'facturerec' || $element == 'facture_rec') {
335 // FactureRec lives in compta/facture/class/facture-rec.class.php (#34775)
336 $element = 'compta/facture';
337 $subelement = 'facture-rec';
338 $classname = 'FactureRec';
339 }
340 if ($element == 'facture_fourn_rec' || $element == 'invoice_supplier_rec') {
341 $element = 'fourn';
342 $subelement = 'fournisseur.facture-rec';
343 $classname = 'FactureFournisseurRec';
344 }
345
346 $object->origin = $origin;
347 $object->origin_id = $originid;
348
349 // Possibility to add external linked objects with hooks
350 $object->linked_objects[$object->origin] = $object->origin_id;
351 if (GETPOSTISARRAY('other_linked_objects')) {
352 $object->linked_objects = array_merge($object->linked_objects, GETPOST('other_linked_objects', 'array:int'));
353 }
354
355 $id = $object->create($user);
356 if ($id > 0) {
357 dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
358
359 if (empty($classname)) {
360 $classname = ucfirst($subelement);
361 }
362 $srcobject = new $classname($db);
363 '@phan-var-force Commande|Propal|Facture $srcobject'; // Can be other class, but CommonObject is too Generic
364
365 dol_syslog("Try to find source object origin=".$object->origin." originid=".$object->origin_id." to add lines");
366 $result = $srcobject->fetch($object->origin_id);
367 if ($result > 0) {
368 $srcobject->fetch_thirdparty();
369 $lines = $srcobject->lines;
370 if (empty($lines) && method_exists($srcobject, 'fetch_lines')) {
371 $srcobject->fetch_lines();
372 $lines = $srcobject->lines;
373 }
374
375 $fk_parent_line = 0;
376 $num = count($lines);
377
378 for ($i = 0; $i < $num; $i++) {
379 $product_type = ($lines[$i]->product_type ? $lines[$i]->product_type : 0);
380
381 if ($product_type == 1 || (getDolGlobalString('CONTRACT_SUPPORT_PRODUCTS') && in_array($product_type, array(0, 1)))) { // TODO Exclude also deee
382 // service prédéfini
383 if ($lines[$i]->fk_product > 0) {
384 $product_static = new Product($db);
385
386 // Define output language
387 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
388 $prod = new Product($db);
389 $prod->id = $lines[$i]->fk_product;
390 $prod->getMultiLangs();
391
392 $outputlangs = $langs;
393 $newlang = '';
394 if (/* empty($newlang) && */ GETPOST('lang_id', 'aZ09')) {
395 $newlang = GETPOST('lang_id', 'aZ09');
396 }
397 if (empty($newlang)) {
398 $newlang = $srcobject->thirdparty->default_lang;
399 }
400 if (!empty($newlang)) {
401 $outputlangs = new Translate("", $conf);
402 $outputlangs->setDefaultLang($newlang);
403 }
404
405 $label = (!empty($prod->multilangs[$outputlangs->defaultlang]["libelle"])) ? $prod->multilangs[$outputlangs->defaultlang]["libelle"] : $lines[$i]->product_label;
406 } else {
407 $label = $lines[$i]->product_label;
408 }
409 $desc = ($lines[$i]->desc && $lines[$i]->desc != $lines[$i]->label) ? dol_htmlentitiesbr($lines[$i]->desc) : '';
410 } else {
411 $desc = dol_htmlentitiesbr($lines[$i]->desc);
412 }
413
414 // Extrafields
415 $array_options = array();
416 // For avoid conflicts if trigger used
417 if (method_exists($lines[$i], 'fetch_optionals')) {
418 $lines[$i]->fetch_optionals();
419 $array_options = $lines[$i]->array_options;
420 }
421
422 $txtva = $lines[$i]->vat_src_code ? $lines[$i]->tva_tx.' ('.$lines[$i]->vat_src_code.')' : $lines[$i]->tva_tx;
423
424 // View third's localtaxes for now
425 $localtax1_tx = get_localtax($txtva, 1, $object->thirdparty);
426 $localtax2_tx = get_localtax($txtva, 2, $object->thirdparty);
427
428 $result = $object->addline(
429 $desc,
430 $lines[$i]->subprice,
431 $lines[$i]->qty,
432 $txtva,
433 $localtax1_tx,
434 $localtax2_tx,
435 $lines[$i]->fk_product,
436 $lines[$i]->remise_percent,
437 $lines[$i]->date_start,
438 $lines[$i]->date_end,
439 'HT',
440 0,
441 $lines[$i]->info_bits,
442 $lines[$i]->fk_fournprice,
443 $lines[$i]->pa_ht,
444 $array_options,
445 (int) $lines[$i]->fk_unit,
446 $num + 1
447 );
448
449 if ($result < 0) {
450 $error++;
451 break;
452 }
453 }
454 }
455 } else {
456 setEventMessages($srcobject->error, $srcobject->errors, 'errors');
457 $error++;
458 }
459
460 // Hooks
461 $parameters = array('objFrom' => $srcobject);
462 $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been
463 // modified by hook
464 if ($reshook < 0) {
465 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
466 $error++;
467 }
468 } else {
469 setEventMessages($object->error, $object->errors, 'errors');
470 $error++;
471 }
472 if ($error) {
473 $action = 'create';
474 }
475 } else {
476 $result = $object->create($user);
477 if ($result > 0) {
478 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
479 exit;
480 } else {
481 setEventMessages($object->error, $object->errors, 'errors');
482 }
483 $action = 'create';
484 }
485 }
486 } elseif ($action == 'classin' && $user->hasRight('contrat', 'creer')) {
487 $object->setProject(GETPOSTINT('projectid'));
488 } elseif ($action == 'addline' && $user->hasRight('contrat', 'creer')) {
489 // Add a new line
490 // Set if we used free entry or predefined product
491 $predef = '';
492 $line_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
493
494 $price_ht = '';
495 $price_ht_devise = '';
496 $price_ttc = '';
497 $price_ttc_devise = '';
498
499 $rang = count($object->lines) + 1;
500
501 if (GETPOST('price_ht') !== '') {
502 $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
503 }
504 if (GETPOST('multicurrency_price_ht') !== '') {
505 $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU', 2);
506 }
507 if (GETPOST('price_ttc') !== '') {
508 $price_ttc = price2num(GETPOST('price_ttc'), 'MU', 2);
509 }
510 if (GETPOST('multicurrency_price_ttc') !== '') {
511 $price_ttc_devise = price2num(GETPOST('multicurrency_price_ttc'), 'CU', 2);
512 }
513
514 if (GETPOST('prod_entry_mode', 'alpha') == 'free') {
515 $idprod = 0;
516 } else {
517 $idprod = GETPOSTINT('idprod');
518
519 if (getDolGlobalString('MAIN_DISABLE_FREE_LINES') && $idprod <= 0) {
520 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")), null, 'errors');
521 $error++;
522 }
523 }
524
525 $tva_tx = GETPOST('tva_tx', 'alpha');
526
527 $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS');
528 $remise_percent = (GETPOSTISSET('remise_percent'.$predef) ? price2num(GETPOST('remise_percent'.$predef), '', 2) : 0);
529 if (empty($remise_percent)) {
530 $remise_percent = 0;
531 }
532
533 if ($qty == '') {
534 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Qty")), null, 'errors');
535 $error++;
536 }
537 if (GETPOST('prod_entry_mode', 'alpha') == 'free' && (empty($idprod) || $idprod < 0) && empty($line_desc)) {
538 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Description")), null, 'errors');
539 $error++;
540 }
541
542 $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'));
543 $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'));
544 if (!empty($date_start) && !empty($date_end) && $date_start > $date_end) {
545 setEventMessages($langs->trans("Error").': '.$langs->trans("DateStartPlanned").' > '.$langs->trans("DateEndPlanned"), null, 'errors');
546 $error++;
547 }
548
549 // Extrafields
550 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
551 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
552 // Unset extrafield
553 if (is_array($extralabelsline)) {
554 // Get extra fields
555 foreach ($extralabelsline as $key => $value) {
556 unset($_POST["options_".$key]);
557 }
558 }
559
560 if (!$error) {
561 // Clean parameters
562 $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'));
563 $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'));
564
565 $price_base_type = '';
566 $price_min = '';
567 // Ecrase $tva_tx par celui du produit. TODO Remove this once vat selection is open
568 // Get and check minimum price
569 if ($idprod > 0) {
570 $prod = new Product($db);
571 $prod->fetch($idprod);
572
573 // Update if prices fields are defined
574 /*$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
575 $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
576 if (empty($tva_tx)) {
577 }*/
578 $tva_npr = 0;
579
580 $price_min = $prod->price_min;
581 $price_min_ttc = $prod->price_min_ttc;
582
583 // On defini prix unitaire
584 if (getDolGlobalString('PRODUIT_MULTIPRICES') && $object->thirdparty->price_level) {
585 $price_min = $prod->multiprices_min[$object->thirdparty->price_level];
586 $price_min_ttc = $prod->multiprices_min_ttc[$object->thirdparty->price_level];
587 } elseif (getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) {
588 // If price per customer
589 require_once DOL_DOCUMENT_ROOT.'/product/class/productcustomerprice.class.php';
590
591 $prodcustprice = new ProductCustomerPrice($db);
592
593 $filter = array('t.fk_product' => (string) $prod->id, 't.fk_soc' => (string) $object->thirdparty->id);
594
595 $result = $prodcustprice->fetchAll('', '', 0, 0, $filter);
596 if ($result) {
597 if (count($prodcustprice->lines) > 0) {
598 $date_now = (int) floor(dol_now() / 86400) * 86400; // date without hours
599 foreach ($prodcustprice->lines as $k => $custprice_line) {
600 if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
601 $price_min = price($custprice_line->price_min);
602 $price_min_ttc = price($custprice_line->price_min_ttc);
603 /*$tva_tx = $custprice_line->tva_tx;
604 if ($custprice_line->default_vat_code && !preg_match('/\‍(.*\‍)/', $tva_tx)) {
605 $tva_tx .= ' ('.$custprice_line->default_vat_code.')';
606 }
607 $tva_npr = $custprice_line->recuperableonly;
608 if (empty($tva_tx)) {
609 $tva_npr = 0;
610 }*/
611 break;
612 }
613 }
614 }
615 }
616 }
617
618 $tmpvat = price2num(preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx));
619 $tmpprodvat = price2num(preg_replace('/\s*\‍(.*\‍)/', '', (string) $prod->tva_tx));
620
621 // Set unit price to use
622 if (!empty($price_ht) || $price_ht === '0') {
623 $pu_ht = price2num($price_ht, 'MU');
624 $pu_ttc = price2num((float) $pu_ht * (1 + ((float) $tmpvat / 100)), 'MU');
625 $price_base_type = 'HT';
626 } elseif (!empty($price_ttc) || $price_ttc === '0') {
627 $pu_ttc = price2num($price_ttc, 'MU');
628 $pu_ht = price2num((float) $pu_ttc / (1 + ((float) $tmpvat / 100)), 'MU');
629 $price_base_type = 'TTC';
630 }
631
632 $desc = $prod->description;
633
634 if (getDolGlobalInt('PRODUIT_AUTOFILL_DESC') == 0) {
635 // 'DoNotAutofillButAutoConcat'
636 $desc = dol_concatdesc($desc, $line_desc, false, getDolGlobalString('MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION') ? true : false);
637 } else {
638 //'AutoFillFormFieldBeforeSubmit' or 'DoNotUseDescriptionOfProdut' => User has already done the modification they want
639 $desc = $line_desc;
640 }
641
642 $fk_unit = $prod->fk_unit;
643 } else {
644 $pu_ht = price2num($price_ht, 'MU');
645 $pu_ttc = price2num($price_ttc, 'MU');
646 $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
647 if (empty($tva_tx)) {
648 $tva_npr = 0;
649 }
650 $tva_tx = str_replace('*', '', $tva_tx);
651 $desc = $line_desc;
652 $fk_unit = GETPOSTINT('units');
653 $pu_ht_devise = price2num($price_ht_devise, 'MU');
654 $pu_ttc_devise = price2num($price_ttc_devise, 'MU');
655
656 $tmpvat = price2num(preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx));
657
658 // Set unit price to use
659 if (!empty($price_ht) || $price_ht === '0') {
660 $pu_ht = price2num($price_ht, 'MU');
661 $pu_ttc = price2num((float) $pu_ht * (1 + ((float) $tmpvat / 100)), 'MU');
662 $price_base_type = 'HT';
663 } elseif (!empty($price_ttc) || $price_ttc === '0') {
664 $pu_ttc = price2num($price_ttc, 'MU');
665 $pu_ht = price2num((float) $pu_ttc / (1 + ((float) $tmpvat / 100)), 'MU');
666 $price_base_type = 'TTC';
667 }
668 }
669
670 $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $mysoc, $tva_npr);
671 $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $mysoc, $tva_npr);
672
673 // ajout prix achat
674 $fk_fournprice = GETPOST('fournprice');
675 if (GETPOST('buying_price')) {
676 $pa_ht = GETPOST('buying_price');
677 } else {
678 $pa_ht = null;
679 }
680
681 $info_bits = 0;
682 if ($tva_npr) {
683 $info_bits |= 0x01;
684 }
685
686 if (((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !$user->hasRight('produit', 'ignore_price_min_advance'))
687 || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS')) && ($price_min && ((float) price2num((string) $pu_ht) * (1 - (float) price2num($remise_percent) / 100) < (float) price2num($price_min)))) {
688 $object->error = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
689 $result = -1;
690 } else {
691 // Insert line
692 $result = $object->addline(
693 $desc,
694 (float) $pu_ht,
695 (float) $qty,
696 $tva_tx,
697 $localtax1_tx,
698 $localtax2_tx,
699 $idprod,
700 $remise_percent,
701 $date_start,
702 $date_end,
703 $price_base_type,
704 (float) $pu_ttc,
705 $info_bits,
706 (int) $fk_fournprice,
707 (float) $pa_ht,
708 $array_options,
709 (int) $fk_unit,
710 $rang
711 );
712 }
713
714 if ($result > 0) {
715 // Define output language
716 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE') && getDolGlobalString('CONTRACT_ADDON_PDF')) { // No generation if default type not defined
717 $outputlangs = $langs;
718 $newlang = '';
719 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
720 $newlang = GETPOST('lang_id', 'aZ09');
721 }
722 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
723 $newlang = $object->thirdparty->default_lang;
724 }
725 if (!empty($newlang)) {
726 $outputlangs = new Translate("", $conf);
727 $outputlangs->setDefaultLang($newlang);
728 }
729
730 $ret = $object->fetch($id); // Reload to get new records
731
732 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
733 }
734
735 unset($_POST['prod_entry_mode']);
736
737 unset($_POST['qty']);
738 unset($_POST['type']);
739 unset($_POST['remise_percent']);
740 unset($_POST['price_ht']);
741 unset($_POST['multicurrency_price_ht']);
742 unset($_POST['price_ttc']);
743 unset($_POST['tva_tx']);
744 unset($_POST['product_ref']);
745 unset($_POST['product_label']);
746 unset($_POST['product_desc']);
747 unset($_POST['fournprice']);
748 unset($_POST['buying_price']);
749 unset($_POST['np_marginRate']);
750 unset($_POST['np_markRate']);
751 unset($_POST['dp_desc']);
752 unset($_POST['idprod']);
753
754 unset($_POST['date_starthour']);
755 unset($_POST['date_startmin']);
756 unset($_POST['date_startsec']);
757 unset($_POST['date_startday']);
758 unset($_POST['date_startmonth']);
759 unset($_POST['date_startyear']);
760 unset($_POST['date_endhour']);
761 unset($_POST['date_endmin']);
762 unset($_POST['date_endsec']);
763 unset($_POST['date_endday']);
764 unset($_POST['date_endmonth']);
765 unset($_POST['date_endyear']);
766 } else {
767 setEventMessages($object->error, $object->errors, 'errors');
768 }
769 }
770 } elseif ($action == 'updateline' && $user->hasRight('contrat', 'creer') && !GETPOST('cancel', 'alpha')) {
771 $error = 0;
772 $predef = '';
773
774 if (!empty($date_start_update) && !empty($date_end_update) && $date_start_update > $date_end_update) {
775 setEventMessages($langs->trans("Error").': '.$langs->trans("DateStartPlanned").' > '.$langs->trans("DateEndPlanned"), null, 'errors');
776 $action = 'editline';
777 $error++;
778 }
779
780 if (!$error) {
781 $objectline = new ContratLigne($db);
782 if ($objectline->fetch($idline) < 0) {
783 setEventMessages($objectline->error, $objectline->errors, 'errors');
784 $error++;
785 }
786 $objectline->fetch_optionals();
787
788 $objectline->oldcopy = dol_clone($objectline, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
789 } else {
790 $objectline = null;
791 }
792
793 $db->begin();
794
795 if (!$error) {
796 if ($date_start_real_update == '') {
797 $date_start_real_update = $objectline->date_start_real;
798 }
799 if ($date_end_real_update == '') {
800 $date_end_real_update = $objectline->date_end_real;
801 }
802
803 $vat_rate = GETPOST('eltva_tx', 'alpha');
804 // Define info_bits
805 $info_bits = 0;
806 if (preg_match('/\*/', $vat_rate)) {
807 $info_bits |= 0x01;
808 }
809
810 // Define vat_rate
811 $vat_rate = str_replace('*', '', $vat_rate);
812 $localtax1_tx = get_localtax($vat_rate, 1, $object->thirdparty, $mysoc);
813 $localtax2_tx = get_localtax($vat_rate, 2, $object->thirdparty, $mysoc);
814
815 $txtva = $vat_rate;
816
817 // Clean vat code
818 $reg = array();
819 $vat_src_code = '';
820 if (preg_match('/\‍((.*)\‍)/', $txtva, $reg)) {
821 $vat_src_code = $reg[1];
822 $txtva = preg_replace('/\s*\‍(.*\‍)/', '', $txtva); // Remove code into vatrate.
823 }
824
825 // ajout prix d'achat
826 if (GETPOST('buying_price')) {
827 $pa_ht = price2num(GETPOST('buying_price'), '', 2);
828 } else {
829 $pa_ht = 0;
830 }
831
832 $fk_unit = GETPOSTINT('unit');
833
834 // TODO Use object->updateline instead objectline->update
835
836 $remise_percent = price2num(GETPOST('elremise_percent'), '', 2);
837
838 $objectline->fk_product = GETPOSTINT('idprod');
839 $objectline->description = GETPOST('product_desc', 'restricthtml');
840 $objectline->subprice = (float) price2num(GETPOST('elprice'), 'MU');
841 $objectline->qty = (float) price2num(GETPOST('elqty'), 'MS');
842 $objectline->remise_percent = $remise_percent;
843 $objectline->tva_tx = ($txtva ? $txtva : 0); // Field may be disabled, so we use vat rate 0
844 $objectline->vat_src_code = $vat_src_code;
845 $objectline->localtax1_tx = is_numeric($localtax1_tx) ? $localtax1_tx : 0;
846 $objectline->localtax2_tx = is_numeric($localtax2_tx) ? $localtax2_tx : 0;
847 $objectline->date_start = $date_start_update;
848 $objectline->date_start_real = $date_start_real_update;
849 $objectline->date_end = $date_end_update;
850 $objectline->date_end_real = $date_end_real_update;
851 $objectline->user_closing_id = $user->id;
852 //$objectline->fk_fournprice = $fk_fournprice;
853 $objectline->pa_ht = $pa_ht;
854 // $objectline->rang = $objectline->rang;
855
856 if ($fk_unit > 0) {
857 $objectline->fk_unit = GETPOSTINT('unit');
858 } else {
859 $objectline->fk_unit = null;
860 }
861
862 // Extrafields
863 $extralabelsline = $extrafields->fetch_name_optionals_label($objectline->table_element);
864 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
865
866 if (is_array($array_options) && count($array_options) > 0) {
867 // We replace values in this->line->array_options only for entries defined into $array_options
868 foreach ($array_options as $key => $value) {
869 $objectline->array_options[$key] = $array_options[$key];
870 }
871 }
872
873 // TODO verifier price_min si fk_product et multiprix
874
875 $result = $objectline->update($user);
876 if ($result < 0) {
877 $error++;
878 $action = 'editline';
879 $_GET['rowid'] = GETPOST('elrowid');
880 setEventMessages($objectline->error, $objectline->errors, 'errors');
881 }
882 }
883
884 if (!$error) {
885 $db->commit();
886 } else {
887 $db->rollback();
888 }
889 } elseif ($action == 'confirm_deleteline' && $confirm == 'yes' && $user->hasRight('contrat', 'creer')) {
890 $result = $object->deleteLine(GETPOSTINT('lineid'), $user);
891
892 if ($result >= 0) {
893 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
894 exit;
895 } else {
896 setEventMessages($object->error, $object->errors, 'errors');
897 }
898 } elseif ($action == 'confirm_valid' && $confirm == 'yes' && $user->hasRight('contrat', 'creer')) {
899 $result = $object->validate($user);
900
901 if ($result > 0) {
902 // Define output language
903 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
904 $outputlangs = $langs;
905 $newlang = '';
906 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
907 $newlang = GETPOST('lang_id', 'aZ09');
908 }
909 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
910 $newlang = $object->thirdparty->default_lang;
911 }
912 if (!empty($newlang)) {
913 $outputlangs = new Translate("", $conf);
914 $outputlangs->setDefaultLang($newlang);
915 }
916 $model = $object->model_pdf;
917 $ret = $object->fetch($id); // Reload to get new records
918
919 $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
920 }
921 } else {
922 setEventMessages($object->error, $object->errors, 'errors');
923 }
924 } elseif ($action == 'reopen' && $user->hasRight('contrat', 'creer')) {
925 $result = $object->reopen($user);
926 if ($result < 0) {
927 setEventMessages($object->error, $object->errors, 'errors');
928 }
929 } elseif ($action == 'confirm_close' && $confirm == 'yes' && $permissiontodisable) {
930 // Close all lines
931 $result = $object->closeAll($user);
932 if ($result < 0) {
933 setEventMessages($object->error, $object->errors, 'errors');
934 }
935 } elseif ($action == 'confirm_activate' && $confirm == 'yes' && $permissiontoactivate) {
936 $date_start = dol_mktime(12, 0, 0, GETPOSTINT('d_startmonth'), GETPOSTINT('d_startday'), GETPOSTINT('d_startyear'));
937 $date_end = dol_mktime(12, 0, 0, GETPOSTINT('d_endmonth'), GETPOSTINT('d_endday'), GETPOSTINT('d_endyear'));
938 $comment = GETPOST('comment', 'alpha');
939 $result = $object->activateAll($user, $date_start, 0, $comment, $date_end);
940 if ($result < 0) {
941 setEventMessages($object->error, $object->errors, 'errors');
942 }
943 } elseif ($action == 'confirm_delete' && $confirm == 'yes' && $permissiontodelete) {
944 $result = $object->delete($user);
945 if ($result >= 0) {
946 header("Location: list.php?restore_lastsearch_values=1");
947 return;
948 } else {
949 setEventMessages($object->error, $object->errors, 'errors');
950 }
951 } elseif ($action == 'confirm_move' && $confirm == 'yes' && $permissiontoedit) {
952 if (GETPOST('newcid') > 0) {
953 $contractline = new ContratLigne($db);
954 $result = $contractline->fetch(GETPOSTINT('lineid'));
955 $contractline->fk_contrat = GETPOSTINT('newcid');
956 $result = $contractline->update($user, 1);
957 if ($result >= 0) {
958 header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
959 return;
960 } else {
961 setEventMessages($object->error, $object->errors, 'errors');
962 }
963 } else {
964 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("RefNewContract")), null, 'errors');
965 }
966 } elseif ($action == 'update_extras' && $permissiontoeditextra) {
967 $object->oldcopy = dol_clone($object, 2);
968
969 $attribute = GETPOST('attribute', 'aZ09');
970
971 // Fill array 'array_options' with data from update form
972 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute);
973 if ($ret < 0) {
974 setEventMessages($extrafields->error, $object->errors, 'errors');
975 $error++;
976 }
977
978 if (!$error) {
979 $result = $object->updateExtraField($attribute, 'CONTRACT_MODIFY');
980 if ($result < 0) {
981 setEventMessages($object->error, $object->errors, 'errors');
982 $error++;
983 }
984 }
985
986 if ($error) {
987 $action = 'edit_extras';
988 }
989 } elseif ($action == 'setref_supplier' && $permissiontoadd) {
990 if (!$cancel) {
991 $object->oldcopy = dol_clone($object, 2);
992
993 $result = $object->setValueFrom('ref_supplier', GETPOST('ref_supplier', 'alpha'), '', null, 'text', '', $user, 'CONTRACT_MODIFY');
994 if ($result < 0) {
995 setEventMessages($object->error, $object->errors, 'errors');
996 $action = 'editref_supplier';
997 } else {
998 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
999 exit;
1000 }
1001 } else {
1002 header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
1003 exit;
1004 }
1005 } elseif ($action == 'setref_customer' && $permissiontoadd) {
1006 if (!$cancel) {
1007 $object->oldcopy = dol_clone($object, 2);
1008
1009 $result = $object->setValueFrom('ref_customer', GETPOST('ref_customer', 'alpha'), '', null, 'text', '', $user, 'CONTRACT_MODIFY');
1010 if ($result < 0) {
1011 setEventMessages($object->error, $object->errors, 'errors');
1012 $action = 'editref_customer';
1013 } else {
1014 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1015 exit;
1016 }
1017 } else {
1018 header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
1019 exit;
1020 }
1021 } elseif ($action == 'setref' && $permissiontoadd) {
1022 if (!$cancel) {
1023 $result = $object->fetch($id);
1024 if ($result < 0) {
1025 setEventMessages($object->error, $object->errors, 'errors');
1026 }
1027
1028 $old_ref = $object->ref;
1029
1030 $result = $object->setValueFrom('ref', GETPOST('ref', 'alpha'), '', null, 'text', '', $user, 'CONTRACT_MODIFY');
1031 if ($result < 0) {
1032 setEventMessages($object->error, $object->errors, 'errors');
1033 $action = 'editref';
1034 } else {
1035 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1036 $old_filedir = $conf->contrat->multidir_output[$object->entity ?? $conf->entity].'/'.dol_sanitizeFileName($old_ref);
1037 $new_filedir = $conf->contrat->multidir_output[$object->entity ?? $conf->entity].'/'.dol_sanitizeFileName($object->ref);
1038
1039 // Rename directory of contract with new name
1040 dol_move_dir($old_filedir, $new_filedir);
1041
1042 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1043 exit;
1044 }
1045 } else {
1046 header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
1047 exit;
1048 }
1049 } elseif ($action == 'setdate_contrat' && $permissiontoadd) {
1050 if (!$cancel) {
1051 $result = $object->fetch($id);
1052 if ($result < 0) {
1053 setEventMessages($object->error, $object->errors, 'errors');
1054 }
1055 $datacontrat = dol_mktime(GETPOSTINT('date_contrathour'), GETPOSTINT('date_contratmin'), 0, GETPOSTINT('date_contratmonth'), GETPOSTINT('date_contratday'), GETPOSTINT('date_contratyear'));
1056 $result = $object->setValueFrom('date_contrat', $datacontrat, '', null, 'date', '', $user, 'CONTRACT_MODIFY');
1057 if ($result < 0) {
1058 setEventMessages($object->error, $object->errors, 'errors');
1059 $action = 'editdate_contrat';
1060 } else {
1061 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1062 exit;
1063 }
1064 } else {
1065 header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
1066 exit;
1067 }
1068 }
1069
1070 // Actions when printing a doc from card
1071 include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
1072
1073 // Actions to build doc
1074 $upload_dir = $conf->contrat->multidir_output[!empty($object->entity) ? $object->entity : $conf->entity];
1075 include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
1076
1077 // Actions to send emails
1078 $triggersendname = 'CONTRACT_SENTBYMAIL';
1079 $paramname = 'id';
1080 $mode = 'emailfromcontract';
1081 $trackid = 'con'.$object->id;
1082 include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
1083
1084
1085 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
1086 if ($action == 'addcontact' && $user->hasRight('contrat', 'creer')) {
1087 $contactid = (GETPOST('userid') ? GETPOSTINT('userid') : GETPOSTINT('contactid'));
1088 $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
1089 $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09'));
1090
1091 if ($result >= 0) {
1092 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1093 exit;
1094 } else {
1095 if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
1096 $langs->load("errors");
1097 setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
1098 } else {
1099 setEventMessages($object->error, $object->errors, 'errors');
1100 }
1101 }
1102 } elseif ($action == 'swapstatut' && $user->hasRight('contrat', 'creer')) {
1103 // bascule du statut d'un contact
1104 $result = $object->swapContactStatus(GETPOSTINT('ligne'));
1105 } elseif ($action == 'deletecontact' && $user->hasRight('contrat', 'creer')) {
1106 // Efface un contact
1107 $result = $object->delete_contact(GETPOSTINT('lineid'));
1108
1109 if ($result >= 0) {
1110 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1111 exit;
1112 } else {
1113 setEventMessages($object->error, $object->errors, 'errors');
1114 }
1115 }
1116 }
1117
1118 // Action clone object
1119 if ($action == 'confirm_clone' && $confirm == 'yes' && $user->hasRight('contrat', 'creer')) {
1120 if (!GETPOSTINT('socid', 3)) {
1121 setEventMessages($langs->trans("NoCloneOptionsSpecified"), null, 'errors');
1122 } else {
1123 if ($object->id > 0) {
1124 $result = $object->createFromClone($user, $socid);
1125 if ($result > 0) {
1126 header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result);
1127 exit();
1128 } else {
1129 if (count($object->errors) > 0) {
1130 setEventMessages($object->error, $object->errors, 'errors');
1131 }
1132 $action = '';
1133 }
1134 }
1135 }
1136 }
1137}
1138
1139
1140/*
1141 * View
1142 */
1143
1144$title = $object->ref." - ".$langs->trans('Contract');
1145if ($action == 'create') {
1146 $title = $langs->trans("NewContract");
1147}
1148$help_url = 'EN:Module_Contracts|FR:Module_Contrat|ES:Contratos_de_servicio';
1149
1150llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-contrat page-card');
1151
1152$form = new Form($db);
1153$formfile = new FormFile($db);
1154if (isModEnabled('project')) {
1155 $formproject = new FormProjets($db);
1156}
1157
1158// Load object modContract
1159$module = getDolGlobalString('CONTRACT_ADDON', 'mod_contract_serpis');
1160if (substr($module, 0, 13) == 'mod_contract_' && substr($module, -3) == 'php') {
1161 $module = substr($module, 0, dol_strlen($module) - 4);
1162}
1163$result = dol_include_once('/core/modules/contract/'.$module.'.php');
1164$modCodeContract = null;
1165if ($result > 0) {
1166 $modCodeContract = new $module();
1168 '@phan-var-force ModelNumRefContracts $modCodeContract';
1169}
1170
1171// Create
1172if ($action == 'create') {
1173 $objectsrc = null;
1174 print load_fiche_titre($langs->trans('NewContract'), '', 'contract');
1175
1176 $soc = new Societe($db);
1177 if ($socid > 0) {
1178 $soc->fetch($socid);
1179 }
1180
1181 if (GETPOST('origin') && GETPOSTINT('originid')) {
1182 // Parse element/subelement (ex: project_task)
1183 $regs = array();
1184 $element = $subelement = GETPOST('origin');
1185 if (preg_match('/^([^_]+)_([^_]+)/i', GETPOST('origin'), $regs)) {
1186 $element = $regs[1];
1187 $subelement = $regs[2];
1188 }
1189
1190 if ($element == 'project') {
1191 $projectid = GETPOSTINT('originid');
1192 } else {
1193 // For compatibility
1194 if ($element == 'order' || $element == 'commande') {
1195 $element = $subelement = 'commande';
1196 }
1197 if ($element == 'propal') {
1198 $element = 'comm/propal';
1199 $subelement = 'propal';
1200 }
1201 if ($element == 'invoice' || $element == 'facture') {
1202 $element = 'compta/facture';
1203 $subelement = 'facture';
1204 }
1205 $classname = '';
1206 if ($element == 'facturerec' || $element == 'facture_rec') {
1207 $element = 'compta/facture';
1208 $subelement = 'facture-rec';
1209 $classname = 'FactureRec';
1210 }
1211 if ($element == 'facture_fourn_rec' || $element == 'invoice_supplier_rec') {
1212 $element = 'fourn';
1213 $subelement = 'fournisseur.facture-rec';
1214 $classname = 'FactureFournisseurRec';
1215 }
1216
1217 dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
1218
1219 if (empty($classname)) {
1220 $classname = ucfirst($subelement);
1221 }
1222 $objectsrc = new $classname($db);
1223 '@phan-var-force Commande|Propal|Facture $objectsrc';
1224 $objectsrc->fetch($originid);
1225 if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
1226 $objectsrc->fetch_lines();
1227 }
1228 $objectsrc->fetch_thirdparty();
1229
1230 // Replicate extrafields
1231 $objectsrc->fetch_optionals();
1232 $object->array_options = $objectsrc->array_options;
1233
1234 $projectid = (int) $objectsrc->fk_project;
1235
1236 $soc = $objectsrc->thirdparty;
1237
1238 $note_private = (!empty($objectsrc->note_private) ? $objectsrc->note_private : '');
1239 $note_public = (!empty($objectsrc->note_public) ? $objectsrc->note_public : '');
1240
1241 // Object source contacts list
1242 $srccontactslist = $objectsrc->liste_contact(-1, 'external', 1);
1243 }
1244 } else {
1245 $projectid = GETPOSTINT('projectid');
1246 $note_private = GETPOST("note_private", "alpha");
1247 $note_public = GETPOST("note_public", "alpha");
1248 }
1249
1250 $object->date_contrat = dol_now();
1251
1252 print '<form name="form_contract" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1253 print '<input type="hidden" name="token" value="'.newToken().'">';
1254 print '<input type="hidden" name="action" value="add">';
1255 print '<input type="hidden" name="socid" value="'.$soc->id.'">'."\n";
1256 print '<input type="hidden" name="remise_percent" value="0">';
1257 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1258
1259 print dol_get_fiche_head();
1260
1261 print '<table class="border centpercent">';
1262
1263 // Ref
1264 print '<tr><td class="titlefield fieldrequired">'.$langs->trans('Ref').'</td><td>';
1265 if (!empty($modCodeContract->code_auto)) {
1266 $tmpcode = $langs->trans("Draft");
1267 } else {
1268 $tmpcode = '<input name="ref" class="maxwidth100" maxlength="128" value="'.dol_escape_htmltag(GETPOST('ref', 'alpha')).'">';
1269 }
1270 print $tmpcode;
1271 print '</td></tr>';
1272
1273 // Ref customer
1274 print '<tr><td>'.$langs->trans('RefCustomer').'</td>';
1275 print '<td><input type="text" class="maxwidth150" name="ref_customer" id="ref_customer" value="'.dol_escape_htmltag(GETPOST('ref_customer', 'alpha')).'"></td></tr>';
1276
1277 // Ref supplier
1278 print '<tr><td>'.$langs->trans('RefSupplier').'</td>';
1279 print '<td><input type="text" class="maxwidth150" name="ref_supplier" id="ref_supplier" value="'.dol_escape_htmltag(GETPOST('ref_supplier', 'alpha')).'"></td></tr>';
1280
1281 // Thirdparty
1282 print '<tr>';
1283 print '<td class="fieldrequired">'.$langs->trans('ThirdParty').'</td>';
1284 if ($socid > 0) {
1285 print '<td>';
1286 print $soc->getNomUrl(1);
1287 print '<input type="hidden" name="socid" value="'.$soc->id.'">';
1288 print '</td>';
1289 } else {
1290 print '<td>';
1291 print img_picto('', 'company', 'class="pictofixedwidth"');
1292 print $form->select_company('', 'socid', '', 'SelectThirdParty', 1, 0, array(), 0, 'minwidth150 widthcentpercentminusxx maxwidth500');
1293 print ' <a href="'.dolBuildUrl(DOL_URL_ROOT . '/societe/card.php', ['action' => 'create', 'customer' => 3, 'backtopage' => dolBuildUrl($_SERVER["PHP_SELF"], ['action' => 'create'])]).'"><span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("AddThirdParty").'"></span></a>';
1294 print '</td>';
1295 }
1296 print '</tr>'."\n";
1297
1298 if ($socid > 0) {
1299 // Ligne info remises tiers
1300 print '<tr><td>'.$langs->trans('Discounts').'</td><td>';
1301 if ($soc->remise_percent) {
1302 print $langs->trans("CompanyHasRelativeDiscount", $soc->remise_percent).' ';
1303 } else {
1304 print '<span class="hideonsmartphone">'.$langs->trans("CompanyHasNoRelativeDiscount").'. </span>';
1305 }
1306 $absolute_discount = $soc->getAvailableDiscounts();
1307 if ($absolute_discount) {
1308 print $langs->trans("CompanyHasAbsoluteDiscount", price($absolute_discount), $langs->trans("Currency".$conf->currency)).'.';
1309 } else {
1310 print '<span class="hideonsmartphone">'.$langs->trans("CompanyHasNoAbsoluteDiscount").'.</span>';
1311 }
1312 print '</td></tr>';
1313 }
1314
1315 // Commercial suivi
1316 print '<tr><td class="nowrap"><span class="fieldrequired">'.$langs->trans("TypeContact_contrat_internal_SALESREPFOLL").'</span></td><td>';
1317 print img_picto('', 'user', 'class="pictofixedwidth"');
1318 print $form->select_dolusers(GETPOST("commercial_suivi_id") ? GETPOST("commercial_suivi_id") : $user->id, 'commercial_suivi_id', 1, null);
1319 print '</td></tr>';
1320
1321 // Commercial signature
1322 print '<tr><td class="nowrap"><span class="fieldrequired">'.$langs->trans("TypeContact_contrat_internal_SALESREPSIGN").'</span></td><td>';
1323 print img_picto('', 'user', 'class="pictofixedwidth"');
1324 print $form->select_dolusers(GETPOST("commercial_signature_id") ? GETPOST("commercial_signature_id") : $user->id, 'commercial_signature_id', 1, null);
1325 print '</td></tr>';
1326
1327 print '<tr><td><span class="fieldrequired">'.$langs->trans("Date").'</span></td><td>';
1328 print img_picto('', 'action', 'class="pictofixedwidth"');
1329 print $form->selectDate($datecontrat, '', 0, 0, 0, "contrat");
1330 print "</td></tr>";
1331
1332 // Project
1333 if (isModEnabled('project')) {
1334 $langs->load('projects');
1335
1336 $formproject = new FormProjets($db);
1337
1338 print '<tr><td>'.$langs->trans("Project").'</td><td>';
1339 print img_picto('', 'project', 'class="pictofixedwidth"');
1340 $formproject->select_projects(($soc->id > 0 ? $soc->id : -1), $projectid, "projectid", 0, 0, 1, 1, 0, 0, 0, '', 0, 0, 'minwidth150 maxwidth300 widthcentpercentminusxx');
1341 print ' &nbsp; <a href="' . dolBuildUrl(DOL_URL_ROOT . '/projet/card.php', ['socid' => $soc->id, 'action' => 'create', 'status' => 1, 'backtopage' => dolBuildUrl($_SERVER["PHP_SELF"], ['action' => 'create', 'socid' => $soc->id])]) . '"><span class="fa fa-plus-circle valignmiddle" title="'.$langs->trans("AddProject").'"></span></a>';
1342 print "</td></tr>";
1343 }
1344
1345 // Note public
1346 print '<tr><td>'.$langs->trans("NotePublic").'</td><td class="tdtop">';
1347 $doleditor = new DolEditor('note_public', (string) $note_public, '', 100, 'dolibarr_notes', 'In', true, true, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
1348 print $doleditor->Create(1);
1349 print '</td></tr>';
1350
1351 // Note private
1352 if (empty($user->socid)) {
1353 print '<tr><td>'.$langs->trans("NotePrivate").'</td><td class="tdtop">';
1354 $doleditor = new DolEditor('note_private', (string) $note_private, '', 100, 'dolibarr_notes', 'In', true, true, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
1355 print $doleditor->Create(1);
1356 print '</td></tr>';
1357 }
1358
1359 // Other attributes
1360 $parameters = array('objectsrc' => $objectsrc, 'colspan' => ' colspan="3"', 'cols' => '3');
1361 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1362 print $hookmanager->resPrint;
1363
1364 // Other attributes
1365 if (empty($reshook)) {
1366 print $object->showOptionals($extrafields, 'create', $parameters);
1367 }
1368
1369 print "</table>\n";
1370
1371 print dol_get_fiche_end();
1372
1373 print $form->buttonsSaveCancel("Create");
1374
1375 if (is_object($objectsrc)) {
1376 print '<input type="hidden" name="origin" value="'.$objectsrc->element.'">';
1377 print '<input type="hidden" name="originid" value="'.$objectsrc->id.'">';
1378
1379 if (!getDolGlobalString('CONTRACT_SUPPORT_PRODUCTS')) {
1380 print '<br>'.$langs->trans("Note").': '.$langs->trans("OnlyLinesWithTypeServiceAreUsed");
1381 }
1382 }
1383
1384 print "</form>\n";
1385} else {
1386 // View and edit mode
1387 $now = dol_now();
1388
1389 if ($object->id > 0) {
1390 $object->fetch_thirdparty();
1391
1392 $soc = $object->thirdparty; // $soc is used later
1393
1394 $result = $object->fetch_lines(); // This also init $this->nbofserviceswait, $this->nbofservicesopened, $this->nbofservicesexpired=, $this->nbofservicesclosed
1395 if ($result < 0) {
1396 dol_print_error($db, $object->error);
1397 }
1398
1399 $nbofservices = count($object->lines);
1400
1401 $author = new User($db);
1402 $author->fetch($object->user_author_id);
1403
1404 $commercial_signature = new User($db);
1405 $commercial_signature->fetch($object->commercial_signature_id);
1406
1407 $commercial_suivi = new User($db);
1408 $commercial_suivi->fetch($object->commercial_suivi_id);
1409
1410 $head = contract_prepare_head($object);
1411
1412 $hselected = '0';
1413 $formconfirm = '';
1414
1415 print dol_get_fiche_head($head, $hselected, $langs->trans("Contract"), -1, 'contract');
1416
1417
1418 if ($action == 'delete') {
1419 //Confirmation de la suppression du contrat
1420 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("DeleteAContract"), $langs->trans("ConfirmDeleteAContract"), "confirm_delete", '', 0, 1);
1421 } elseif ($action == 'valid') {
1422 //Confirmation de la validation
1423 $ref = substr($object->ref, 1, 4);
1424 if ($ref == 'PROV' && !empty($modCodeContract->code_auto)) {
1425 $numref = $object->getNextNumRef($object->thirdparty);
1426 } else {
1427 $numref = (string) $object->ref;
1428 }
1429 $text = $langs->trans('ConfirmValidateContract', $numref);
1430 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("ValidateAContract"), $text, "confirm_valid", '', 0, 1);
1431 } elseif ($action == 'close') {
1432 // Confirmation de la fermeture
1433 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("CloseAContract"), $langs->trans("ConfirmCloseContract"), "confirm_close", '', 0, 1);
1434 } elseif ($action == 'activate') {
1435 $formquestion = array(
1436 array('type' => 'date', 'name' => 'd_start', 'label' => $langs->trans("DateServiceActivate"), 'value' => dol_now()),
1437 array('type' => 'date', 'name' => 'd_end', 'label' => $langs->trans("DateEndPlanned"), 0 => '', 1 => ''),
1438 array('type' => 'text', 'name' => 'comment', 'label' => $langs->trans("Comment"), 'value' => '', 0 => '', 1 => '', 'class' => 'minwidth300', 'moreattr' => 'autofocus')
1439 );
1440 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("ActivateAllOnContract"), $langs->trans("ConfirmActivateAllOnContract"), "confirm_activate", $formquestion, 'yes', 1, 300);
1441 } elseif ($action == 'clone') {
1442 $filter = '(s.client:IN:1,2,3)';
1443 // Clone confirmation
1444 $formquestion = array(array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOSTINT('socid'), 'socid', $filter)));
1445 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneContract', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
1446 } elseif ($action == 'sign') {
1447 $text = $langs->trans('ConfirmSignContract');
1448 if (isModEnabled('notification')) {
1449 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
1450 $notify = new Notify($db);
1451 $text .= '<br>';
1452 $text .= $notify->confirmMessage('CONTRACT_MODIFY', $object->socid, $object);
1453 }
1454 $formquestion = [];
1455 $formquestion[] = [
1456 'type' => 'select',
1457 'name' => 'signed_status',
1458 'label' => '<span class="fieldrequired">'.$langs->trans('SignStatus').'</span>',
1459 'values' => $object->getSignedStatusLocalisedArray()
1460 ];
1461 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('SignContract'), $text, 'confirm_sign', $formquestion, 0, 1);
1462 } elseif ($action == 'unsign') {
1463 $text = $langs->trans('ConfirmUnsignContract');
1464 if (isModEnabled('notification')) {
1465 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
1466 $notify = new Notify($db);
1467 $text .= '<br>';
1468 $text .= $notify->confirmMessage('CONTRACT_MODIFY', $object->socid, $object);
1469 }
1470 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('UnsignContract'), $text, 'confirm_unsign', '', 0, 1);
1471 }
1472
1473
1474 // Call Hook formConfirm
1475 $parameters = array(
1476 'formConfirm' => $formconfirm,
1477 'id' => $id,
1478 //'lineid' => $lineid,
1479 );
1480 // Note that $action and $object may have been modified by hook
1481 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action);
1482 if (empty($reshook)) {
1483 $formconfirm .= $hookmanager->resPrint;
1484 } elseif ($reshook > 0) {
1485 $formconfirm = $hookmanager->resPrint;
1486 }
1487
1488 // Print form confirm
1489 print $formconfirm;
1490
1491
1492 // Contract
1493 if ($object->status == $object::STATUS_DRAFT && $user->hasRight('contrat', 'creer')) {
1494 print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'" method="POST">';
1495 print '<input type="hidden" name="token" value="'.newToken().'">';
1496 print '<input type="hidden" name="action" value="setremise">';
1497 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1498 }
1499
1500 // Contract card
1501
1502 $linkback = '<a href="'.DOL_URL_ROOT.'/contrat/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
1503
1504
1505 $morehtmlref = '';
1506 if (!empty($modCodeContract->code_auto)) {
1507 $morehtmlref .= $object->ref;
1508 } else {
1509 $morehtmlref .= $form->editfieldkey("", 'ref', $object->ref, $object, $user->hasRight('contrat', 'creer'), 'string', '', 0, 3);
1510 $morehtmlref .= $form->editfieldval("", 'ref', $object->ref, $object, $user->hasRight('contrat', 'creer'), 'string', '', null, '2');
1511 }
1512
1513 $morehtmlref .= '<div class="refidno">';
1514 // Ref customer
1515 $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->hasRight('contrat', 'creer'), 'string', '', 0, 1);
1516 $morehtmlref .= $form->editfieldval("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->hasRight('contrat', 'creer'), 'string'.(isset($conf->global->THIRDPARTY_REF_INPUT_SIZE) ? ':' . getDolGlobalString('THIRDPARTY_REF_INPUT_SIZE') : ''), '', null, null, '', 1, 'getFormatedCustomerRef');
1517 // Ref supplier
1518 $morehtmlref .= '<br>';
1519 $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->hasRight('contrat', 'creer'), 'string', '', 0, 1);
1520 $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->hasRight('contrat', 'creer'), 'string', '', null, null, '', 1, 'getFormatedSupplierRef');
1521 // Thirdparty
1522 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1);
1523 if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
1524 $morehtmlref .= ' <span class="otherlink valignmiddle">(<a href="'.DOL_URL_ROOT.'/contrat/list.php?socid='.$object->thirdparty->id.'&search_name='.urlencode($object->thirdparty->name).'">'.$langs->trans("OtherContracts").'</a>)</span>';
1525 }
1526 // Project
1527 if (isModEnabled('project')) {
1528 $langs->load("projects");
1529 $morehtmlref .= '<br>';
1530 if ($permissiontoadd) {
1531 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
1532 if ($action != 'classify') {
1533 $morehtmlref .= '<a class="editfielda" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'classify', 'id' => $object->id], true).'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
1534 }
1535 $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');
1536 } else {
1537 if (!empty($object->fk_project)) {
1538 $proj = new Project($db);
1539 $proj->fetch($object->fk_project);
1540 $morehtmlref .= $proj->getNomUrl(1);
1541 if ($proj->title) {
1542 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
1543 }
1544 }
1545 }
1546 }
1547 $morehtmlref .= '</div>';
1548
1549
1550 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'none', $morehtmlref);
1551
1552
1553 print '<div class="fichecenter">';
1554 print '<div class="underbanner clearboth"></div>';
1555
1556
1557 print '<table class="border tableforfield" width="100%">';
1558
1559 // Line info of thirdparty discounts
1560 print '<tr><td class="titlefield">'.$langs->trans('Discount').'</td><td colspan="3">';
1561 if ($object->thirdparty->remise_percent) {
1562 print $langs->trans("CompanyHasRelativeDiscount", $object->thirdparty->remise_percent).'. ';
1563 } else {
1564 print '<span class="hideonsmartphone">'.$langs->trans("CompanyHasNoRelativeDiscount").'. </span>';
1565 }
1566 $absolute_discount = $object->thirdparty->getAvailableDiscounts();
1567 if ($absolute_discount) {
1568 print $langs->trans("CompanyHasAbsoluteDiscount", price($absolute_discount), $langs->trans("Currency".$conf->currency)).'.';
1569 } else {
1570 print '<span class="hideonsmartphone">'.$langs->trans("CompanyHasNoAbsoluteDiscount").'.</span>';
1571 }
1572 print '</td></tr>';
1573
1574 // Date
1575 print '<tr>';
1576 print '<td class="titlefield">';
1577 print $form->editfieldkey("Date", 'date_contrat', $object->date_contrat, $object, $user->hasRight('contrat', 'creer'));
1578 print '</td><td>';
1579 print $form->editfieldval("Date", 'date_contrat', $object->date_contrat, $object, $user->hasRight('contrat', 'creer'), 'datehourpicker');
1580 print '</td>';
1581 print '</tr>';
1582
1583 // Other attributes
1584 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1585
1586 print "</table>";
1587
1588 print '</div>';
1589
1590 if ($object->status == $object::STATUS_DRAFT && $user->hasRight('contrat', 'creer')) {
1591 print '</form>';
1592 }
1593
1594 echo '<br>';
1595
1596 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
1597 $blocname = 'contacts';
1598 $title = $langs->trans('ContactsAddresses');
1599 include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
1600 }
1601
1602 if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
1603 $blocname = 'notes';
1604 $title = $langs->trans('Notes');
1605 include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
1606 }
1607
1608
1609 $arrayothercontracts = $object->getListOfContracts('others'); // array or -1 if technical error
1610
1611 /*
1612 * Lines of contracts
1613 */
1614
1615 // Add products/services form
1616 //$forceall = 1;
1617 global $inputalsopricewithtax;
1618 $inputalsopricewithtax = 1;
1619
1620 $productstatic = new Product($db);
1621
1622 $usemargins = 0;
1623 if (isModEnabled('margin') && !empty($object->element) && in_array($object->element, array('facture', 'propal', 'commande'))) {
1624 $usemargins = 1;
1625 }
1626
1627 $parameters = array('nbOfLines' => &$nbofservices);
1628 $reshook = $hookmanager->executeHooks('printObjectLinesBlock', $parameters, $object, $action);
1629 if (empty($reshook)) {
1630 // Title line for service
1631 $cursorline = 1;
1632
1633 print '<div id="contrat-lines-container" id="contractlines" data-contractid="'.$object->id.'" data-element="'.$object->element.'" >';
1634 while ($cursorline <= $nbofservices) {
1635 print '<div id="contrat-line-container'.$object->lines[$cursorline - 1]->id.'" data-contratlineid = "'.$object->lines[$cursorline - 1]->id.'" data-element="'.$object->lines[$cursorline - 1]->element.'" >';
1636 print '<form name="update" id="addproduct" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'" method="post">';
1637 print '<input type="hidden" name="token" value="'.newToken().'">';
1638 print '<input type="hidden" name="action" value="updateline">';
1639 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1640 print '<input type="hidden" name="elrowid" value="'.$object->lines[$cursorline - 1]->id.'">';
1641 print '<input type="hidden" name="fournprice" value="'.(!empty($object->lines[$cursorline - 1]->fk_fournprice) ? $object->lines[$cursorline - 1]->fk_fournprice : 0).'">';
1642
1643 // Area with common detail of line
1644 print '<div class="div-table-responsive-no-min">';
1645 print '<table class="notopnoleftnoright allwidth tableforservicepart1 centpercent">';
1646
1647 $sql = "SELECT cd.rowid, cd.statut, cd.label as label_det, cd.fk_product, cd.product_type, cd.description, cd.qty,";
1648 $sql .= " cd.tva_tx, cd.vat_src_code, cd.remise_percent, cd.info_bits, cd.subprice, cd.multicurrency_subprice,";
1649 $sql .= " cd.date_ouverture_prevue as date_start, cd.date_ouverture as date_start_real,";
1650 $sql .= " cd.date_fin_validite as date_end, cd.date_cloture as date_end_real,";
1651 $sql .= " cd.commentaire as comment, cd.fk_product_fournisseur_price as fk_fournprice, cd.buy_price_ht as pa_ht,";
1652 $sql .= " cd.fk_unit,";
1653 $sql .= " p.rowid as pid, p.ref as pref, p.label as plabel, p.fk_product_type as ptype, p.entity as pentity, p.tosell, p.tobuy, p.tobatch";
1654 $sql .= " ,cd.rang";
1655 $sql .= " FROM ".MAIN_DB_PREFIX."contratdet as cd";
1656 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid";
1657 $sql .= " WHERE cd.rowid = ".((int) $object->lines[$cursorline - 1]->id);
1658
1659 $result = $db->query($sql);
1660 $objp = null;
1661 if ($result) {
1662 $total = 0;
1663
1664 $objp = $db->fetch_object($result);
1665
1666 // Line title
1667 print '<tr class="liste_titre'.($cursorline ? ' liste_titre_add' : '').'">';
1668 print '<td>'.$langs->trans("ServiceNb", $cursorline).'</td>';
1669 print '<td width="80" class="center">'.$langs->trans("VAT").'</td>';
1670 print '<td width="80" class="right">'.$langs->trans("PriceUHT").'</td>';
1671 //if (isModEnabled("multicurrency")) {
1672 // print '<td width="80" class="right">'.$langs->trans("PriceUHTCurrency").'</td>';
1673 //}
1674 print '<td width="30" class="center">'.$langs->trans("Qty").'</td>';
1675 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1676 print '<td width="30" class="left">'.$langs->trans("Unit").'</td>';
1677 }
1678 print '<td width="50" class="right">'.$langs->trans("ReductionShort").'</td>';
1679 if (isModEnabled('margin') && getDolGlobalString('MARGIN_SHOW_ON_CONTRACT')) {
1680 print '<td width="50" class="right">'.$langs->trans("BuyingPrice").'</td>';
1681 }
1682 //
1683
1684 if ($nbofservices > 1 && $conf->browser->layout != 'phone' && $user->hasRight('contrat', 'creer')) {
1685 print '<td width="30" class="linecolmove tdlineupdown center">';
1686 if ($cursorline > 1) {
1687 print '<a class="lineupdown reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=up&token='.newToken().'&rowid='.$objp->rowid.'">';
1688 echo img_up('default', 0, 'imgupforline');
1689 print '</a>';
1690 }
1691 if ($cursorline < $nbofservices) {
1692 print '<a class="lineupdown reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=down&token='.newToken().'&rowid='.$objp->rowid.'">';
1693 echo img_down('default', 0, 'imgdownforline');
1694 print '</a>';
1695 }
1696 print '</td>';
1697 } else {
1698 print '<td width="30">&nbsp;</td>';
1699 }
1700
1701 print "</tr>\n";
1702
1703
1704
1705 // Line in view mode
1706 if ($action != 'editline' || $idline != $objp->rowid) {
1707 $moreparam = '';
1708 if (getDolGlobalString('CONTRACT_HIDE_CLOSED_SERVICES_BY_DEFAULT') && $objp->statut == ContratLigne::STATUS_CLOSED && $action != 'showclosedlines') {
1709 $moreparam = 'style="display: none;"';
1710 }
1711
1712 $line = $objp;
1713 $line->id = $objp->rowid;
1714
1715 $coldisplay = 0;
1716
1717 print '<tr class="tdtop oddeven" '.$moreparam.'>';
1718
1719 // Label
1720 print '<td class="linecoldescription minwidth300imp">';
1721 $coldisplay++;
1722 print '<div id="line_'.$line->rowid.'"></div>';
1723 if ($objp->fk_product > 0) {
1724 $productstatic->id = $objp->fk_product;
1725 $productstatic->type = $objp->ptype;
1726 $productstatic->ref = $objp->pref;
1727 $productstatic->entity = $objp->pentity;
1728 $productstatic->label = $objp->plabel;
1729 $productstatic->status = $objp->tosell;
1730 $productstatic->status_buy = $objp->tobuy;
1731 $productstatic->status_batch = $objp->tobatch;
1732
1733 $text = $productstatic->getNomUrl(1, '', 32);
1734 if ($objp->plabel) {
1735 $text .= ' - ';
1736 $text .= $objp->plabel;
1737 }
1738 $description = $objp->description;
1739
1740 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1741 print (!empty($line->fk_parent_line) ? img_picto('', 'rightarrow.png') : '') . $text;
1742 if (!getDolGlobalInt('PRODUIT_DESC_IN_FORM')) {
1743 print $form->textwithpicto('', $description);
1744 }
1745 } else {
1746 print $form->textwithtooltip($text, $description, 3, 0, '', '', 0, (!empty($line->fk_parent_line) ? img_picto('', 'rightarrow.png') : ''));
1747 }
1748
1749 // Add description in form
1750 if ($line->fk_product > 0 && getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
1751 print (!empty($line->description) && $line->description != $line->plabel) ? (($line->date_start || $line->date_end) ? '' : '<br>').'<br>'.dol_htmlentitiesbr($line->description) : '';
1752 }
1753 } else {
1754 print img_object($langs->trans("ShowProductOrService"), ($objp->product_type ? 'service' : 'product')).' '.dol_htmlentitiesbr($objp->description)."\n";
1755 }
1756 print '</td>';
1757
1758 // VAT
1759 print '<td class="center">';
1760 print vatrate($objp->tva_tx.($objp->vat_src_code ? (' ('.$objp->vat_src_code.')') : ''), true, $objp->info_bits);
1761 print '</td>';
1762 // Price
1763 print '<td class="right">'.($objp->subprice != '' ? price($objp->subprice) : '')."</td>\n";
1764 // Price multicurrency
1765 /*if (isModEnabled("multicurrency")) {
1766 print '<td class="linecoluht_currency nowrap right">'.price($objp->multicurrency_subprice).'</td>';
1767 }*/
1768 // Quantity
1769 print '<td class="center">'.$objp->qty.'</td>';
1770 // Unit
1771 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1772 print '<td class="left">'.$object->lines[$cursorline - 1]->getLabelOfUnit('long', $langs).'</td>';
1773 }
1774 // Discount
1775 if ($objp->remise_percent > 0) {
1776 print '<td class="right">'.$objp->remise_percent."%</td>\n";
1777 } else {
1778 print '<td>&nbsp;</td>';
1779 }
1780
1781 // Margin
1782 if (isModEnabled('margin') && getDolGlobalString('MARGIN_SHOW_ON_CONTRACT')) {
1783 print '<td class="right nowraponall">'.price($objp->pa_ht).'</td>';
1784 }
1785
1786 // Icon move, update et delete (status contract 0=draft,1=validated,2=closed)
1787 print '<td class="nowraponall right">';
1788 if ($user->hasRight('contrat', 'creer') && is_array($arrayothercontracts) && count($arrayothercontracts) && ($object->status >= 0)) {
1789 print '<!-- link to move service line into another contract -->';
1790 print '<a class="reposition marginrightonly" style="padding-left: 5px;" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=move&token='.newToken().'&elrowid='.$objp->rowid.'">';
1791 print img_picto($langs->trans("MoveToAnotherContract"), 'uparrow');
1792 print '</a>';
1793 }
1794 if ($user->hasRight('contrat', 'creer') && ($object->statut >= 0)) {
1795 print '<a class="reposition marginrightonly editfielda" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=editline&token='.newToken().'&elrowid='.$objp->rowid.'">';
1796 print img_edit();
1797 print '</a>';
1798 }
1799 if ($user->hasRight('contrat', 'creer') && ($object->statut >= 0)) {
1800 print '<a class="reposition marginrightonly" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=deleteline&token='.newToken().'&elrowid='.$objp->rowid.'">';
1801 print img_delete();
1802 print '</a>';
1803 }
1804 print '</td>';
1805
1806 print "</tr>\n";
1807
1808 $colspan = 6;
1809 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1810 $colspan++;
1811 }
1812 if (isModEnabled('margin') && getDolGlobalString('MARGIN_SHOW_ON_CONTRACT')) {
1813 $colspan++;
1814 }
1815
1816 // Dates of service planned and real
1817 if ($objp->subprice >= 0) {
1818 print '<tr class="oddeven" '.$moreparam.'>';
1819 print '<td colspan="'.$colspan.'">';
1820
1821 // Date planned
1822 print $langs->trans("DateStartPlanned").': ';
1823 if ($objp->date_start) {
1824 print dol_print_date($db->jdate($objp->date_start), 'day');
1825 // Warning si date prevu passee et pas en service
1826 if ($objp->statut == 0 && $db->jdate($objp->date_start) < ($now - $conf->contrat->services->inactifs->warning_delay)) {
1827 $warning_delay = $conf->contrat->services->inactifs->warning_delay / 3600 / 24;
1828 $textlate = $langs->trans("Late").' = '.$langs->trans("DateReference").' > '.$langs->trans("DateToday").' '.(ceil($warning_delay) >= 0 ? '+' : '').ceil($warning_delay).' '.$langs->trans("days");
1829 print " ".img_warning($textlate);
1830 }
1831 } else {
1832 print $langs->trans("Unknown");
1833 }
1834 print ' &nbsp;-&nbsp; ';
1835 print $langs->trans("DateEndPlanned").': ';
1836 if ($objp->date_end) {
1837 print dol_print_date($db->jdate($objp->date_end), 'day');
1838 if ($objp->statut == 4 && $db->jdate($objp->date_end) < ($now - $conf->contrat->services->expires->warning_delay)) {
1839 $warning_delay = $conf->contrat->services->expires->warning_delay / 3600 / 24;
1840 $textlate = $langs->trans("Late").' = '.$langs->trans("DateReference").' > '.$langs->trans("DateToday").' '.(ceil($warning_delay) >= 0 ? '+' : '').ceil($warning_delay).' '.$langs->trans("days");
1841 print " ".img_warning($textlate);
1842 }
1843 } else {
1844 print $langs->trans("Unknown");
1845 }
1846
1847 print '</td>';
1848 print '</tr>';
1849 }
1850
1851 // Display lines extrafields
1852 if (is_array($extralabelslines) && count($extralabelslines) > 0) {
1853 $line = new ContratLigne($db);
1854 $line->id = $objp->rowid;
1855 $line->fetch_optionals();
1856 print $line->showOptionals($extrafields, 'view', array('class' => 'oddeven', 'style' => $moreparam, 'colspan' => $colspan, 'tdclass' => 'notitlefieldcreate'), '', '', '1');
1857 }
1858 } else {
1859 // Line in mode update
1860 // Ligne carac
1861 print '<tr class="oddeven">';
1862 print '<td>';
1863 $currentLineProductId = GETPOSTISSET('idprod') ? GETPOST('idprod') : (!empty($object->lines[$cursorline - 1]->fk_product) ? $object->lines[$cursorline - 1]->fk_product : 0);
1864 if ($objp->fk_product > 0) {
1865 $canchangeproduct = 1;
1866
1867 // @TODO: As $canchangeproduct is set just before, in what usecase it can be empty ?
1868 if (empty($canchangeproduct)) {
1869 $productstatic->id = $objp->fk_product;
1870 $productstatic->type = $objp->ptype;
1871 $productstatic->ref = $objp->pref;
1872 $productstatic->entity = $objp->pentity;
1873 print $productstatic->getNomUrl(1, '', 32);
1874 print $objp->label ? ' - '.dol_trunc($objp->label, 32) : '';
1875 print '<input type="hidden" name="idprod" value="'.$currentLineProductId.'">';
1876 } else {
1877 $senderissupplier = 0; // @TODO Option to allow purchased products ?
1878 if (empty($senderissupplier)) {
1879 if (getDolGlobalString('CONTRACT_SUPPORT_PRODUCTS')) {
1880 $filtertype = '';
1881 } else {
1882 $filtertype = '1';
1883 }
1884 print $form->select_produits($currentLineProductId, 'idprod', $filtertype, 0, 0, 1, 2, '', 0, array(), 0, 1, 0, 'minwidth250onall maxwidth500 widthcentpercentminusx');
1885 } else {
1886 $form->select_produits_fournisseurs($currentLineProductId, 'idprod');
1887 }
1888 }
1889 print '<br>';
1890 } else {
1891 print $objp->label ? $objp->label.'<br>' : '';
1892 print '<input type="hidden" name="idprod" value="'.$currentLineProductId.'">';
1893 }
1894
1895 // editeur wysiwyg
1896 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1897 $nbrows = ROWS_2;
1898 if (getDolGlobalString('MAIN_INPUT_DESC_HEIGHT')) {
1899 $nbrows = getDolGlobalString('MAIN_INPUT_DESC_HEIGHT');
1900 }
1901 $doleditor = new DolEditor('product_desc', (GETPOSTISSET('product_desc') ? GETPOST('product_desc') : $objp->description), '', 92, 'dolibarr_details', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_DETAILS'), $nbrows, '90%');
1902 $doleditor->Create();
1903
1904 print '</td>';
1905
1906 // VAT
1907 print '<td class="right">';
1908 print $form->load_tva("eltva_tx", $objp->tva_tx.($objp->vat_src_code ? (' ('.$objp->vat_src_code.')') : ''), $mysoc, $object->thirdparty, $currentLineProductId, $objp->info_bits, $objp->product_type, false, 1);
1909 print '</td>';
1910
1911 // Price
1912 print '<td class="right"><input class="width50" type="text" name="elprice" value="'.(GETPOSTISSET('elprice') ? GETPOST('elprice') : price($objp->subprice)).'"></td>';
1913
1914 // Price multicurrency
1915 /*if (isModEnabled("multicurrency")) {
1916 print '<td class="linecoluht_currency nowrap right">'.price($objp->multicurrency_subprice).'</td>';
1917 }*/
1918
1919 // Quantity
1920 print '<td class="center"><input size="2" type="text" name="elqty" value="'.(GETPOSTISSET('elqty') ? GETPOST('elqty') : $objp->qty).'"></td>';
1921
1922 // Unit
1923 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1924 print '<td class="left">';
1925 print $form->selectUnits((GETPOSTISSET('unit') ? GETPOSTINT('unit') : $objp->fk_unit), "unit");
1926 print '</td>';
1927 }
1928
1929 // Discount
1930 print '<td class="nowraponall right"><input size="1" type="text" name="elremise_percent" value="'.(GETPOSTISSET('elremise_percent') ? GETPOST('elremise_percent') : $objp->remise_percent).'">%</td>';
1931
1932 if (!empty($usemargins)) {
1933 print '<td class="right">';
1934 if ($objp->fk_product) {
1935 print '<select id="fournprice" name="fournprice"></select>';
1936 }
1937 print '<input id="buying_price" type="text" class="width50" name="buying_price" value="'.price((GETPOSTISSET('buying_price') ? GETPOST('buying_price') : $objp->pa_ht), 0, '', 0).'"></td>';
1938 }
1939 print '<td class="center">';
1940 print '<input type="submit" class="button margintoponly marginbottomonly" name="save" value="'.$langs->trans("Modify").'">';
1941 print '<br><input type="submit" class="button margintoponly marginbottomonly button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
1942 print '</td>';
1943 print '</tr>';
1944
1945 $colspan = 6;
1946 if (isModEnabled('margin') && getDolGlobalString('MARGIN_SHOW_ON_CONTRACT')) {
1947 $colspan++;
1948 }
1949 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1950 $colspan++;
1951 }
1952
1953 // Line dates planned
1954 print '<tr class="oddeven">';
1955 print '<td colspan="'.$colspan.'">';
1956 print $langs->trans("DateStartPlanned").' ';
1957 print $form->selectDate($db->jdate($objp->date_start), "date_start_update", $usehm, $usehm, ($db->jdate($objp->date_start) > 0 ? 0 : 1), "update");
1958 print ' &nbsp;&nbsp;'.$langs->trans("DateEndPlanned").' ';
1959 print $form->selectDate($db->jdate($objp->date_end), "date_end_update", $usehm, $usehm, ($db->jdate($objp->date_end) > 0 ? 0 : 1), "update");
1960 print '</td>';
1961 print '</tr>';
1962
1963 if (is_array($extralabelslines) && count($extralabelslines) > 0) {
1964 $line = new ContratLigne($db);
1965 $line->id = $objp->rowid;
1966 $line->fetch_optionals();
1967
1968 print $line->showOptionals($extrafields, 'edit', array('style' => 'class="oddeven"', 'colspan' => $colspan, 'tdclass' => 'notitlefieldcreate'), '', '', '1');
1969 }
1970 }
1971
1972 $db->free($result);
1973 } else {
1974 dol_print_error($db);
1975 }
1976
1977 if ($object->statut > 0) {
1978 $moreparam = '';
1979 if (getDolGlobalString('CONTRACT_HIDE_CLOSED_SERVICES_BY_DEFAULT') && $object->lines[$cursorline - 1]->statut == ContratLigne::STATUS_CLOSED && $action != 'showclosedlines') {
1980 $moreparam = 'style="display: none;"';
1981 }
1982
1983 $colspan = 6;
1984 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1985 $colspan++;
1986 }
1987 if (isModEnabled('margin') && getDolGlobalString('MARGIN_SHOW_ON_CONTRACT')) {
1988 $colspan++;
1989 }
1990
1991 print '<tr class="oddeven" '.$moreparam.'>';
1992 print '<td class="tdhrthin" colspan="'.$colspan.'"><hr class="opacitymedium tdhrthin"></td>';
1993 print "</tr>\n";
1994 }
1995
1996 print "</table>";
1997 print '</div>';
1998
1999 print "</form>\n";
2000
2001
2002 /*
2003 * Confirmation to delete service line of contract
2004 */
2005 if ($action == 'deleteline' && !$cancel && $user->hasRight('contrat', 'creer') && $object->lines[$cursorline - 1]->id == $idline) {
2006 print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".((int) $object->id)."&lineid=".((int) $idline), $langs->trans("DeleteContractLine"), $langs->trans("ConfirmDeleteContractLine"), "confirm_deleteline", '', 0, 1);
2007 if ($ret == 'html') {
2008 print '<table class="notopnoleftnoright centpercent"><tr class="oddeven" height="6"><td></td></tr></table>';
2009 }
2010 }
2011
2012 /*
2013 * Confirmation to move service toward another contract
2014 */
2015 if ($action == 'move' && !$cancel && $user->hasRight('contrat', 'creer') && $object->lines[$cursorline - 1]->id == $idline) {
2016 $arraycontractid = array();
2017 foreach ($arrayothercontracts as $contractcursor) {
2018 $arraycontractid[$contractcursor->id] = $contractcursor->ref;
2019 }
2020 //var_dump($arraycontractid);
2021 // Cree un tableau formulaire
2022 $formquestion = array(
2023 'text' => $langs->trans("ConfirmMoveToAnotherContractQuestion"),
2024 0 => array('type' => 'select', 'name' => 'newcid', 'values' => $arraycontractid));
2025
2026 print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".((int) $object->id)."&lineid=".((int) $idline), $langs->trans("MoveToAnotherContract"), $langs->trans("ConfirmMoveToAnotherContract"), "confirm_move", $formquestion, 'yes');
2027 print '<table class="notopnoleftnoright centpercent"><tr class="oddeven" height="6"><td></td></tr></table>';
2028 }
2029
2030 // Area with status and activation info of line
2031 if ($object->status > 0) {
2032 print '<table class="notopnoleftnoright tableforservicepart2'.($cursorline < $nbofservices ? ' boxtablenobottom' : '').' centpercent">';
2033
2034 print '<tr class="oddeven" '.$moreparam.'>';
2035 print '<td><span class="valignmiddle hideonsmartphone">'.$langs->trans("ServiceStatus").':</span> '.$object->lines[$cursorline - 1]->getLibStatut(4).'</td>';
2036 print '<td width="30" class="right">';
2037 if ($user->socid == 0) {
2038 if ($object->status > 0 && $action != 'activateline' && $action != 'unactivateline' && is_object($objp)) {
2039 $tmpaction = 'activateline';
2040 $tmpactionpicto = 'play';
2041 $tmpactiontext = $langs->trans("Activate");
2042 if ($objp->statut == 4) {
2043 $tmpaction = 'unactivateline';
2044 $tmpactionpicto = 'playstop.png';
2045 $tmpactiontext = $langs->trans("Disable");
2046 }
2047 if (($tmpaction == 'activateline' && $user->hasRight('contrat', 'activer')) || ($tmpaction == 'unactivateline' && $user->hasRight('contrat', 'desactiver'))) {
2048 print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;ligne='.$object->lines[$cursorline - 1]->id.'&amp;action='.$tmpaction.'&token='.newToken().'">';
2049 print img_picto($tmpactiontext, $tmpactionpicto);
2050 print '</a>';
2051 }
2052 }
2053 }
2054 print '</td>';
2055 print "</tr>\n";
2056
2057 print '<tr class="oddeven" '.$moreparam.'>';
2058
2059 print '<td>';
2060 // Si pas encore active
2061 if (!$objp->date_start_real) {
2062 print $langs->trans("DateStartReal").': ';
2063 if ($objp->date_start_real) {
2064 print dol_print_date($db->jdate($objp->date_start_real), 'day');
2065 } else {
2066 print $langs->trans("ContractStatusNotRunning");
2067 }
2068 }
2069 // Si active et en cours
2070 if ($objp->date_start_real && !$objp->date_end_real) {
2071 print $langs->trans("DateStartReal").': ';
2072 print dol_print_date($db->jdate($objp->date_start_real), 'day');
2073 }
2074 // Si desactive
2075 if ($objp->date_start_real && $objp->date_end_real) {
2076 print $langs->trans("DateStartReal").': ';
2077 print dol_print_date($db->jdate($objp->date_start_real), 'day');
2078 print ' &nbsp;-&nbsp; ';
2079 print $langs->trans("DateEndReal").': ';
2080 print dol_print_date($db->jdate($objp->date_end_real), 'day');
2081 }
2082 if (!empty($objp->comment)) {
2083 print " &nbsp;-&nbsp; ".$objp->comment;
2084 }
2085 print '</td>';
2086
2087 print '<td class="center">&nbsp;</td>';
2088
2089 print '</tr>';
2090 print '</table>';
2091 }
2092
2093 // Form to activate line
2094 if ($permissiontoactivate && $action == 'activateline' && $object->lines[$cursorline - 1]->id == GETPOSTINT('ligne') && is_object($objp)) {
2095 print '<form name="active" action="'.$_SERVER["PHP_SELF"].'" method="POST">';
2096 print '<input type="hidden" name="token" value="'.newToken().'">';
2097 print '<input type="hidden" name="action" value="confirm_active">';
2098 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
2099 print '<input type="hidden" name="id" value="'.$object->id.'">';
2100 print '<input type="hidden" name="ligne" value="'.GETPOSTINT('ligne').'">';
2101 print '<input type="hidden" name="confirm" value="yes">';
2102
2103 print '<table class="noborder tableforservicepart2'.($cursorline < $nbofservices ? ' boxtablenobottom' : '').' centpercent">';
2104
2105 // Definie date debut et fin par default
2106 $dateactstart = $objp->date_start;
2107 if (GETPOST('remonth')) {
2108 $dateactstart = dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
2109 } elseif (!$dateactstart) {
2110 $dateactstart = time();
2111 }
2112
2113 $dateactend = $objp->date_end;
2114 if (GETPOST('endmonth')) {
2115 $dateactend = dol_mktime(12, 0, 0, GETPOSTINT('endmonth'), GETPOSTINT('endday'), GETPOSTINT('endyear'));
2116 } elseif (!$dateactend) {
2117 if ($objp->fk_product > 0) {
2118 $product = new Product($db);
2119 $product->fetch($objp->fk_product);
2120 if (!empty($product->duration_value) && !empty($product->duration_unit)) {
2121 $dateactend = dol_time_plus_duree(time(), $product->duration_value, $product->duration_unit);
2122 }
2123 }
2124 }
2125
2126 print '<tr class="oddeven">';
2127 print '<td class="nohover">'.$langs->trans("DateServiceActivate").'</td><td class="nohover">';
2128 print $form->selectDate($dateactstart, 'start', $usehm, $usehm, 0, "active", 1, 0);
2129 print '</td>';
2130 print '<td class="nohover">'.$langs->trans("DateEndPlanned").'</td><td class="nohover">';
2131 print $form->selectDate($dateactend, "end", $usehm, $usehm, 0, "active", 1, 0);
2132 print '</td>';
2133 print '<td class="center nohover">';
2134 print '</td>';
2135
2136 print '</tr>';
2137
2138 print '<tr class="oddeven">';
2139 print '<td class="nohover">'.$langs->trans("Comment").'</td><td colspan="3" class="nohover" colspan="'.(isModEnabled('margin') ? 4 : 3).'"><input type="text" class="minwidth300" name="comment" value="'.dol_escape_htmltag(GETPOST("comment", 'alphanohtml')).'"></td>';
2140 print '<td class="nohover right">';
2141 print '<input type="submit" class="button" name="activate" value="'.$langs->trans("Activate").'"> &nbsp; ';
2142 print '<input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
2143 print '</td>';
2144 print '</tr>';
2145
2146 print '</table>';
2147
2148 print '</form>';
2149 }
2150
2151 // Form to disable a contract line
2152 if ($permissiontodisable && $action == 'unactivateline' && $object->lines[$cursorline - 1]->id == GETPOSTINT('ligne') && is_object($objp)) {
2153 print '<!-- Form to disabled a line -->'."\n";
2154 print '<form name="confirm_closeline" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;ligne='.$object->lines[$cursorline - 1]->id.'" method="post">';
2155 print '<input type="hidden" name="token" value="'.newToken().'">';
2156 print '<input type="hidden" name="confirm" value="yes">';
2157 print '<input type="hidden" name="action" value="confirm_closeline">';
2158 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
2159
2160 print '<table class="noborder tableforservicepart2'.($cursorline < $nbofservices ? ' boxtablenobottom' : '').' centpercent">';
2161
2162 // Definie date debut et fin par default
2163 $dateactstart = $objp->date_start_real;
2164 if (GETPOST('remonth')) {
2165 $dateactstart = dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
2166 } elseif (!$dateactstart) {
2167 $dateactstart = time();
2168 }
2169
2170 $dateactend = $objp->date_end_real;
2171 if (GETPOST('endmonth')) {
2172 $dateactend = dol_mktime(12, 0, 0, GETPOSTINT('endmonth'), GETPOSTINT('endday'), GETPOSTINT('endyear'));
2173 } elseif (!$dateactend) {
2174 if ($objp->fk_product > 0) {
2175 $product = new Product($db);
2176 $product->fetch($objp->fk_product);
2177 $dateactend = dol_time_plus_duree(time(), $product->duration_value, $product->duration_unit);
2178 }
2179 }
2180 $now = dol_now();
2181 if ($dateactend > $now) {
2182 $dateactend = $now;
2183 }
2184
2185 print '<tr class="oddeven"><td colspan="2" class="nohover">';
2186 if ($objp->statut >= 4) {
2187 if ($objp->statut == 4) {
2188 print $langs->trans("DateEndReal").' ';
2189 print $form->selectDate($dateactend, "end", $usehm, $usehm, ($objp->date_end_real > 0 ? 0 : 1), "closeline", 1, 1);
2190 }
2191 }
2192 print '</td>';
2193 print '<td class="center nohover">';
2194 print '</td></tr>';
2195
2196 print '<tr class="oddeven">';
2197 print '<td class="nohover">'.$langs->trans("Comment").'</td><td class="nohover"><input class="quatrevingtpercent" type="text" class="flat" name="comment" value="'.dol_escape_htmltag(GETPOST('comment', 'alpha')).'"></td>';
2198 print '<td class="nohover right">';
2199 print '<input type="submit" class="button" name="close" value="'.$langs->trans("Disable").'"> &nbsp; ';
2200 print '<input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
2201 print '</td>';
2202 print '</tr>';
2203
2204 print '</table>';
2205
2206 print '</form>';
2207 }
2208 print '</div>';
2209 $cursorline++;
2210 }
2211 print '</div>';
2212 }
2213
2214 // Form to add new line
2215 if ($user->hasRight('contrat', 'creer') && ($object->status == 0)) {
2216 $dateSelector = 1;
2217
2218 print "\n";
2219 print ' <form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline') ? '' : '#line_'.GETPOSTINT('lineid')).'" method="POST">
2220 <input type="hidden" name="token" value="'.newToken().'">
2221 <input type="hidden" name="action" value="'.(($action != 'editline') ? 'addline' : 'updateline').'">
2222 <input type="hidden" name="mode" value="">
2223 <input type="hidden" name="id" value="'.$object->id.'">
2224 <input type="hidden" name="page_y" value="">
2225 <input type="hidden" name="backtopage" value="'.$backtopage.'">
2226 ';
2227
2228 print '<div class="div-table-responsive-no-min">';
2229 print '<table id="tablelines" class="noborder noshadow" width="100%">'; // Array with (n*2)+1 lines
2230
2231 // Form to add new line
2232 if ($action != 'editline') {
2233 $forcetoshowtitlelines = 1;
2234 if (empty($object->multicurrency_code)) {
2235 $object->multicurrency_code = $conf->currency; // TODO Remove this when multicurrency supported on contracts
2236 }
2237
2238 // Add free products/services
2239
2240 $parameters = array();
2241 $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2242 if ($reshook < 0) {
2243 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2244 }
2245 if (empty($reshook)) {
2246 $object->formAddObjectLine(1, $mysoc, $soc);
2247 }
2248 }
2249
2250 print '</table>';
2251 print '</div>';
2252 print '</form>';
2253 }
2254
2255 print dol_get_fiche_end();
2256
2257 // Select mail models is same action as presend
2258 if (GETPOST('modelselected')) {
2259 $action = 'presend';
2260 }
2261
2262 /*
2263 * Buttons
2264 */
2265 if ($user->socid == 0 && $action != 'presend' && $action != 'editline') {
2266 print '<div class="tabsAction">';
2267
2268 $parameters = array();
2269 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2270
2271 if (empty($reshook)) {
2272 $params = array(
2273 'attr' => array(
2274 'title' => '',
2275 'class' => 'classfortooltip'
2276 )
2277 );
2278
2279 // Send
2280 if (empty($user->socid)) {
2281 if ($object->status == $object::STATUS_VALIDATED) {
2282 if ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || $user->hasRight('contrat', 'creer'))) {
2283 print dolGetButtonAction('', $langs->trans('SendMail'), 'email', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&token='.newToken().'&mode=init#formmailbeforetitle', '', true, $params);
2284 } else {
2285 print dolGetButtonAction('', $langs->trans('SendMail'), 'email', '#', '', false, $params);
2286 }
2287 }
2288 }
2289
2290 if ($object->status == $object::STATUS_DRAFT && $nbofservices) {
2291 if ($user->hasRight('contrat', 'creer')) {
2292 unset($params['attr']['title']);
2293 print dolGetButtonAction($langs->trans('Validate'), '', 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=valid&token='.newToken(), '', true, $params);
2294 } else {
2295 $params['attr']['title'] = $langs->trans("NotEnoughPermissions");
2296 print dolGetButtonAction($langs->trans('Validate'), '', 'default', '#', '', false, $params);
2297 }
2298 }
2299 if ($object->status == $object::STATUS_VALIDATED) {
2300 if ($user->hasRight('contrat', 'creer')) {
2301 unset($params['attr']['title']);
2302 print dolGetButtonAction($langs->trans('Modify'), '', 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken(), '', true, $params);
2303 } else {
2304 $params['attr']['title'] = $langs->trans("NotEnoughPermissions");
2305 print dolGetButtonAction($langs->trans('Modify'), '', 'default', '#', '', false, $params);
2306 }
2307 }
2308
2309 // Create ... buttons
2310 $arrayofcreatebutton = array();
2311 if (isModEnabled('propal') && $object->status > 0 && $soc->client > 0) {
2312 $arrayofcreatebutton[] = array(
2313 'url' => '/comm/propal/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->thirdparty->id.'&renewal=true',
2314 'label' => $langs->trans('AddProp'),
2315 'lang' => 'propal',
2316 'perm' => $user->hasRight('propale', 'creer') ? true : false,
2317 'enabled' => true,
2318 );
2319 }
2320 //if (isModEnabled('order') && $object->status > 0 && $object->nbofservicesclosed < $nbofservices) {
2321 if (isModEnabled('order') && $object->status > 0 && $soc->client > 0) {
2322 $arrayofcreatebutton[] = array(
2323 'url' => '/commande/card.php?action=create&token='.newToken().'&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->thirdparty->id,
2324 'label' => $langs->trans('AddOrder'),
2325 'lang' => 'orders',
2326 'perm' => $user->hasRight('commande', 'creer') ? true : false,
2327 'enabled' => true,
2328 );
2329 }
2330 if (isModEnabled('invoice') && $object->status > 0 && $soc->client > 0) {
2331 $arrayofcreatebutton[] = array(
2332 'url' => '/compta/facture/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->thirdparty->id,
2333 'label' => $langs->trans('CreateBill'),
2334 'lang' => 'bills',
2335 'perm' => $user->hasRight('facture', 'creer') ? true : false,
2336 'enabled' => true,
2337 );
2338 }
2339 if (isModEnabled('supplier_invoice') && $object->status > 0 && $soc->fournisseur == 1) {
2340 $langs->load("suppliers");
2341 $arrayofcreatebutton[] = array(
2342 'url' => '/fourn/facture/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->thirdparty->id,
2343 'label' => $langs->trans('AddSupplierInvoice'),
2344 'lang' => 'bills',
2345 'perm' => $user->hasRight('fournisseur', 'facture', 'creer') ? true : false,
2346 'enabled' => true,
2347 );
2348 }
2349 if (count($arrayofcreatebutton)) {
2350 unset($params['attr']['title']);
2351 print dolGetButtonAction('', $langs->trans("Create"), 'default', $arrayofcreatebutton, '', true, $params);
2352 }
2353
2354 $arrayforbutaction = array();
2355 $arrayforbutaction[] = array(
2356 'url' => '/contrat/card.php?id='.$object->id.'&action=activate&token='.newToken(),
2357 'label' => $langs->trans('ActivateAllContracts'),
2358 'lang' => 'bills',
2359 'perm' => ($object->nbofservicesclosed > 0 || $object->nbofserviceswait > 0) ? $permissiontoactivate : -1,
2360 'enabled' => true,
2361 );
2362 $arrayforbutaction[] = array(
2363 'url' => '/contrat/card.php?id='.$object->id.'&action=close&token='.newToken(),
2364 'label' => $langs->trans('CloseAllContracts'),
2365 'lang' => 'bills',
2366 'perm' => ($object->nbofservicesclosed < $nbofservices) ? $permissiontodisable : -1,
2367 'enabled' => true,
2368 );
2369
2370 if (count($arrayforbutaction)) {
2371 unset($params['attr']['title']);
2372 print dolGetButtonAction('', $langs->trans("Enable")." / ".$langs->trans("Close"), 'default', $arrayforbutaction, '', true, $params);
2373 }
2374
2375 if (getDolGlobalString('CONTRACT_HIDE_CLOSED_SERVICES_BY_DEFAULT') && $object->nbofservicesclosed > 0) {
2376 if ($action == 'showclosedlines') {
2377 print '<div class="inline-block divButAction"><a class="butAction" id="btnhideclosedlines" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=hideclosedlines">'.$langs->trans("HideClosedServices").'</a></div>';
2378 } else {
2379 print '<div class="inline-block divButAction"><a class="butAction" id="btnshowclosedlines" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=showclosedlines">'.$langs->trans("ShowClosedServices").'</a></div>';
2380 }
2381 }
2382
2383 // Sign
2384 if (getDolGlobalString('CONTRACT_SHOW_SIGNATURE_STATUS_WITH_SERVICE_STATUS') && $object->status > Contrat::STATUS_DRAFT) {
2385 if ($object->signed_status != Contrat::$SIGNED_STATUSES['STATUS_SIGNED_ALL']) {
2386 print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=sign&token=' . newToken() . '">' . $langs->trans("ContractSign") . '</a></div>';
2387 } else {
2388 print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=unsign&token=' . newToken() . '">' . $langs->trans("ContractUnsign") . '</a></div>';
2389 }
2390 }
2391
2392 // Clone
2393 if ($user->hasRight('contrat', 'creer')) {
2394 unset($params['attr']['title']);
2395 print dolGetButtonAction($langs->trans('ToClone'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&socid='.$object->socid.'&action=clone&token='.newToken(), '', true, $params);
2396 }
2397
2398 // Delete
2399 unset($params['attr']['title']);
2400 print dolGetButtonAction($langs->trans('Delete'), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken(), '', $permissiontodelete, $params);
2401 }
2402
2403 print "</div>";
2404 }
2405
2406 if ($action != 'presend') {
2407 print '<div class="fichecenter"><div class="fichehalfleft">';
2408
2409 /*
2410 * Generated documents
2411 */
2412 $filename = dol_sanitizeFileName($object->ref);
2413 $filedir = $conf->contract->multidir_output[$object->entity ?? $conf->entity]."/".dol_sanitizeFileName($object->ref);
2414 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
2415 $genallowed = $user->hasRight('contrat', 'lire');
2416 $delallowed = $user->hasRight('contrat', 'creer');
2417
2418
2419 print $formfile->showdocuments('contract', $filename, $filedir, $urlsource, $genallowed, $delallowed, ($object->model_pdf ? $object->model_pdf : getDolGlobalString('CONTRACT_ADDON_PDF')), 1, 0, 0, 28, 0, '', '0', '', $soc->default_lang, '', $object);
2420
2421
2422 // Show links to link elements
2423 $tmparray = $form->showLinkToObjectBlock($object, array(), array('contrat'), 1);
2424 $linktoelem = $tmparray['linktoelem'];
2425 $htmltoenteralink = $tmparray['htmltoenteralink'];
2426 print $htmltoenteralink;
2427
2428 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
2429
2430 // Show online signature link
2431 if ($object->status != Contrat::STATUS_DRAFT && getDolGlobalString('CONTRACT_ALLOW_ONLINESIGN')) {
2432 print '<br><!-- Link to sign -->';
2433 require_once DOL_DOCUMENT_ROOT.'/core/lib/signature.lib.php';
2434
2435 print showOnlineSignatureUrl('contract', $object->ref, $object).'<br>';
2436 }
2437
2438 print '</div><div class="fichehalfright">';
2439
2440 $MAXEVENT = 10;
2441
2442 $morehtmlcenter = '<div class="nowraponall">';
2443 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullConversation'), '', 'fa fa-comments imgforviewmode', DOL_URL_ROOT.'/contrat/messaging.php?id='.$object->id);
2444 $morehtmlcenter .= dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/contrat/agenda.php?id='.$object->id);
2445 $morehtmlcenter .= '</div>';
2446
2447
2448 // List of actions on element
2449 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
2450 $formactions = new FormActions($db);
2451 $somethingshown = $formactions->showactions($object, 'contract', $socid, 1, 'listactions', $MAXEVENT, '', $morehtmlcenter);
2452
2453 print '</div></div>';
2454 }
2455
2456 // Presend form
2457 $modelmail = 'contract';
2458 $defaulttopic = 'SendContractRef';
2459 $diroutput = $conf->contract->multidir_output[$object->entity ?? $conf->entity];
2460 $trackid = 'con'.$object->id;
2461
2462 include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
2463 }
2464}
2465
2466
2467llxFooter();
2468
2469$db->close();
2470
2471
2472// TODO Why this on the page when editing margin for contracts ?
2473if (isModEnabled('margin') && $action == 'editline') {
2474 print "\n".'<script type="text/javascript">'."\n";
2475 ?>
2476 $(document).ready(function() {
2477 var idprod = $("input[name='idprod']").val();
2478 var fournprice = $("input[name='fournprice']").val();
2479 var token = '<?php echo currentToken(); ?>'; // For AJAX Call we use old 'token' and not 'newtoken'
2480 if (idprod > 0) {
2481 $.post('<?php echo DOL_URL_ROOT; ?>/fourn/ajax/getSupplierPrices.php', {
2482 'idprod': idprod,
2483 'token': token
2484 }, function(data) {
2485 if (data.length > 0) {
2486 var options = '';
2487 var trouve=false;
2488 $(data).each(function() {
2489 options += '<option value="'+this.id+'" price="'+this.price+'"';
2490 if (fournprice > 0) {
2491 if (this.id == fournprice) {
2492 options += ' selected';
2493 $("#buying_price").val(this.price);
2494 trouve = true;
2495 }
2496 }
2497 options += '>'+this.label+'</option>';
2498 });
2499 options += '<option value=null'+(trouve?'':' selected')+'><?php echo $langs->trans("InputPrice"); ?></option>';
2500 $("#fournprice").html(options);
2501 if (trouve) {
2502 $("#buying_price").hide();
2503 $("#fournprice").show();
2504 }
2505 else {
2506 $("#buying_price").show();
2507 }
2508 $("#fournprice").change(function() {
2509 var selval = $(this).find('option:selected').attr("price");
2510 if (selval)
2511 $("#buying_price").val(selval).hide();
2512 else
2513 $('#buying_price').show();
2514 });
2515 }
2516 else {
2517 $("#fournprice").hide();
2518 $('#buying_price').show();
2519 }
2520 },
2521 'json');
2522 }
2523 else {
2524 $("#fournprice").hide();
2525 $('#buying_price').show();
2526 }
2527 });
2528 <?php
2529 print "\n".'<script type="text/javascript">'."\n";
2530}
$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
Class to manage lines of contracts.
Class to manage a WYSIWYG editor.
Class to manage standard extra fields.
Class to manage building of HTML components.
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
Class to manage building of HTML components.
Class to manage the table of subscription to notifications.
File of class to manage predefined price products or services by customer.
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.
global $mysoc
contract_prepare_head(Contrat $object)
Prepare array with list of tabs.
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:125
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
dol_move_dir($srcdir, $destdir, $overwriteifexists=1, $indexdatabase=1, $renamedircontent=1)
Move a directory into another name.
dol_now($mode='gmt')
Return date for now.
recordNotFound($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Displays an error page when a record is not found.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formatted for view output Used into pdf and HTML pages.
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_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dolBuildUrl($url, $params=[], $addtoken=false)
Return path of url.
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 '.
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
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)
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
img_down($titlealt='default', $selected=0, $moreclass='')
Show down arrow logo.
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.
GETPOSTISARRAY($paramname, $method=0)
Return true if the parameter $paramname is submit from a POST OR GET as an array.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dolGetButtonAction($label, $text='', $actionType='default', $url='', $id='', $userRight=1, $params=array())
Function dolGetButtonAction.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_clone($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.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
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.
img_up($titlealt='default', $selected=0, $moreclass='')
Show top arrow logo.
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,...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
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...
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.