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