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