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