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 
34 require "../main.inc.php";
35 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
36 require_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
37 require_once DOL_DOCUMENT_ROOT.'/core/lib/contract.lib.php';
38 require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
39 require_once DOL_DOCUMENT_ROOT.'/core/modules/contract/modules_contract.php';
40 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
41 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
42 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
43 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
44 if (isModEnabled("propal")) {
45  require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
46 }
47 if (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 }
51 require_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
71 if ($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
83 if ($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
113 if ($reshook < 0) {
114  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
115 }
116 if (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  setEventMessages($objectline->error, $objectline->errors, 'errors');
806  }
807  }
808 
809  if (!$error) {
810  $db->commit();
811  } else {
812  $db->rollback();
813  }
814  } elseif ($action == 'confirm_deleteline' && $confirm == 'yes' && $user->hasRight('contrat', 'creer')) {
815  $result = $object->deleteline(GETPOST('lineid', 'int'), $user);
816 
817  if ($result >= 0) {
818  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
819  exit;
820  } else {
821  setEventMessages($object->error, $object->errors, 'errors');
822  }
823  } elseif ($action == 'confirm_valid' && $confirm == 'yes' && $user->hasRight('contrat', 'creer')) {
824  $result = $object->validate($user);
825 
826  if ($result > 0) {
827  // Define output language
828  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
829  $outputlangs = $langs;
830  $newlang = '';
831  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
832  $newlang = GETPOST('lang_id', 'aZ09');
833  }
834  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
835  $newlang = $object->thirdparty->default_lang;
836  }
837  if (!empty($newlang)) {
838  $outputlangs = new Translate("", $conf);
839  $outputlangs->setDefaultLang($newlang);
840  }
841  $model = $object->model_pdf;
842  $ret = $object->fetch($id); // Reload to get new records
843 
844  $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
845  }
846  } else {
847  setEventMessages($object->error, $object->errors, 'errors');
848  }
849  } elseif ($action == 'reopen' && $user->hasRight('contrat', 'creer')) {
850  $result = $object->reopen($user);
851  if ($result < 0) {
852  setEventMessages($object->error, $object->errors, 'errors');
853  }
854  } elseif ($action == 'confirm_close' && $confirm == 'yes' && $user->hasRight('contrat', 'creer')) {
855  // Close all lines
856  $result = $object->closeAll($user);
857  if ($result < 0) {
858  setEventMessages($object->error, $object->errors, 'errors');
859  }
860  } elseif ($action == 'confirm_activate' && $confirm == 'yes' && $user->hasRight('contrat', 'creer')) {
861  $date_start = dol_mktime(12, 0, 0, GETPOST('d_startmonth'), GETPOST('d_startday'), GETPOST('d_startyear'));
862  $date_end = dol_mktime(12, 0, 0, GETPOST('d_endmonth'), GETPOST('d_endday'), GETPOST('d_endyear'));
863  $comment = GETPOST('comment', 'alpha');
864  $result = $object->activateAll($user, $date_start, 0, $comment, $date_end);
865  if ($result < 0) {
866  setEventMessages($object->error, $object->errors, 'errors');
867  }
868  } elseif ($action == 'confirm_delete' && $confirm == 'yes' && $user->hasRight('contrat', 'supprimer')) {
869  $result = $object->delete($user);
870  if ($result >= 0) {
871  header("Location: list.php?restore_lastsearch_values=1");
872  return;
873  } else {
874  setEventMessages($object->error, $object->errors, 'errors');
875  }
876  } elseif ($action == 'confirm_move' && $confirm == 'yes' && $user->hasRight('contrat', 'creer')) {
877  if (GETPOST('newcid') > 0) {
878  $contractline = new ContratLigne($db);
879  $result = $contractline->fetch(GETPOSTINT('lineid'));
880  $contractline->fk_contrat = GETPOSTINT('newcid');
881  $result = $contractline->update($user, 1);
882  if ($result >= 0) {
883  header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
884  return;
885  } else {
886  setEventMessages($object->error, $object->errors, 'errors');
887  }
888  } else {
889  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("RefNewContract")), null, 'errors');
890  }
891  } elseif ($action == 'update_extras') {
892  $object->oldcopy = dol_clone($object);
893 
894  // Fill array 'array_options' with data from update form
895  $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml'));
896  if ($ret < 0) {
897  $error++;
898  }
899 
900  if (!$error) {
901  $result = $object->insertExtraFields('CONTRACT_MODIFY');
902  if ($result < 0) {
903  setEventMessages($object->error, $object->errors, 'errors');
904  $error++;
905  }
906  }
907 
908  if ($error) {
909  $action = 'edit_extras';
910  }
911  } elseif ($action == 'setref_supplier') {
912  if (!$cancel) {
913  $object->oldcopy = dol_clone($object);
914 
915  $result = $object->setValueFrom('ref_supplier', GETPOST('ref_supplier', 'alpha'), '', null, 'text', '', $user, 'CONTRACT_MODIFY');
916  if ($result < 0) {
917  setEventMessages($object->error, $object->errors, 'errors');
918  $action = 'editref_supplier';
919  } else {
920  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
921  exit;
922  }
923  } else {
924  header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
925  exit;
926  }
927  } elseif ($action == 'setref_customer') {
928  if (!$cancel) {
929  $object->oldcopy = dol_clone($object);
930 
931  $result = $object->setValueFrom('ref_customer', GETPOST('ref_customer', 'alpha'), '', null, 'text', '', $user, 'CONTRACT_MODIFY');
932  if ($result < 0) {
933  setEventMessages($object->error, $object->errors, 'errors');
934  $action = 'editref_customer';
935  } else {
936  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
937  exit;
938  }
939  } else {
940  header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
941  exit;
942  }
943  } elseif ($action == 'setref') {
944  if (!$cancel) {
945  $result = $object->fetch($id);
946  if ($result < 0) {
947  setEventMessages($object->error, $object->errors, 'errors');
948  }
949 
950  $old_ref = $object->ref;
951 
952  $result = $object->setValueFrom('ref', GETPOST('ref', 'alpha'), '', null, 'text', '', $user, 'CONTRACT_MODIFY');
953  if ($result < 0) {
954  setEventMessages($object->error, $object->errors, 'errors');
955  $action = 'editref';
956  } else {
957  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
958  $old_filedir = $conf->contrat->multidir_output[$object->entity].'/'.dol_sanitizeFileName($old_ref);
959  $new_filedir = $conf->contrat->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref);
960 
961  // Rename directory of contract with new name
962  dol_move_dir($old_filedir, $new_filedir);
963 
964  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
965  exit;
966  }
967  } else {
968  header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
969  exit;
970  }
971  } elseif ($action == 'setdate_contrat') {
972  if (!$cancel) {
973  $result = $object->fetch($id);
974  if ($result < 0) {
975  setEventMessages($object->error, $object->errors, 'errors');
976  }
977  $datacontrat = dol_mktime(GETPOST('date_contrathour'), GETPOST('date_contratmin'), 0, GETPOST('date_contratmonth'), GETPOST('date_contratday'), GETPOST('date_contratyear'));
978  $result = $object->setValueFrom('date_contrat', $datacontrat, '', null, 'date', '', $user, 'CONTRACT_MODIFY');
979  if ($result < 0) {
980  setEventMessages($object->error, $object->errors, 'errors');
981  $action = 'editdate_contrat';
982  } else {
983  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
984  exit;
985  }
986  } else {
987  header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
988  exit;
989  }
990  }
991 
992  // Actions when printing a doc from card
993  include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
994 
995  // Actions to build doc
996  $upload_dir = $conf->contrat->multidir_output[$object->entity];
997  include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
998 
999  // Actions to send emails
1000  $triggersendname = 'CONTRACT_SENTBYMAIL';
1001  $paramname = 'id';
1002  $mode = 'emailfromcontract';
1003  $trackid = 'con'.$object->id;
1004  include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
1005 
1006 
1007  if (!empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && $user->hasRight('contrat', 'creer')) {
1008  if ($action == 'addcontact') {
1009  $contactid = (GETPOST('userid') ? GETPOST('userid') : GETPOST('contactid'));
1010  $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
1011  $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09'));
1012 
1013  if ($result >= 0) {
1014  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1015  exit;
1016  } else {
1017  if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
1018  $langs->load("errors");
1019  setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
1020  } else {
1021  setEventMessages($object->error, $object->errors, 'errors');
1022  }
1023  }
1024  } elseif ($action == 'swapstatut') {
1025  // bascule du statut d'un contact
1026  $result = $object->swapContactStatus(GETPOST('ligne', 'int'));
1027  } elseif ($action == 'deletecontact') {
1028  // Efface un contact
1029  $result = $object->delete_contact(GETPOST('lineid', 'int'));
1030 
1031  if ($result >= 0) {
1032  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1033  exit;
1034  } else {
1035  setEventMessages($object->error, $object->errors, 'errors');
1036  }
1037  }
1038  }
1039 
1040  // Action clone object
1041  if ($action == 'confirm_clone' && $confirm == 'yes') {
1042  if (!GETPOST('socid', 3)) {
1043  setEventMessages($langs->trans("NoCloneOptionsSpecified"), null, 'errors');
1044  } else {
1045  if ($object->id > 0) {
1046  $result = $object->createFromClone($user, $socid);
1047  if ($result > 0) {
1048  header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result);
1049  exit();
1050  } else {
1051  if (count($object->errors) > 0) {
1052  setEventMessages($object->error, $object->errors, 'errors');
1053  }
1054  $action = '';
1055  }
1056  }
1057  }
1058  }
1059 }
1060 
1061 
1062 /*
1063  * View
1064  */
1065 
1066 
1067 $help_url = 'EN:Module_Contracts|FR:Module_Contrat';
1068 
1069 llxHeader('', $langs->trans("Contract"), $help_url);
1070 
1071 $form = new Form($db);
1072 $formfile = new FormFile($db);
1073 if (isModEnabled('project')) {
1074  $formproject = new FormProjets($db);
1075 }
1076 
1077 // Load object modContract
1078 $module = (!empty($conf->global->CONTRACT_ADDON) ? $conf->global->CONTRACT_ADDON : 'mod_contract_serpis');
1079 if (substr($module, 0, 13) == 'mod_contract_' && substr($module, -3) == 'php') {
1080  $module = substr($module, 0, dol_strlen($module) - 4);
1081 }
1082 $result = dol_include_once('/core/modules/contract/'.$module.'.php');
1083 if ($result > 0) {
1084  $modCodeContract = new $module();
1085 }
1086 
1087 // Create
1088 if ($action == 'create') {
1089  print load_fiche_titre($langs->trans('AddContract'), '', 'contract');
1090 
1091  $soc = new Societe($db);
1092  if ($socid > 0) {
1093  $soc->fetch($socid);
1094  }
1095 
1096  if (GETPOST('origin') && GETPOST('originid', 'int')) {
1097  // Parse element/subelement (ex: project_task)
1098  $regs = array();
1099  $element = $subelement = GETPOST('origin');
1100  if (preg_match('/^([^_]+)_([^_]+)/i', GETPOST('origin'), $regs)) {
1101  $element = $regs[1];
1102  $subelement = $regs[2];
1103  }
1104 
1105  if ($element == 'project') {
1106  $projectid = GETPOST('originid', 'int');
1107  } else {
1108  // For compatibility
1109  if ($element == 'order' || $element == 'commande') {
1110  $element = $subelement = 'commande';
1111  }
1112  if ($element == 'propal') {
1113  $element = 'comm/propal'; $subelement = 'propal';
1114  }
1115  if ($element == 'invoice' || $element == 'facture') {
1116  $element = 'compta/facture';
1117  $subelement = 'facture';
1118  }
1119 
1120  dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
1121 
1122  $classname = ucfirst($subelement);
1123  $objectsrc = new $classname($db);
1124  $objectsrc->fetch($originid);
1125  if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
1126  $objectsrc->fetch_lines();
1127  }
1128  $objectsrc->fetch_thirdparty();
1129 
1130  // Replicate extrafields
1131  $objectsrc->fetch_optionals();
1132  $object->array_options = $objectsrc->array_options;
1133 
1134  $projectid = (!empty($objectsrc->fk_project) ? $objectsrc->fk_project : '');
1135 
1136  $soc = $objectsrc->thirdparty;
1137 
1138  $note_private = (!empty($objectsrc->note_private) ? $objectsrc->note_private : '');
1139  $note_public = (!empty($objectsrc->note_public) ? $objectsrc->note_public : '');
1140 
1141  // Object source contacts list
1142  $srccontactslist = $objectsrc->liste_contact(-1, 'external', 1);
1143  }
1144  } else {
1145  $projectid = GETPOST('projectid', 'int');
1146  $note_private = GETPOST("note_private");
1147  $note_public = GETPOST("note_public");
1148  }
1149 
1150  $object->date_contrat = dol_now();
1151 
1152  print '<form name="form_contract" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1153  print '<input type="hidden" name="token" value="'.newToken().'">';
1154  print '<input type="hidden" name="action" value="add">';
1155  print '<input type="hidden" name="socid" value="'.$soc->id.'">'."\n";
1156  print '<input type="hidden" name="remise_percent" value="0">';
1157  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1158 
1159  print dol_get_fiche_head();
1160 
1161  print '<table class="border centpercent">';
1162 
1163  // Ref
1164  print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans('Ref').'</td><td>';
1165  if (!empty($modCodeContract->code_auto)) {
1166  $tmpcode = $langs->trans("Draft");
1167  } else {
1168  $tmpcode = '<input name="ref" class="maxwidth100" maxlength="128" value="'.dol_escape_htmltag(GETPOST('ref') ?GETPOST('ref') : $tmpcode).'">';
1169  }
1170  print $tmpcode;
1171  print '</td></tr>';
1172 
1173  // Ref customer
1174  print '<tr><td>'.$langs->trans('RefCustomer').'</td>';
1175  print '<td><input type="text" class="maxwidth150" name="ref_customer" id="ref_customer" value="'.dol_escape_htmltag(GETPOST('ref_customer', 'alpha')).'"></td></tr>';
1176 
1177  // Ref supplier
1178  print '<tr><td>'.$langs->trans('RefSupplier').'</td>';
1179  print '<td><input type="text" class="maxwidth150" name="ref_supplier" id="ref_supplier" value="'.dol_escape_htmltag(GETPOST('ref_supplier', 'alpha')).'"></td></tr>';
1180 
1181  // Thirdparty
1182  print '<tr>';
1183  print '<td class="fieldrequired">'.$langs->trans('ThirdParty').'</td>';
1184  if ($socid > 0) {
1185  print '<td>';
1186  print $soc->getNomUrl(1);
1187  print '<input type="hidden" name="socid" value="'.$soc->id.'">';
1188  print '</td>';
1189  } else {
1190  print '<td>';
1191  print img_picto('', 'company', 'class="pictofixedwidth"');
1192  print $form->select_company('', 'socid', '', 'SelectThirdParty', 1, 0, null, 0, 'minwidth300 widthcentpercentminusxx maxwidth500');
1193  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>';
1194  print '</td>';
1195  }
1196  print '</tr>'."\n";
1197 
1198  if ($socid > 0) {
1199  // Ligne info remises tiers
1200  print '<tr><td>'.$langs->trans('Discounts').'</td><td>';
1201  if ($soc->remise_percent) {
1202  print $langs->trans("CompanyHasRelativeDiscount", $soc->remise_percent).' ';
1203  } else {
1204  print '<span class="hideonsmartphone">'.$langs->trans("CompanyHasNoRelativeDiscount").'. </span>';
1205  }
1206  $absolute_discount = $soc->getAvailableDiscounts();
1207  if ($absolute_discount) {
1208  print $langs->trans("CompanyHasAbsoluteDiscount", price($absolute_discount), $langs->trans("Currency".$conf->currency)).'.';
1209  } else {
1210  print '<span class="hideonsmartphone">'.$langs->trans("CompanyHasNoAbsoluteDiscount").'.</span>';
1211  }
1212  print '</td></tr>';
1213  }
1214 
1215  // Commercial suivi
1216  print '<tr><td class="nowrap"><span class="fieldrequired">'.$langs->trans("TypeContact_contrat_internal_SALESREPFOLL").'</span></td><td>';
1217  print img_picto('', 'user', 'class="pictofixedwidth"');
1218  print $form->select_dolusers(GETPOST("commercial_suivi_id") ?GETPOST("commercial_suivi_id") : $user->id, 'commercial_suivi_id', 1, '');
1219  print '</td></tr>';
1220 
1221  // Commercial signature
1222  print '<tr><td class="nowrap"><span class="fieldrequired">'.$langs->trans("TypeContact_contrat_internal_SALESREPSIGN").'</span></td><td>';
1223  print img_picto('', 'user', 'class="pictofixedwidth"');
1224  print $form->select_dolusers(GETPOST("commercial_signature_id") ?GETPOST("commercial_signature_id") : $user->id, 'commercial_signature_id', 1, '');
1225  print '</td></tr>';
1226 
1227  print '<tr><td><span class="fieldrequired">'.$langs->trans("Date").'</span></td><td>';
1228  print img_picto('', 'action', 'class="pictofixedwidth"');
1229  print $form->selectDate($datecontrat, '', 0, 0, '', "contrat");
1230  print "</td></tr>";
1231 
1232  // Project
1233  if (isModEnabled('project')) {
1234  $langs->load('projects');
1235 
1236  $formproject = new FormProjets($db);
1237 
1238  print '<tr><td>'.$langs->trans("Project").'</td><td>';
1239  print img_picto('', 'project', 'class="pictofixedwidth"');
1240  $formproject->select_projects(($soc->id > 0 ? $soc->id : -1), $projectid, "projectid", 0, 0, 1, 1);
1241  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>';
1242  print "</td></tr>";
1243  }
1244 
1245  print '<tr><td>'.$langs->trans("NotePublic").'</td><td class="tdtop">';
1246  $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%');
1247  print $doleditor->Create(1);
1248  print '</td></tr>';
1249 
1250  if (empty($user->socid)) {
1251  print '<tr><td>'.$langs->trans("NotePrivate").'</td><td class="tdtop">';
1252  $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%');
1253  print $doleditor->Create(1);
1254  print '</td></tr>';
1255  }
1256 
1257  // Other attributes
1258  $parameters = array('objectsrc' => $objectsrc, 'colspan' => ' colspan="3"', 'cols' => '3');
1259  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1260  print $hookmanager->resPrint;
1261 
1262  // Other attributes
1263  if (empty($reshook)) {
1264  print $object->showOptionals($extrafields, 'create', $parameters);
1265  }
1266 
1267  print "</table>\n";
1268 
1269  print dol_get_fiche_end();
1270 
1271  print $form->buttonsSaveCancel("Create");
1272 
1273  if (is_object($objectsrc)) {
1274  print '<input type="hidden" name="origin" value="'.$objectsrc->element.'">';
1275  print '<input type="hidden" name="originid" value="'.$objectsrc->id.'">';
1276 
1277  if (empty($conf->global->CONTRACT_SUPPORT_PRODUCTS)) {
1278  print '<br>'.$langs->trans("Note").': '.$langs->trans("OnlyLinesWithTypeServiceAreUsed");
1279  }
1280  }
1281 
1282  print "</form>\n";
1283 } else {
1284  // View and edit mode
1285  $now = dol_now();
1286 
1287  if ($object->id > 0) {
1288  $object->fetch_thirdparty();
1289 
1290  $soc = $object->thirdparty; // $soc is used later
1291 
1292  $result = $object->fetch_lines(); // This also init $this->nbofserviceswait, $this->nbofservicesopened, $this->nbofservicesexpired=, $this->nbofservicesclosed
1293  if ($result < 0) {
1294  dol_print_error($db, $object->error);
1295  }
1296 
1297  $nbofservices = count($object->lines);
1298 
1299  $author = new User($db);
1300  $author->fetch($object->user_author_id);
1301 
1302  $commercial_signature = new User($db);
1303  $commercial_signature->fetch($object->commercial_signature_id);
1304 
1305  $commercial_suivi = new User($db);
1306  $commercial_suivi->fetch($object->commercial_suivi_id);
1307 
1308  $head = contract_prepare_head($object);
1309 
1310  $hselected = 0;
1311  $formconfirm = '';
1312 
1313  print dol_get_fiche_head($head, $hselected, $langs->trans("Contract"), -1, 'contract');
1314 
1315 
1316  if ($action == 'delete') {
1317  //Confirmation de la suppression du contrat
1318  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("DeleteAContract"), $langs->trans("ConfirmDeleteAContract"), "confirm_delete", '', 0, 1);
1319  } elseif ($action == 'valid') {
1320  //Confirmation de la validation
1321  $ref = substr($object->ref, 1, 4);
1322  if ($ref == 'PROV' && !empty($modCodeContract->code_auto)) {
1323  $numref = $object->getNextNumRef($object->thirdparty);
1324  } else {
1325  $numref = $object->ref;
1326  }
1327  $text = $langs->trans('ConfirmValidateContract', $numref);
1328  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("ValidateAContract"), $text, "confirm_valid", '', 0, 1);
1329  } elseif ($action == 'close') {
1330  // Confirmation de la fermeture
1331  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("CloseAContract"), $langs->trans("ConfirmCloseContract"), "confirm_close", '', 0, 1);
1332  } elseif ($action == 'activate') {
1333  $formquestion = array(
1334  array('type' => 'date', 'name' => 'd_start', 'label' => $langs->trans("DateServiceActivate"), 'value' => dol_now()),
1335  array('type' => 'date', 'name' => 'd_end', 'label' => $langs->trans("DateEndPlanned"), /*'value' => $form->selectDate('', "end", $usehm, $usehm, '', "active", 1, 0),*/ '', ''),
1336  array('type' => 'text', 'name' => 'comment', 'label' => $langs->trans("Comment"), 'value' => '', '', '', 'class' => 'minwidth300', 'moreattr'=>'autofocus')
1337  );
1338  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("ActivateAllOnContract"), $langs->trans("ConfirmActivateAllOnContract"), "confirm_activate", $formquestion, 'yes', 1, 280);
1339  } elseif ($action == 'clone') {
1340  $filter = '(s.client:IN:1,2,3)';
1341  // Clone confirmation
1342  $formquestion = array(array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter)));
1343  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneContract', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
1344  }
1345 
1346 
1347  // Call Hook formConfirm
1348  $parameters = array(
1349  'formConfirm' => $formconfirm,
1350  'id' => $id,
1351  //'lineid' => $lineid,
1352  );
1353  // Note that $action and $object may have been modified by hook
1354  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action);
1355  if (empty($reshook)) {
1356  $formconfirm .= $hookmanager->resPrint;
1357  } elseif ($reshook > 0) {
1358  $formconfirm = $hookmanager->resPrint;
1359  }
1360 
1361  // Print form confirm
1362  print $formconfirm;
1363 
1364 
1365  // Contract
1366  if (!empty($object->brouillon) && $user->hasRight('contrat', 'creer')) {
1367  print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'" method="POST">';
1368  print '<input type="hidden" name="token" value="'.newToken().'">';
1369  print '<input type="hidden" name="action" value="setremise">';
1370  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1371  }
1372 
1373  // Contract card
1374 
1375  $linkback = '<a href="'.DOL_URL_ROOT.'/contrat/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
1376 
1377 
1378  $morehtmlref = '';
1379  if (!empty($modCodeContract->code_auto)) {
1380  $morehtmlref .= $object->ref;
1381  } else {
1382  $morehtmlref .= $form->editfieldkey("", 'ref', $object->ref, $object, $user->rights->contrat->creer, 'string', '', 0, 3);
1383  $morehtmlref .= $form->editfieldval("", 'ref', $object->ref, $object, $user->rights->contrat->creer, 'string', '', 0, 2);
1384  }
1385 
1386  $morehtmlref .= '<div class="refidno">';
1387  // Ref customer
1388  $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->rights->contrat->creer, 'string', '', 0, 1);
1389  $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');
1390  // Ref supplier
1391  $morehtmlref .= '<br>';
1392  $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->rights->contrat->creer, 'string', '', 0, 1);
1393  $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->rights->contrat->creer, 'string', '', null, null, '', 1, 'getFormatedSupplierRef');
1394  // Thirdparty
1395  $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1);
1396  if (empty($conf->global->MAIN_DISABLE_OTHER_LINK) && $object->thirdparty->id > 0) {
1397  $morehtmlref .= ' (<a href="'.DOL_URL_ROOT.'/contrat/list.php?socid='.$object->thirdparty->id.'&search_name='.urlencode($object->thirdparty->name).'">'.$langs->trans("OtherContracts").'</a>)';
1398  }
1399  // Project
1400  if (isModEnabled('project')) {
1401  $langs->load("projects");
1402  $morehtmlref .= '<br>';
1403  if ($permissiontoadd) {
1404  $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
1405  if ($action != 'classify') {
1406  $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
1407  }
1408  $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
1409  } else {
1410  if (!empty($object->fk_project)) {
1411  $proj = new Project($db);
1412  $proj->fetch($object->fk_project);
1413  $morehtmlref .= $proj->getNomUrl(1);
1414  if ($proj->title) {
1415  $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
1416  }
1417  }
1418  }
1419  }
1420  $morehtmlref .= '</div>';
1421 
1422 
1423  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'none', $morehtmlref);
1424 
1425 
1426  print '<div class="fichecenter">';
1427  print '<div class="underbanner clearboth"></div>';
1428 
1429 
1430  print '<table class="border tableforfield" width="100%">';
1431 
1432  // Line info of thirdparty discounts
1433  print '<tr><td class="titlefield">'.$langs->trans('Discount').'</td><td colspan="3">';
1434  if ($object->thirdparty->remise_percent) {
1435  print $langs->trans("CompanyHasRelativeDiscount", $object->thirdparty->remise_percent).'. ';
1436  } else {
1437  print '<span class="hideonsmartphone">'.$langs->trans("CompanyHasNoRelativeDiscount").'. </span>';
1438  }
1439  $absolute_discount = $object->thirdparty->getAvailableDiscounts();
1440  if ($absolute_discount) {
1441  print $langs->trans("CompanyHasAbsoluteDiscount", price($absolute_discount), $langs->trans("Currency".$conf->currency)).'.';
1442  } else {
1443  print '<span class="hideonsmartphone">'.$langs->trans("CompanyHasNoAbsoluteDiscount").'.</span>';
1444  }
1445  print '</td></tr>';
1446 
1447  // Date
1448  print '<tr>';
1449  print '<td class="titlefield">';
1450  print $form->editfieldkey("Date", 'date_contrat', $object->date_contrat, $object, $user->rights->contrat->creer);
1451  print '</td><td>';
1452  print $form->editfieldval("Date", 'date_contrat', $object->date_contrat, $object, $user->rights->contrat->creer, 'datehourpicker');
1453  print '</td>';
1454  print '</tr>';
1455 
1456  // Other attributes
1457  $cols = 3;
1458  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1459 
1460  print "</table>";
1461 
1462  print '</div>';
1463 
1464  if (!empty($object->brouillon) && $user->hasRight('contrat', 'creer')) {
1465  print '</form>';
1466  }
1467 
1468  echo '<br>';
1469 
1470  if (!empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) {
1471  $blocname = 'contacts';
1472  $title = $langs->trans('ContactsAddresses');
1473  include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
1474  }
1475 
1476  if (!empty($conf->global->MAIN_DISABLE_NOTES_TAB)) {
1477  $blocname = 'notes';
1478  $title = $langs->trans('Notes');
1479  include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
1480  }
1481 
1482 
1483  $arrayothercontracts = $object->getListOfContracts('others'); // array or -1 if technical error
1484 
1485  /*
1486  * Lines of contracts
1487  */
1488 
1489  // Add products/services form
1490  //$forceall = 1;
1491  global $inputalsopricewithtax;
1492  $inputalsopricewithtax = 1;
1493 
1494  $productstatic = new Product($db);
1495 
1496  $usemargins = 0;
1497  if (isModEnabled('margin') && !empty($object->element) && in_array($object->element, array('facture', 'propal', 'commande'))) {
1498  $usemargins = 1;
1499  }
1500 
1501  // Title line for service
1502  $cursorline = 1;
1503 
1504 
1505  print '<div id="contrat-lines-container" id="contractlines" data-contractid="'.$object->id.'" data-element="'.$object->element.'" >';
1506  while ($cursorline <= $nbofservices) {
1507  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.'" >';
1508  print '<form name="update" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'" method="post">';
1509  print '<input type="hidden" name="token" value="'.newToken().'">';
1510  print '<input type="hidden" name="action" value="updateline">';
1511  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1512  print '<input type="hidden" name="elrowid" value="'.$object->lines[$cursorline - 1]->id.'">';
1513  print '<input type="hidden" name="fournprice" value="'.(!empty($object->lines[$cursorline - 1]->fk_fournprice) ? $object->lines[$cursorline - 1]->fk_fournprice : 0).'">';
1514 
1515  // Area with common detail of line
1516  print '<div class="div-table-responsive-no-min">';
1517  print '<table class="notopnoleftnoright allwidth tableforservicepart1 centpercent">';
1518 
1519  $sql = "SELECT cd.rowid, cd.statut, cd.label as label_det, cd.fk_product, cd.product_type, cd.description, cd.price_ht, cd.qty,";
1520  $sql .= " cd.tva_tx, cd.vat_src_code, cd.remise_percent, cd.info_bits, cd.subprice, cd.multicurrency_subprice,";
1521  $sql .= " cd.date_ouverture_prevue as date_start, cd.date_ouverture as date_start_real,";
1522  $sql .= " cd.date_fin_validite as date_end, cd.date_cloture as date_end_real,";
1523  $sql .= " cd.commentaire as comment, cd.fk_product_fournisseur_price as fk_fournprice, cd.buy_price_ht as pa_ht,";
1524  $sql .= " cd.fk_unit,";
1525  $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";
1526  $sql .= " ,cd.rang";
1527  $sql .= " FROM ".MAIN_DB_PREFIX."contratdet as cd";
1528  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid";
1529  $sql .= " WHERE cd.rowid = ".((int) $object->lines[$cursorline - 1]->id);
1530 
1531  $result = $db->query($sql);
1532  if ($result) {
1533  $total = 0;
1534 
1535  $objp = $db->fetch_object($result);
1536 
1537  // Line title
1538  print '<tr class="liste_titre'.($cursorline ? ' liste_titre_add' : '').'">';
1539  print '<td>'.$langs->trans("ServiceNb", $cursorline).'</td>';
1540  print '<td width="80" class="center">'.$langs->trans("VAT").'</td>';
1541  print '<td width="80" class="right">'.$langs->trans("PriceUHT").'</td>';
1542  //if (isModEnabled("multicurrency")) {
1543  // print '<td width="80" class="right">'.$langs->trans("PriceUHTCurrency").'</td>';
1544  //}
1545  print '<td width="30" class="center">'.$langs->trans("Qty").'</td>';
1546  if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1547  print '<td width="30" class="left">'.$langs->trans("Unit").'</td>';
1548  }
1549  print '<td width="50" class="right">'.$langs->trans("ReductionShort").'</td>';
1550  if (isModEnabled('margin') && !empty($conf->global->MARGIN_SHOW_ON_CONTRACT)) {
1551  print '<td width="50" class="right">'.$langs->trans("BuyingPrice").'</td>';
1552  }
1553  //
1554 
1555  if ($nbofservices > 1 && $conf->browser->layout != 'phone' && !empty($user->rights->contrat->creer)) {
1556  print '<td width="30" class="linecolmove tdlineupdown center">';
1557  if ($cursorline > 1) {
1558  print '<a class="lineupdown reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=up&token='.newToken().'&rowid='.$objp->rowid.'">';
1559  echo img_up('default', 0, 'imgupforline');
1560  print '</a>';
1561  }
1562  if ($cursorline < $nbofservices) {
1563  print '<a class="lineupdown reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=down&token='.newToken().'&rowid='.$objp->rowid.'">';
1564  echo img_down('default', 0, 'imgdownforline');
1565  print '</a>';
1566  }
1567  print '</td>';
1568  } else {
1569  print '<td width="30">&nbsp;</td>';
1570  }
1571 
1572  print "</tr>\n";
1573 
1574 
1575 
1576  // Line in view mode
1577  if ($action != 'editline' || GETPOST('rowid') != $objp->rowid) {
1578  $moreparam = '';
1579  if (!empty($conf->global->CONTRACT_HIDE_CLOSED_SERVICES_BY_DEFAULT) && $objp->statut == ContratLigne::STATUS_CLOSED && $action != 'showclosedlines') {
1580  $moreparam = 'style="display: none;"';
1581  }
1582 
1583  print '<tr class="tdtop oddeven" '.$moreparam.'>';
1584 
1585  // Label
1586  if ($objp->fk_product > 0) {
1587  $productstatic->id = $objp->fk_product;
1588  $productstatic->type = $objp->ptype;
1589  $productstatic->ref = $objp->pref;
1590  $productstatic->entity = $objp->pentity;
1591  $productstatic->label = $objp->plabel;
1592  $productstatic->status = $objp->tosell;
1593  $productstatic->status_buy = $objp->tobuy;
1594  $productstatic->status_batch = $objp->tobatch;
1595 
1596  print '<td>';
1597  $text = $productstatic->getNomUrl(1, '', 32);
1598  if ($objp->plabel) {
1599  $text .= ' - ';
1600  $text .= $objp->plabel;
1601  }
1602  $description = $objp->description;
1603 
1604  // Add description in form
1605  if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
1606  $text .= (!empty($objp->description) && $objp->description != $objp->plabel) ? '<br>'.dol_htmlentitiesbr($objp->description) : '';
1607  $description = ''; // Already added into main visible desc
1608  }
1609 
1610  print $form->textwithtooltip($text, $description, 3, '', '', $cursorline, 3, (!empty($line->fk_parent_line) ?img_picto('', 'rightarrow') : ''));
1611 
1612  print '</td>';
1613  } else {
1614  print '<td>'.img_object($langs->trans("ShowProductOrService"), ($objp->product_type ? 'service' : 'product')).' '.dol_htmlentitiesbr($objp->description)."</td>\n";
1615  }
1616  // VAT
1617  print '<td class="center">';
1618  print vatrate($objp->tva_tx.($objp->vat_src_code ? (' ('.$objp->vat_src_code.')') : ''), '%', $objp->info_bits);
1619  print '</td>';
1620  // Price
1621  print '<td class="right">'.($objp->subprice != '' ? price($objp->subprice) : '')."</td>\n";
1622  // Price multicurrency
1623  /*if (isModEnabled("multicurrency")) {
1624  print '<td class="linecoluht_currency nowrap right">'.price($objp->multicurrency_subprice).'</td>';
1625  }*/
1626  // Quantity
1627  print '<td class="center">'.$objp->qty.'</td>';
1628  // Unit
1629  if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1630  print '<td class="left">'.$langs->trans($object->lines[$cursorline - 1]->getLabelOfUnit()).'</td>';
1631  }
1632  // Discount
1633  if ($objp->remise_percent > 0) {
1634  print '<td class="right">'.$objp->remise_percent."%</td>\n";
1635  } else {
1636  print '<td>&nbsp;</td>';
1637  }
1638 
1639  // Margin
1640  if (isModEnabled('margin') && !empty($conf->global->MARGIN_SHOW_ON_CONTRACT)) {
1641  print '<td class="right nowraponall">'.price($objp->pa_ht).'</td>';
1642  }
1643 
1644  // Icon move, update et delete (status contract 0=draft,1=validated,2=closed)
1645  print '<td class="nowraponall right">';
1646  if ($user->rights->contrat->creer && is_array($arrayothercontracts) && count($arrayothercontracts) && ($object->statut >= 0)) {
1647  print '<!-- link to move service line into another contract -->';
1648  print '<a class="reposition marginrightonly" style="padding-left: 5px;" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=move&token='.newToken().'&rowid='.$objp->rowid.'">';
1649  print img_picto($langs->trans("MoveToAnotherContract"), 'uparrow');
1650  print '</a>';
1651  }
1652  if ($user->rights->contrat->creer && ($object->statut >= 0)) {
1653  print '<a class="reposition marginrightonly editfielda" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=editline&token='.newToken().'&rowid='.$objp->rowid.'">';
1654  print img_edit();
1655  print '</a>';
1656  }
1657  if ($user->rights->contrat->creer && ($object->statut >= 0)) {
1658  print '<a class="reposition marginrightonly" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=deleteline&token='.newToken().'&rowid='.$objp->rowid.'">';
1659  print img_delete();
1660  print '</a>';
1661  }
1662  print '</td>';
1663 
1664  print "</tr>\n";
1665 
1666  $colspan = 6;
1667  if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1668  $colspan++;
1669  }
1670  if (isModEnabled('margin') && !empty($conf->global->MARGIN_SHOW_ON_CONTRACT)) {
1671  $colspan++;
1672  }
1673 
1674  // Dates of service planed and real
1675  if ($objp->subprice >= 0) {
1676  print '<tr class="oddeven" '.$moreparam.'>';
1677  print '<td colspan="'.$colspan.'">';
1678 
1679  // Date planned
1680  print $langs->trans("DateStartPlanned").': ';
1681  if ($objp->date_start) {
1682  print dol_print_date($db->jdate($objp->date_start), 'day');
1683  // Warning si date prevu passee et pas en service
1684  if ($objp->statut == 0 && $db->jdate($objp->date_start) < ($now - $conf->contrat->services->inactifs->warning_delay)) {
1685  $warning_delay = $conf->contrat->services->inactifs->warning_delay / 3600 / 24;
1686  $textlate = $langs->trans("Late").' = '.$langs->trans("DateReference").' > '.$langs->trans("DateToday").' '.(ceil($warning_delay) >= 0 ? '+' : '').ceil($warning_delay).' '.$langs->trans("days");
1687  print " ".img_warning($textlate);
1688  }
1689  } else {
1690  print $langs->trans("Unknown");
1691  }
1692  print ' &nbsp;-&nbsp; ';
1693  print $langs->trans("DateEndPlanned").': ';
1694  if ($objp->date_end) {
1695  print dol_print_date($db->jdate($objp->date_end), 'day');
1696  if ($objp->statut == 4 && $db->jdate($objp->date_end) < ($now - $conf->contrat->services->expires->warning_delay)) {
1697  $warning_delay = $conf->contrat->services->expires->warning_delay / 3600 / 24;
1698  $textlate = $langs->trans("Late").' = '.$langs->trans("DateReference").' > '.$langs->trans("DateToday").' '.(ceil($warning_delay) >= 0 ? '+' : '').ceil($warning_delay).' '.$langs->trans("days");
1699  print " ".img_warning($textlate);
1700  }
1701  } else {
1702  print $langs->trans("Unknown");
1703  }
1704 
1705  print '</td>';
1706  print '</tr>';
1707  }
1708 
1709  // Display lines extrafields
1710  if (is_array($extralabelslines) && count($extralabelslines) > 0) {
1711  $line = new ContratLigne($db);
1712  $line->id = $objp->rowid;
1713  $line->fetch_optionals();
1714  print $line->showOptionals($extrafields, 'view', array('class'=>'oddeven', 'style'=>$moreparam, 'colspan'=>$colspan), '', '', 1);
1715  }
1716  } else {
1717  // Line in mode update
1718  // Ligne carac
1719  print '<tr class="oddeven">';
1720  print '<td>';
1721  if ($objp->fk_product > 0) {
1722  $canchangeproduct = 1;
1723  if (empty($canchangeproduct)) {
1724  $productstatic->id = $objp->fk_product;
1725  $productstatic->type = $objp->ptype;
1726  $productstatic->ref = $objp->pref;
1727  $productstatic->entity = $objp->pentity;
1728  print $productstatic->getNomUrl(1, '', 32);
1729  print $objp->label ? ' - '.dol_trunc($objp->label, 32) : '';
1730  print '<input type="hidden" name="idprod" value="'.(!empty($object->lines[$cursorline - 1]->fk_product) ? $object->lines[$cursorline - 1]->fk_product : 0).'">';
1731  } else {
1732  $senderissupplier = 0;
1733  if (empty($senderissupplier)) {
1734  print $form->select_produits((!empty($object->lines[$cursorline - 1]->fk_product) ? $object->lines[$cursorline - 1]->fk_product : 0), 'idprod');
1735  } else {
1736  $form->select_produits_fournisseurs((!empty($object->lines[$cursorline - 1]->fk_product) ? $object->lines[$cursorline - 1]->fk_product : 0), 'idprod');
1737  }
1738  }
1739  print '<br>';
1740  } else {
1741  print $objp->label ? $objp->label.'<br>' : '';
1742  print '<input type="hidden" name="idprod" value="'.(!empty($object->lines[$cursorline - 1]->fk_product) ? $object->lines[$cursorline - 1]->fk_product : 0).'">';
1743  }
1744 
1745  // editeur wysiwyg
1746  require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1747  $nbrows = ROWS_2;
1748  if (!empty($conf->global->MAIN_INPUT_DESC_HEIGHT)) {
1749  $nbrows = $conf->global->MAIN_INPUT_DESC_HEIGHT;
1750  }
1751  $enable = (isset($conf->global->FCKEDITOR_ENABLE_DETAILS) ? $conf->global->FCKEDITOR_ENABLE_DETAILS : 0);
1752  $doleditor = new DolEditor('product_desc', $objp->description, '', 92, 'dolibarr_details', '', false, true, $enable, $nbrows, '90%');
1753  $doleditor->Create();
1754 
1755  print '</td>';
1756 
1757  // VAT
1758  print '<td class="right">';
1759  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);
1760  print '</td>';
1761 
1762  // Price
1763  print '<td class="right"><input size="5" type="text" name="elprice" value="'.price($objp->subprice).'"></td>';
1764 
1765  // Price multicurrency
1766  /*if (isModEnabled("multicurrency")) {
1767  print '<td class="linecoluht_currency nowrap right">'.price($objp->multicurrency_subprice).'</td>';
1768  }*/
1769 
1770  // Quantity
1771  print '<td class="center"><input size="2" type="text" name="elqty" value="'.$objp->qty.'"></td>';
1772 
1773  // Unit
1774  if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1775  print '<td class="left">';
1776  print $form->selectUnits($objp->fk_unit, "unit");
1777  print '</td>';
1778  }
1779 
1780  // Discount
1781  print '<td class="nowrap right"><input size="1" type="text" name="elremise_percent" value="'.$objp->remise_percent.'">%</td>';
1782 
1783  if (!empty($usemargins)) {
1784  print '<td class="right">';
1785  if ($objp->fk_product) {
1786  print '<select id="fournprice" name="fournprice"></select>';
1787  }
1788  print '<input id="buying_price" type="text" size="5" name="buying_price" value="'.price($objp->pa_ht, 0, '', 0).'"></td>';
1789  }
1790  print '<td class="center">';
1791  print '<input type="submit" class="button margintoponly marginbottomonly" name="save" value="'.$langs->trans("Modify").'">';
1792  print '<br><input type="submit" class="button margintoponly marginbottomonly button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
1793  print '</td>';
1794  print '</tr>';
1795 
1796  $colspan = 6;
1797  if (isModEnabled('margin') && !empty($conf->global->MARGIN_SHOW_ON_CONTRACT)) {
1798  $colspan++;
1799  }
1800  if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1801  $colspan++;
1802  }
1803 
1804  // Line dates planed
1805  print '<tr class="oddeven">';
1806  print '<td colspan="'.$colspan.'">';
1807  print $langs->trans("DateStartPlanned").' ';
1808  print $form->selectDate($db->jdate($objp->date_start), "date_start_update", $usehm, $usehm, ($db->jdate($objp->date_start) > 0 ? 0 : 1), "update");
1809  print ' &nbsp;&nbsp;'.$langs->trans("DateEndPlanned").' ';
1810  print $form->selectDate($db->jdate($objp->date_end), "date_end_update", $usehm, $usehm, ($db->jdate($objp->date_end) > 0 ? 0 : 1), "update");
1811  print '</td>';
1812  print '</tr>';
1813 
1814  if (is_array($extralabelslines) && count($extralabelslines) > 0) {
1815  $line = new ContratLigne($db);
1816  $line->id = $objp->rowid;
1817  $line->fetch_optionals();
1818  print $line->showOptionals($extrafields, 'edit', array('style'=>'class="oddeven"', 'colspan'=>$colspan), '', '', 1);
1819  }
1820  }
1821 
1822  $db->free($result);
1823  } else {
1824  dol_print_error($db);
1825  }
1826 
1827  if ($object->statut > 0) {
1828  $moreparam = '';
1829  if (!empty($conf->global->CONTRACT_HIDE_CLOSED_SERVICES_BY_DEFAULT) && $object->lines[$cursorline - 1]->statut == ContratLigne::STATUS_CLOSED && $action != 'showclosedlines') {
1830  $moreparam = 'style="display: none;"';
1831  }
1832 
1833  $colspan = 6;
1834  if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1835  $colspan++;
1836  }
1837  if (isModEnabled('margin') && !empty($conf->global->MARGIN_SHOW_ON_CONTRACT)) {
1838  $colspan++;
1839  }
1840 
1841  print '<tr class="oddeven" '.$moreparam.'>';
1842  print '<td class="tdhrthin" colspan="'.$colspan.'"><hr class="opacitymedium tdhrthin"></td>';
1843  print "</tr>\n";
1844  }
1845 
1846  print "</table>";
1847  print '</div>';
1848 
1849  print "</form>\n";
1850 
1851 
1852  /*
1853  * Confirmation to delete service line of contract
1854  */
1855  if ($action == 'deleteline' && !$_REQUEST["cancel"] && $user->hasRight('contrat', 'creer') && $object->lines[$cursorline - 1]->id == GETPOST('rowid')) {
1856  print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id."&lineid=".GETPOST('rowid'), $langs->trans("DeleteContractLine"), $langs->trans("ConfirmDeleteContractLine"), "confirm_deleteline", '', 0, 1);
1857  if ($ret == 'html') {
1858  print '<table class="notopnoleftnoright" width="100%"><tr class="oddeven" height="6"><td></td></tr></table>';
1859  }
1860  }
1861 
1862  /*
1863  * Confirmation to move service toward another contract
1864  */
1865  if ($action == 'move' && !$_REQUEST["cancel"] && $user->hasRight('contrat', 'creer') && $object->lines[$cursorline - 1]->id == GETPOST('rowid')) {
1866  $arraycontractid = array();
1867  foreach ($arrayothercontracts as $contractcursor) {
1868  $arraycontractid[$contractcursor->id] = $contractcursor->ref;
1869  }
1870  //var_dump($arraycontractid);
1871  // Cree un tableau formulaire
1872  $formquestion = array(
1873  'text' => $langs->trans("ConfirmMoveToAnotherContractQuestion"),
1874  array('type' => 'select', 'name' => 'newcid', 'values' => $arraycontractid));
1875 
1876  print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id."&lineid=".GETPOST('rowid', 'int'), $langs->trans("MoveToAnotherContract"), $langs->trans("ConfirmMoveToAnotherContract"), "confirm_move", $formquestion);
1877  print '<table class="notopnoleftnoright" width="100%"><tr class="oddeven" height="6"><td></td></tr></table>';
1878  }
1879 
1880  // Area with status and activation info of line
1881  if ($object->statut > 0) {
1882  print '<table class="notopnoleftnoright tableforservicepart2'.($cursorline < $nbofservices ? ' boxtablenobottom' : '').' centpercent">';
1883 
1884  print '<tr class="oddeven" '.$moreparam.'>';
1885  print '<td><span class="valignmiddle hideonsmartphone">'.$langs->trans("ServiceStatus").':</span> '.$object->lines[$cursorline - 1]->getLibStatut(4).'</td>';
1886  print '<td width="30" class="right">';
1887  if ($user->socid == 0) {
1888  if ($object->statut > 0 && $action != 'activateline' && $action != 'unactivateline') {
1889  $tmpaction = 'activateline';
1890  $tmpactionpicto = 'play';
1891  $tmpactiontext = $langs->trans("Activate");
1892  if ($objp->statut == 4) {
1893  $tmpaction = 'unactivateline';
1894  $tmpactionpicto = 'playstop';
1895  $tmpactiontext = $langs->trans("Disable");
1896  }
1897  if (($tmpaction == 'activateline' && $user->rights->contrat->activer) || ($tmpaction == 'unactivateline' && $user->rights->contrat->desactiver)) {
1898  print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;ligne='.$object->lines[$cursorline - 1]->id.'&amp;action='.$tmpaction.'">';
1899  print img_picto($tmpactiontext, $tmpactionpicto);
1900  print '</a>';
1901  }
1902  }
1903  }
1904  print '</td>';
1905  print "</tr>\n";
1906 
1907  print '<tr class="oddeven" '.$moreparam.'>';
1908 
1909  print '<td>';
1910  // Si pas encore active
1911  if (!$objp->date_start_real) {
1912  print $langs->trans("DateStartReal").': ';
1913  if ($objp->date_start_real) {
1914  print dol_print_date($db->jdate($objp->date_start_real), 'day');
1915  } else {
1916  print $langs->trans("ContractStatusNotRunning");
1917  }
1918  }
1919  // Si active et en cours
1920  if ($objp->date_start_real && !$objp->date_end_real) {
1921  print $langs->trans("DateStartReal").': ';
1922  print dol_print_date($db->jdate($objp->date_start_real), 'day');
1923  }
1924  // Si desactive
1925  if ($objp->date_start_real && $objp->date_end_real) {
1926  print $langs->trans("DateStartReal").': ';
1927  print dol_print_date($db->jdate($objp->date_start_real), 'day');
1928  print ' &nbsp;-&nbsp; ';
1929  print $langs->trans("DateEndReal").': ';
1930  print dol_print_date($db->jdate($objp->date_end_real), 'day');
1931  }
1932  if (!empty($objp->comment)) {
1933  print " &nbsp;-&nbsp; ".$objp->comment;
1934  }
1935  print '</td>';
1936 
1937  print '<td class="center">&nbsp;</td>';
1938 
1939  print '</tr>';
1940  print '</table>';
1941  }
1942 
1943  // Form to activate line
1944  if ($user->rights->contrat->activer && $action == 'activateline' && $object->lines[$cursorline - 1]->id == GETPOST('ligne', 'int')) {
1945  print '<form name="active" action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1946  print '<input type="hidden" name="token" value="'.newToken().'">';
1947  print '<input type="hidden" name="action" value="confirm_active">';
1948  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1949  print '<input type="hidden" name="id" value="'.$object->id.'">';
1950  print '<input type="hidden" name="ligne" value="'.GETPOST('ligne', 'int').'">';
1951  print '<input type="hidden" name="confirm" value="yes">';
1952 
1953  print '<table class="noborder tableforservicepart2'.($cursorline < $nbofservices ? ' boxtablenobottom' : '').' centpercent">';
1954 
1955  // Definie date debut et fin par defaut
1956  $dateactstart = $objp->date_start;
1957  if (GETPOST('remonth')) {
1958  $dateactstart = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear'));
1959  } elseif (!$dateactstart) {
1960  $dateactstart = time();
1961  }
1962 
1963  $dateactend = $objp->date_end;
1964  if (GETPOST('endmonth')) {
1965  $dateactend = dol_mktime(12, 0, 0, GETPOST('endmonth'), GETPOST('endday'), GETPOST('endyear'));
1966  } elseif (!$dateactend) {
1967  if ($objp->fk_product > 0) {
1968  $product = new Product($db);
1969  $product->fetch($objp->fk_product);
1970  $dateactend = dol_time_plus_duree(time(), $product->duration_value, $product->duration_unit);
1971  }
1972  }
1973 
1974  print '<tr class="oddeven">';
1975  print '<td class="nohover">'.$langs->trans("DateServiceActivate").'</td><td class="nohover">';
1976  print $form->selectDate($dateactstart, 'start', $usehm, $usehm, '', "active", 1, 0);
1977  print '</td>';
1978  print '<td class="nohover">'.$langs->trans("DateEndPlanned").'</td><td class="nohover">';
1979  print $form->selectDate($dateactend, "end", $usehm, $usehm, '', "active", 1, 0);
1980  print '</td>';
1981  print '<td class="center nohover">';
1982  print '</td>';
1983 
1984  print '</tr>';
1985 
1986  print '<tr class="oddeven">';
1987  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>';
1988  print '<td class="nohover right">';
1989  print '<input type="submit" class="button" name="activate" value="'.$langs->trans("Activate").'"> &nbsp; ';
1990  print '<input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
1991  print '</td>';
1992  print '</tr>';
1993 
1994  print '</table>';
1995 
1996  print '</form>';
1997  }
1998 
1999  if ($user->rights->contrat->activer && $action == 'unactivateline' && $object->lines[$cursorline - 1]->id == GETPOST('ligne', 'int')) {
2003  print '<!-- Form to disabled a line -->'."\n";
2004  print '<form name="confirm_closeline" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;ligne='.$object->lines[$cursorline - 1]->id.'" method="post">';
2005  print '<input type="hidden" name="token" value="'.newToken().'">';
2006  print '<input type="hidden" name="confirm" value="yes">';
2007  print '<input type="hidden" name="action" value="confirm_closeline">';
2008  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
2009 
2010  print '<table class="noborder tableforservicepart2'.($cursorline < $nbofservices ? ' boxtablenobottom' : '').' centpercent">';
2011 
2012  // Definie date debut et fin par defaut
2013  $dateactstart = $objp->date_start_real;
2014  if (GETPOST('remonth')) {
2015  $dateactstart = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear'));
2016  } elseif (!$dateactstart) {
2017  $dateactstart = time();
2018  }
2019 
2020  $dateactend = $objp->date_end_real;
2021  if (GETPOST('endmonth')) {
2022  $dateactend = dol_mktime(12, 0, 0, GETPOST('endmonth'), GETPOST('endday'), GETPOST('endyear'));
2023  } elseif (!$dateactend) {
2024  if ($objp->fk_product > 0) {
2025  $product = new Product($db);
2026  $product->fetch($objp->fk_product);
2027  $dateactend = dol_time_plus_duree(time(), $product->duration_value, $product->duration_unit);
2028  }
2029  }
2030  $now = dol_now();
2031  if ($dateactend > $now) {
2032  $dateactend = $now;
2033  }
2034 
2035  print '<tr class="oddeven"><td colspan="2" class="nohover">';
2036  if ($objp->statut >= 4) {
2037  if ($objp->statut == 4) {
2038  print $langs->trans("DateEndReal").' ';
2039  print $form->selectDate($dateactend, "end", $usehm, $usehm, ($objp->date_end_real > 0 ? 0 : 1), "closeline", 1, 1);
2040  }
2041  }
2042  print '</td>';
2043  print '<td class="center nohover">';
2044  print '</td></tr>';
2045 
2046  print '<tr class="oddeven">';
2047  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>';
2048  print '<td class="nohover right">';
2049  print '<input type="submit" class="button" name="close" value="'.$langs->trans("Disable").'"> &nbsp; ';
2050  print '<input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
2051  print '</td>';
2052  print '</tr>';
2053 
2054  print '</table>';
2055 
2056  print '</form>';
2057  }
2058  print '</div>';
2059  $cursorline++;
2060  }
2061  print '</div>';
2062 
2063  // Form to add new line
2064  if ($user->rights->contrat->creer && ($object->statut == 0)) {
2065  $dateSelector = 1;
2066 
2067  print "\n";
2068  print ' <form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline') ? '' : '#line_'.GETPOST('lineid', 'int')).'" method="POST">
2069  <input type="hidden" name="token" value="'.newToken().'">
2070  <input type="hidden" name="action" value="'.(($action != 'editline') ? 'addline' : 'updateline').'">
2071  <input type="hidden" name="mode" value="">
2072  <input type="hidden" name="id" value="'.$object->id.'">
2073  <input type="hidden" name="page_y" value="">
2074  <input type="hidden" name="backtopage" value="'.$backtopage.'">
2075  ';
2076 
2077  print '<div class="div-table-responsive-no-min">';
2078  print '<table id="tablelines" class="noborder noshadow" width="100%">'; // Array with (n*2)+1 lines
2079 
2080  // Form to add new line
2081  if ($action != 'editline') {
2082  $forcetoshowtitlelines = 1;
2083  if (empty($object->multicurrency_code)) {
2084  $object->multicurrency_code = $conf->currency; // TODO Remove this when multicurrency supported on contracts
2085  }
2086 
2087  // Add free products/services
2088 
2089  $parameters = array();
2090  $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2091  if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2092  if (empty($reshook))
2093  $object->formAddObjectLine(1, $mysoc, $soc);
2094  }
2095 
2096  print '</table>';
2097  print '</div>';
2098  print '</form>';
2099  }
2100 
2101  print dol_get_fiche_end();
2102 
2103  // Select mail models is same action as presend
2104  if (GETPOST('modelselected')) {
2105  $action = 'presend';
2106  }
2107 
2108  /*
2109  * Buttons
2110  */
2111  if ($user->socid == 0 && $action != 'presend' && $action != 'editline') {
2112  print '<div class="tabsAction">';
2113 
2114  $parameters = array();
2115  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2116 
2117  if (empty($reshook)) {
2118  $params = array(
2119  'attr' => array(
2120  'title' => '',
2121  'class' => 'classfortooltip'
2122  )
2123  );
2124 
2125  // Send
2126  if (empty($user->socid)) {
2127  if ($object->statut == 1) {
2128  if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->contrat->creer)) {
2129  print dolGetButtonAction('', $langs->trans('SendMail'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&token='.newToken().'&mode=init#formmailbeforetitle', '', true, $params);
2130  } else {
2131  print dolGetButtonAction('', $langs->trans('SendMail'), 'default', '#', '', false, $params);
2132  }
2133  }
2134  }
2135 
2136  if ($object->statut == 0 && $nbofservices) {
2137  if ($user->rights->contrat->creer) {
2138  print dolGetButtonAction($langs->trans('Validate'), '', 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=valid&token='.newToken(), '', true, $params);
2139  } else {
2140  $params['attr']['title'] = $langs->trans("NotEnoughPermissions");
2141  print dolGetButtonAction($langs->trans('Validate'), '', 'default', '#', '', false, $params);
2142  }
2143  }
2144  if ($object->statut == 1) {
2145  if ($user->rights->contrat->creer) {
2146  print dolGetButtonAction($langs->trans('Modify'), '', 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken(), '', true, $params);
2147  } else {
2148  $params['attr']['title'] = $langs->trans("NotEnoughPermissions");
2149  print dolGetButtonAction($langs->trans('Modify'), '', 'default', '#', '', false, $params);
2150  }
2151  }
2152 
2153  if (isModEnabled('commande') && $object->statut > 0 && $object->nbofservicesclosed < $nbofservices) {
2154  $langs->load("orders");
2155  if ($user->hasRight('commande', 'creer')) {
2156  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);
2157  } else {
2158  $params['attr']['title'] = $langs->trans("NotEnoughPermissions");
2159  print dolGetButtonAction($langs->trans('CreateOrder'), '', 'default', '#', '', false, $params);
2160  }
2161  }
2162 
2163  if (isModEnabled('facture') && $object->statut > 0) {
2164  $langs->load("bills");
2165  if ($user->hasRight('facture', 'creer')) {
2166  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);
2167  } else {
2168  $params['attr']['title'] = $langs->trans("NotEnoughPermissions");
2169  print dolGetButtonAction($langs->trans('CreateBill'), '', 'default', '#', '', false, $params);
2170  }
2171  }
2172 
2173  if ($object->nbofservicesclosed > 0 || $object->nbofserviceswait > 0) {
2174  if ($user->rights->contrat->activer) {
2175  print dolGetButtonAction($langs->trans('ActivateAllContracts'), '', 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=activate&token='.newToken(), '', true, $params);
2176  } else {
2177  print dolGetButtonAction($langs->trans('ActivateAllContracts'), '', 'default', '#', '', false, $params);
2178  }
2179  }
2180  if ($object->nbofservicesclosed < $nbofservices) {
2181  if ($user->rights->contrat->desactiver) {
2182  print dolGetButtonAction($langs->trans('CloseAllContracts'), '', 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=close&token='.newToken(), '', true, $params);
2183  } else {
2184  print dolGetButtonAction($langs->trans('CloseAllContracts'), '', 'default', '#', '', false, $params);
2185  }
2186 
2187  //if (! $numactive)
2188  //{
2189  //}
2190  //else
2191  //{
2192  // print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("CloseRefusedBecauseOneServiceActive").'">'.$langs->trans("Close").'</a></div>';
2193  //}
2194  }
2195 
2196  if (!empty($conf->global->CONTRACT_HIDE_CLOSED_SERVICES_BY_DEFAULT) && $object->nbofservicesclosed > 0) {
2197  if ($action == 'showclosedlines') {
2198  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>';
2199  } else {
2200  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>';
2201  }
2202  }
2203 
2204  // Clone
2205  if ($user->rights->contrat->creer) {
2206  print dolGetButtonAction($langs->trans('ToClone'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&socid='.$object->socid.'&action=clone&token='.newToken(), '', true, $params);
2207  }
2208 
2209  // Delete
2210  print dolGetButtonAction($langs->trans('Delete'), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken(), '', $permissiontodelete, $params);
2211  }
2212 
2213  print "</div>";
2214  }
2215 
2216  if ($action != 'presend') {
2217  print '<div class="fichecenter"><div class="fichehalfleft">';
2218 
2219  /*
2220  * Generated documents
2221  */
2222  $filename = dol_sanitizeFileName($object->ref);
2223  $filedir = $conf->contrat->multidir_output[$object->entity]."/".dol_sanitizeFileName($object->ref);
2224  $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
2225  $genallowed = $user->hasRight('contrat', 'lire');
2226  $delallowed = $user->hasRight('contrat', 'creer');
2227 
2228 
2229  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);
2230 
2231 
2232  // Show links to link elements
2233  $linktoelem = $form->showLinkToObjectBlock($object, null, array('contrat'));
2234  $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
2235 
2236  // Show online signature link
2237  if ($object->statut != Contrat::STATUS_DRAFT && getDolGlobalString('CONTRACT_ALLOW_ONLINESIGN')) {
2238  print '<br><!-- Link to sign -->';
2239  require_once DOL_DOCUMENT_ROOT.'/core/lib/signature.lib.php';
2240 
2241  print showOnlineSignatureUrl('contract', $object->ref).'<br>';
2242  }
2243 
2244  print '</div><div class="fichehalfright">';
2245 
2246  $MAXEVENT = 10;
2247 
2248  $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/contrat/agenda.php?id='.$object->id);
2249 
2250 
2251  // List of actions on element
2252  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
2253  $formactions = new FormActions($db);
2254  $somethingshown = $formactions->showactions($object, 'contract', $socid, 1, 'listactions', $MAXEVENT, '', $morehtmlcenter);
2255 
2256  print '</div></div>';
2257  }
2258 
2259  // Presend form
2260  $modelmail = 'contract';
2261  $defaulttopic = 'SendContractRef';
2262  $diroutput = $conf->contrat->multidir_output[$object->entity];
2263  $trackid = 'con'.$object->id;
2264 
2265  include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
2266  }
2267 }
2268 
2269 
2270 llxFooter();
2271 
2272 $db->close();
2273 ?>
2274 
2275 <?php
2276 if (isModEnabled('margin') && $action == 'editline') {
2277  // TODO Why this ? To manage margin on contracts ?
2278  ?>
2279 <script type="text/javascript">
2280 $(document).ready(function() {
2281  var idprod = $("input[name='idprod']").val();
2282  var fournprice = $("input[name='fournprice']").val();
2283  var token = '<?php echo currentToken(); ?>'; // For AJAX Call we use old 'token' and not 'newtoken'
2284  if (idprod > 0) {
2285  $.post('<?php echo DOL_URL_ROOT; ?>/fourn/ajax/getSupplierPrices.php', {
2286  'idprod': idprod,
2287  'token': token
2288  }, function(data) {
2289  if (data.length > 0) {
2290  var options = '';
2291  var trouve=false;
2292  $(data).each(function() {
2293  options += '<option value="'+this.id+'" price="'+this.price+'"';
2294  if (fournprice > 0) {
2295  if (this.id == fournprice) {
2296  options += ' selected';
2297  $("#buying_price").val(this.price);
2298  trouve = true;
2299  }
2300  }
2301  options += '>'+this.label+'</option>';
2302  });
2303  options += '<option value=null'+(trouve?'':' selected')+'><?php echo $langs->trans("InputPrice"); ?></option>';
2304  $("#fournprice").html(options);
2305  if (trouve) {
2306  $("#buying_price").hide();
2307  $("#fournprice").show();
2308  }
2309  else {
2310  $("#buying_price").show();
2311  }
2312  $("#fournprice").change(function() {
2313  var selval = $(this).find('option:selected').attr("price");
2314  if (selval)
2315  $("#buying_price").val(selval).hide();
2316  else
2317  $('#buying_price').show();
2318  });
2319  }
2320  else {
2321  $("#fournprice").hide();
2322  $('#buying_price').show();
2323  }
2324  },
2325  'json');
2326  }
2327  else {
2328  $("#fournprice").hide();
2329  $('#buying_price').show();
2330  }
2331 });
2332 </script>
2333  <?php
2334 }
if(GETPOST('button_removefilter_x', 'alpha')||GETPOST('button_removefilter.x', 'alpha')||GETPOST('button_removefilter', 'alpha')) if(GETPOST('button_search_x', 'alpha')||GETPOST('button_search.x', 'alpha')||GETPOST('button_search', 'alpha')) if($action=="save" &&empty($cancel)) $help_url
View.
Definition: agenda.php:118
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.
Definition: user.class.php:48
$parameters
Actions.
Definition: card.php:83
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
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
dol_move_dir($srcdir, $destdir, $overwriteifexists=1, $indexdatabase=1, $renamedircontent=1)
Move a directory into another name.
Definition: files.lib.php:1105
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).
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
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)
newToken()
Return the value of token currently saved into session with name 'newtoken'.
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.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
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.
isModEnabled($module)
Is Dolibarr module enabled.
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...
$formconfirm
if ($action == 'delbookkeepingyear') {
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.