dolibarr  21.0.0-alpha
card.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2022 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
5  * Copyright (C) 2005 Marc Barilley / Ocebo <marc@ocebo.com>
6  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
7  * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
8  * Copyright (C) 2010-2023 Juanjo Menent <jmenent@2byte.es>
9  * Copyright (C) 2010-2022 Philippe Grand <philippe.grand@atoo-net.com>
10  * Copyright (C) 2012-2023 Christophe Battarel <christophe.battarel@altairis.fr>
11  * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
12  * Copyright (C) 2013-2014 Florian Henry <florian.henry@open-concept.pro>
13  * Copyright (C) 2014 Ferran Marcet <fmarcet@2byte.es>
14  * Copyright (C) 2016 Marcos García <marcosgdf@gmail.com>
15  * Copyright (C) 2018-2024 Frédéric France <frederic.france@netlogic.fr>
16  * Copyright (C) 2020 Nicolas ZABOURI <info@inovea-conseil.com>
17  * Copyright (C) 2022 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
18  * Copyright (C) 2023 Lenin Rivas <lenin.rivas777@gmail.com>
19  * Copyright (C) 2023 William Mead <william.mead@manchenumerique.fr>
20  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
21  *
22  * This program is free software; you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License as published by
24  * the Free Software Foundation; either version 3 of the License, or
25  * (at your option) any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License
33  * along with this program. If not, see <https://www.gnu.org/licenses/>.
34  */
35 
36 
43 // Load Dolibarr environment
44 require '../../main.inc.php';
45 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
46 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
47 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formpropal.class.php';
48 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmargin.class.php';
49 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
50 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
51 require_once DOL_DOCUMENT_ROOT.'/core/modules/propale/modules_propale.php';
52 require_once DOL_DOCUMENT_ROOT.'/core/lib/propal.lib.php';
53 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
54 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
55 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
56 if (isModEnabled('project')) {
57  require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
58  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
59 }
60 
61 if (isModEnabled('variants')) {
62  require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
63 }
64 
65 // Load translation files required by the page
66 $langs->loadLangs(array('companies', 'propal', 'compta', 'bills', 'orders', 'products', 'deliveries', 'sendings', 'other'));
67 if (isModEnabled('incoterm')) {
68  $langs->load('incoterm');
69 }
70 if (isModEnabled('margin')) {
71  $langs->load('margins');
72 }
73 
74 $error = 0;
75 
76 $id = GETPOSTINT('id');
77 $ref = GETPOST('ref', 'alpha');
78 $socid = GETPOSTINT('socid');
79 $action = GETPOST('action', 'aZ09');
80 $cancel = GETPOST('cancel', 'alpha');
81 $origin = GETPOST('origin', 'alpha');
82 $originid = GETPOSTINT('originid');
83 $confirm = GETPOST('confirm', 'alpha');
84 $backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
85 $lineid = GETPOSTINT('lineid');
86 $contactid = GETPOSTINT('contactid');
87 $projectid = GETPOSTINT('projectid');
88 $rank = (GETPOSTINT('rank') > 0) ? GETPOSTINT('rank') : -1;
89 
90 // PDF
91 $hidedetails = (GETPOSTINT('hidedetails') ? GETPOSTINT('hidedetails') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 1 : 0));
92 $hidedesc = (GETPOSTINT('hidedesc') ? GETPOSTINT('hidedesc') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 1 : 0));
93 $hideref = (GETPOSTINT('hideref') ? GETPOSTINT('hideref') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF') ? 1 : 0));
94 
95 $object = new Propal($db);
96 $extrafields = new ExtraFields($db);
97 
98 // fetch optionals attributes and labels
99 $extrafields->fetch_name_optionals_label($object->table_element);
100 
101 // Load object
102 if ($id > 0 || !empty($ref)) {
103  $ret = $object->fetch($id, $ref);
104  if ($ret > 0) {
105  $ret = $object->fetch_thirdparty();
106  if ($ret > 0 && isset($object->fk_project)) {
107  $ret = $object->fetch_project();
108  }
109  }
110  if ($ret <= 0) {
111  setEventMessages($object->error, $object->errors, 'errors');
112  $action = '';
113  }
114 }
115 
116 // Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
117 $hookmanager->initHooks(array('propalcard', 'globalcard'));
118 
119 $usercanread = $user->hasRight("propal", "lire");
120 $usercancreate = $user->hasRight("propal", "creer");
121 $usercandelete = $user->hasRight("propal", "supprimer");
122 
123 $usercanclose = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $usercancreate) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('propal', 'propal_advance', 'close')));
124 $usercanvalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $usercancreate) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('propal', 'propal_advance', 'validate')));
125 $usercansend = (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('propal', 'propal_advance', 'send')));
126 
127 $usermustrespectpricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !$user->hasRight('produit', 'ignore_price_min_advance')) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
128 $usercancreateorder = $user->hasRight('commande', 'creer');
129 $usercancreateinvoice = $user->hasRight('facture', 'creer');
130 $usercancreatecontract = $user->hasRight('contrat', 'creer');
131 $usercancreateintervention = $user->hasRight('ficheinter', 'creer');
132 $usercancreatepurchaseorder = ($user->hasRight('fournisseur', 'commande', 'creer') || $user->hasRight('supplier_order', 'creer'));
133 
134 $permissionnote = $usercancreate; // Used by the include of actions_setnotes.inc.php
135 $permissiondellink = $usercancreate; // Used by the include of actions_dellink.inc.php
136 $permissiontoedit = $usercancreate; // Used by the include of actions_lineupdown.inc.php
137 
138 // Security check
139 if (!empty($user->socid)) {
140  $socid = $user->socid;
141 }
142 restrictedArea($user, 'propal', $object->id);
143 
144 
145 /*
146  * Actions
147  */
148 
149 $parameters = array('socid' => $socid);
150 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
151 if ($reshook < 0) {
152  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
153 }
154 
155 if (empty($reshook)) {
156  $backurlforlist = DOL_URL_ROOT.'/comm/propal/list.php';
157 
158  if (empty($backtopage) || ($cancel && empty($id))) {
159  if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
160  if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
161  $backtopage = $backurlforlist;
162  } else {
163  $backtopage = DOL_URL_ROOT.'/comm/propal/card.php?id='.((!empty($id) && $id > 0) ? $id : '__ID__');
164  }
165  }
166  }
167 
168  if ($cancel) {
169  if (!empty($backtopageforcancel)) {
170  header("Location: ".$backtopageforcancel);
171  exit;
172  } elseif (!empty($backtopage)) {
173  header("Location: ".$backtopage);
174  exit;
175  }
176  $action = '';
177  }
178 
179  include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not includ_once
180 
181  include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
182 
183  include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; // Must be 'include', not 'include_once'
184 
185  // Action clone object
186  if ($action == 'confirm_clone' && $confirm == 'yes' && $usercancreate) {
187  if (!($socid > 0)) {
188  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('IdThirdParty')), null, 'errors');
189  } else {
190  if ($object->id > 0) {
191  if (getDolGlobalString('PROPAL_CLONE_DATE_DELIVERY')) {
192  //Get difference between old and new delivery date and change lines according to difference
193  $date_delivery = dol_mktime(
194  12,
195  0,
196  0,
197  GETPOSTINT('date_deliverymonth'),
198  GETPOSTINT('date_deliveryday'),
199  GETPOSTINT('date_deliveryyear')
200  );
201  $date_delivery_old = $object->delivery_date;
202  if (!empty($date_delivery_old) && !empty($date_delivery)) {
203  //Attempt to get the date without possible hour rounding errors
204  $old_date_delivery = dol_mktime(
205  12,
206  0,
207  0,
208  dol_print_date($date_delivery_old, '%m'),
209  dol_print_date($date_delivery_old, '%d'),
210  dol_print_date($date_delivery_old, '%Y')
211  );
212  //Calculate the difference and apply if necessary
213  $difference = $date_delivery - $old_date_delivery;
214  if ($difference != 0) {
215  $object->delivery_date = $date_delivery;
216  foreach ($object->lines as $line) {
217  if (isset($line->date_start)) {
218  $line->date_start = $line->date_start + $difference;
219  }
220  if (isset($line->date_end)) {
221  $line->date_end = $line->date_end + $difference;
222  }
223  }
224  }
225  }
226  }
227 
228  $result = $object->createFromClone($user, $socid, (GETPOSTISSET('entity') ? GETPOSTINT('entity') : null), (GETPOSTINT('update_prices') ? true : false), (GETPOSTINT('update_desc') ? true : false));
229  if ($result > 0) {
230  $warningMsgLineList = array();
231  // check all product lines are to sell otherwise add a warning message for each product line is not to sell
232  foreach ($object->lines as $line) {
233  if (!is_object($line->product)) {
234  $line->fetch_product();
235  }
236  if (is_object($line->product) && $line->product->id > 0) {
237  if (empty($line->product->status)) {
238  $warningMsgLineList[$line->id] = $langs->trans('WarningLineProductNotToSell', $line->product->ref);
239  }
240  }
241  }
242  if (!empty($warningMsgLineList)) {
243  setEventMessages('', $warningMsgLineList, 'warnings');
244  }
245 
246  header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result);
247  exit();
248  } else {
249  if (count($object->errors) > 0) {
250  setEventMessages($object->error, $object->errors, 'errors');
251  }
252  $action = '';
253  }
254  }
255  }
256  } elseif ($action == 'confirm_cancel' && $confirm == 'yes' && $usercanclose) {
257  // Cancel proposal
258  $result = $object->setCancel($user);
259  if ($result > 0) {
260  header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
261  exit();
262  } else {
263  $langs->load("errors");
264  setEventMessages($object->error, $object->errors, 'errors');
265  }
266  } elseif ($action == 'confirm_delete' && $confirm == 'yes' && $usercandelete) {
267  // Delete proposal
268  $result = $object->delete($user);
269  if ($result > 0) {
270  header('Location: '.DOL_URL_ROOT.'/comm/propal/list.php?restore_lastsearch_values=1');
271  exit();
272  } else {
273  $langs->load("errors");
274  setEventMessages($object->error, $object->errors, 'errors');
275  }
276  } elseif ($action == 'confirm_deleteline' && $confirm == 'yes' && $usercancreate) {
277  // Remove line
278  $result = $object->deleteLine($lineid);
279  // reorder lines
280  if ($result > 0) {
281  $object->line_order(true);
282  } else {
283  $langs->load("errors");
284  setEventMessages($object->error, $object->errors, 'errors');
285  }
286 
287  if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
288  // Define output language
289  $outputlangs = $langs;
290  if (getDolGlobalInt('MAIN_MULTILANGS')) {
291  $outputlangs = new Translate("", $conf);
292  $newlang = (GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $object->thirdparty->default_lang);
293  $outputlangs->setDefaultLang($newlang);
294  }
295  $ret = $object->fetch($id); // Reload to get new records
296  if ($ret > 0) {
297  $object->fetch_thirdparty();
298  }
299  $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
300  }
301 
302  header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
303  exit();
304  } elseif ($action == 'confirm_validate' && $confirm == 'yes' && $usercanvalidate) {
305  // Validation
306  $idwarehouse = GETPOSTINT('idwarehouse');
307  $result = $object->valid($user);
308  if ($result > 0 && getDolGlobalString('PROPAL_SKIP_ACCEPT_REFUSE')) {
309  $result = $object->closeProposal($user, $object::STATUS_SIGNED);
310  }
311  if ($result >= 0) {
312  if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
313  $outputlangs = $langs;
314  $newlang = '';
315  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
316  $newlang = GETPOST('lang_id', 'aZ09');
317  }
318  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
319  $newlang = $object->thirdparty->default_lang;
320  }
321  if (!empty($newlang)) {
322  $outputlangs = new Translate("", $conf);
323  $outputlangs->setDefaultLang($newlang);
324  }
325  $model = $object->model_pdf;
326  $ret = $object->fetch($id); // Reload to get new records
327  if ($ret > 0) {
328  $object->fetch_thirdparty();
329  }
330 
331  $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
332  }
333  } else {
334  $langs->load("errors");
335  if (count($object->errors) > 0) {
336  setEventMessages($object->error, $object->errors, 'errors');
337  } else {
338  setEventMessages($langs->trans($object->error), null, 'errors');
339  }
340  }
341  } elseif ($action == 'setdate' && $usercancreate) {
342  $datep = dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
343 
344  if (empty($datep)) {
345  $error++;
346  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
347  }
348 
349  if (!$error) {
350  $result = $object->set_date($user, $datep);
351  if ($result > 0 && !empty($object->duree_validite) && !empty($object->fin_validite)) {
352  $datev = $datep + ($object->duree_validite * 24 * 3600);
353  $result = $object->set_echeance($user, $datev, 1);
354  }
355  if ($result < 0) {
356  dol_print_error($db, $object->error);
357  } elseif (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
358  $outputlangs = $langs;
359  $newlang = '';
360  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
361  $newlang = GETPOST('lang_id', 'aZ09');
362  }
363  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
364  $newlang = $object->thirdparty->default_lang;
365  }
366  if (!empty($newlang)) {
367  $outputlangs = new Translate("", $conf);
368  $outputlangs->setDefaultLang($newlang);
369  }
370  $model = $object->model_pdf;
371  $ret = $object->fetch($id); // Reload to get new records
372  if ($ret > 0) {
373  $object->fetch_thirdparty();
374  }
375 
376  $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
377  }
378  }
379  } elseif ($action == 'setecheance' && $usercancreate) {
380  $result = $object->set_echeance($user, dol_mktime(12, 0, 0, GETPOSTINT('echmonth'), GETPOSTINT('echday'), GETPOSTINT('echyear')));
381  if ($result >= 0) {
382  if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
383  $outputlangs = $langs;
384  $newlang = '';
385  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
386  $newlang = GETPOST('lang_id', 'aZ09');
387  }
388  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
389  $newlang = $object->thirdparty->default_lang;
390  }
391  if (!empty($newlang)) {
392  $outputlangs = new Translate("", $conf);
393  $outputlangs->setDefaultLang($newlang);
394  }
395  $model = $object->model_pdf;
396  $ret = $object->fetch($id); // Reload to get new records
397  if ($ret > 0) {
398  $object->fetch_thirdparty();
399  }
400 
401  $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
402  }
403  } else {
404  setEventMessages($object->error, $object->errors, 'errors');
405  }
406  } elseif ($action == 'setdate_livraison' && $usercancreate) {
407  $result = $object->setDeliveryDate($user, dol_mktime(12, 0, 0, GETPOSTINT('date_livraisonmonth'), GETPOSTINT('date_livraisonday'), GETPOSTINT('date_livraisonyear')));
408  if ($result < 0) {
409  dol_print_error($db, $object->error);
410  }
411  } elseif ($action == 'setref_client' && $usercancreate) {
412  // Positionne ref client
413  $result = $object->set_ref_client($user, GETPOST('ref_client'));
414  if ($result < 0) {
415  setEventMessages($object->error, $object->errors, 'errors');
416  }
417  } elseif ($action == 'set_incoterms' && isModEnabled('incoterm') && $usercancreate) {
418  // Set incoterm
419  $result = $object->setIncoterms(GETPOSTINT('incoterm_id'), GETPOSTINT('location_incoterms'));
420  } elseif ($action == 'add' && $usercancreate) {
421  // Create proposal
422  $object->socid = $socid;
423  $object->fetch_thirdparty();
424 
425  $datep = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear'));
426  $date_delivery = dol_mktime(12, 0, 0, GETPOST('date_livraisonmonth'), GETPOST('date_livraisonday'), GETPOST('date_livraisonyear'));
427  $duration = GETPOSTINT('duree_validite');
428 
429  if (empty($datep)) {
430  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DatePropal")), null, 'errors');
431  $action = 'create';
432  $error++;
433  }
434  if (empty($duration)) {
435  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ValidityDuration")), null, 'errors');
436  $action = 'create';
437  $error++;
438  }
439 
440  if ($socid < 1) {
441  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Customer")), null, 'errors');
442 
443  $action = 'create';
444  $error++;
445  }
446 
447  if (!$error) {
448  $db->begin();
449 
450  // If we select proposal to clone during creation (when option PROPAL_CLONE_ON_CREATE_PAGE is on)
451  if (GETPOST('createmode') == 'copy' && GETPOST('copie_propal')) {
452  if ($object->fetch(GETPOSTINT('copie_propal')) > 0) {
453  $object->ref = GETPOST('ref');
454  $object->datep = $datep;
455  $object->date = $datep;
456  $object->delivery_date = $date_delivery;
457  $object->availability_id = GETPOSTINT('availability_id');
458  $object->demand_reason_id = GETPOSTINT('demand_reason_id');
459  $object->fk_delivery_address = GETPOSTINT('fk_address');
460  $object->shipping_method_id = GETPOSTINT('shipping_method_id');
461  $object->warehouse_id = GETPOSTINT('warehouse_id');
462  $object->duree_validite = $duration;
463  $object->cond_reglement_id = GETPOSTINT('cond_reglement_id');
464  $object->deposit_percent = GETPOSTFLOAT('cond_reglement_id_deposit_percent');
465  $object->mode_reglement_id = GETPOSTINT('mode_reglement_id');
466  $object->fk_account = GETPOSTINT('fk_account');
467  $object->socid = GETPOSTINT('socid');
468  $object->contact_id = GETPOSTINT('contactid');
469  $object->fk_project = GETPOSTINT('projectid');
470  $object->model_pdf = GETPOST('model', 'alphanohtml');
471  $object->author = $user->id; // deprecated
472  $object->user_author_id = $user->id;
473  $object->note_private = GETPOST('note_private', 'restricthtml');
474  $object->note_public = GETPOST('note_public', 'restricthtml');
475  $object->statut = Propal::STATUS_DRAFT;
476  $object->status = Propal::STATUS_DRAFT;
477  $object->fk_incoterms = GETPOSTINT('incoterm_id');
478  $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
479  } else {
480  setEventMessages($langs->trans("ErrorFailedToCopyProposal", GETPOST('copie_propal')), null, 'errors');
481  }
482  } else {
483  $object->ref = GETPOST('ref');
484  $object->ref_client = GETPOST('ref_client');
485  $object->datep = $datep;
486  $object->date = $datep;
487  $object->delivery_date = $date_delivery;
488  $object->availability_id = GETPOSTINT('availability_id');
489  $object->demand_reason_id = GETPOSTINT('demand_reason_id');
490  $object->fk_delivery_address = GETPOSTINT('fk_address');
491  $object->shipping_method_id = GETPOSTINT('shipping_method_id');
492  $object->warehouse_id = GETPOSTINT('warehouse_id');
493  $object->duree_validite = price2num(GETPOST('duree_validite', 'alpha'));
494  $object->cond_reglement_id = GETPOSTINT('cond_reglement_id');
495  $object->deposit_percent = GETPOSTFLOAT('cond_reglement_id_deposit_percent');
496  $object->mode_reglement_id = GETPOSTINT('mode_reglement_id');
497  $object->fk_account = GETPOSTINT('fk_account');
498  $object->contact_id = GETPOSTINT('contactid');
499  $object->fk_project = GETPOSTINT('projectid');
500  $object->model_pdf = GETPOST('model');
501  $object->author = $user->id; // deprecated
502  $object->note_private = GETPOST('note_private', 'restricthtml');
503  $object->note_public = GETPOST('note_public', 'restricthtml');
504  $object->fk_incoterms = GETPOSTINT('incoterm_id');
505  $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
506 
507  $object->origin = GETPOST('origin');
508  $object->origin_id = GETPOSTINT('originid');
509 
510  // Multicurrency
511  if (isModEnabled("multicurrency")) {
512  $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
513  }
514 
515  // Fill array 'array_options' with data from add form
516  $ret = $extrafields->setOptionalsFromPost(null, $object);
517  if ($ret < 0) {
518  $error++;
519  $action = 'create';
520  }
521  }
522 
523  if (!$error) {
524  if ($origin && $originid) {
525  // Parse element/subelement (ex: project_task)
526  $element = $subelement = $origin;
527  $regs = array();
528  if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
529  $element = $regs[1];
530  $subelement = $regs[2];
531  }
532 
533  // For compatibility
534  if ($element == 'order') {
535  $element = $subelement = 'commande';
536  }
537  if ($element == 'propal') {
538  $element = 'comm/propal';
539  $subelement = 'propal';
540  }
541  if ($element == 'contract') {
542  $element = $subelement = 'contrat';
543  }
544  if ($element == 'inter') {
545  $element = $subelement = 'ficheinter';
546  }
547  if ($element == 'shipping') {
548  $element = $subelement = 'expedition';
549  }
550 
551  $object->origin = $origin;
552  $object->origin_id = $originid;
553 
554  // Possibility to add external linked objects with hooks
555  $object->linked_objects[$object->origin] = $object->origin_id;
556  if (GETPOSTISARRAY('other_linked_objects')) {
557  $object->linked_objects = array_merge($object->linked_objects, GETPOST('other_linked_objects', 'array:int'));
558  }
559 
560  $id = $object->create($user);
561  if ($id > 0) {
562  dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
563 
564  $classname = ucfirst($subelement);
565  $srcobject = new $classname($db);
566 
567  dol_syslog("Try to find source object origin=".$object->origin." originid=".$object->origin_id." to add lines");
568  $result = $srcobject->fetch($object->origin_id);
569 
570  if ($result > 0) {
571  $lines = $srcobject->lines;
572  if (empty($lines) && method_exists($srcobject, 'fetch_lines')) {
573  $srcobject->fetch_lines();
574  $lines = $srcobject->lines;
575  }
576 
577  $fk_parent_line = 0;
578  $num = count($lines);
579  for ($i = 0; $i < $num; $i++) {
580  $label = (!empty($lines[$i]->label) ? $lines[$i]->label : '');
581  $desc = (!empty($lines[$i]->desc) ? $lines[$i]->desc : '');
582 
583  // Positive line
584  $product_type = ($lines[$i]->product_type ? $lines[$i]->product_type : 0);
585 
586  // Date start
587  $date_start = false;
588  if ($lines[$i]->date_debut_prevue) {
589  $date_start = $lines[$i]->date_debut_prevue;
590  }
591  if ($lines[$i]->date_debut_reel) {
592  $date_start = $lines[$i]->date_debut_reel;
593  }
594  if ($lines[$i]->date_start) {
595  $date_start = $lines[$i]->date_start;
596  }
597 
598  // Date end
599  $date_end = false;
600  if ($lines[$i]->date_fin_prevue) {
601  $date_end = $lines[$i]->date_fin_prevue;
602  }
603  if ($lines[$i]->date_fin_reel) {
604  $date_end = $lines[$i]->date_fin_reel;
605  }
606  if ($lines[$i]->date_end) {
607  $date_end = $lines[$i]->date_end;
608  }
609 
610  // Reset fk_parent_line for no child products and special product
611  if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) {
612  $fk_parent_line = 0;
613  }
614 
615  // Extrafields
616  if (method_exists($lines[$i], 'fetch_optionals')) {
617  $lines[$i]->fetch_optionals();
618  $array_options = $lines[$i]->array_options;
619  }
620 
621  $tva_tx = $lines[$i]->tva_tx;
622  if (!empty($lines[$i]->vat_src_code) && !preg_match('/\‍(/', $tva_tx)) {
623  $tva_tx .= ' ('.$lines[$i]->vat_src_code.')';
624  }
625 
626  $result = $object->addline($desc, $lines[$i]->subprice, $lines[$i]->qty, $tva_tx, $lines[$i]->localtax1_tx, $lines[$i]->localtax2_tx, $lines[$i]->fk_product, $lines[$i]->remise_percent, 'HT', 0, $lines[$i]->info_bits, $product_type, $lines[$i]->rang, $lines[$i]->special_code, $fk_parent_line, $lines[$i]->fk_fournprice, $lines[$i]->pa_ht, $label, $date_start, $date_end, $array_options, $lines[$i]->fk_unit);
627 
628  if ($result > 0) {
629  $lineid = $result;
630  } else {
631  $lineid = 0;
632  $error++;
633  break;
634  }
635 
636  // Defined the new fk_parent_line
637  if ($result > 0 && $lines[$i]->product_type == 9) {
638  $fk_parent_line = $result;
639  }
640  }
641 
642  // Hooks
643  $parameters = array('objFrom' => $srcobject);
644  $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been
645  // modified by hook
646  if ($reshook < 0) {
647  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
648  $error++;
649  }
650  } else {
651  setEventMessages($srcobject->error, $srcobject->errors, 'errors');
652  $error++;
653  }
654  } else {
655  setEventMessages($object->error, $object->errors, 'errors');
656  $error++;
657  }
658  } else {
659  // Standard creation
660  $id = $object->create($user);
661  }
662 
663  if ($id > 0) {
664  // Insert default contacts if defined
665  if (GETPOST('contactid') > 0) {
666  $result = $object->add_contact(GETPOST('contactid'), 'CUSTOMER', 'external');
667  if ($result < 0) {
668  $error++;
669  setEventMessages($langs->trans("ErrorFailedToAddContact"), null, 'errors');
670  }
671  }
672 
673  if (getDolGlobalString('PROPOSAL_AUTO_ADD_AUTHOR_AS_CONTACT')) {
674  $result = $object->add_contact($user->id, 'SALESREPFOLL', 'internal');
675  if ($result < 0) {
676  $error++;
677  setEventMessages($langs->trans("ErrorFailedToAddUserAsContact"), null, 'errors');
678  }
679  }
680 
681  if (!$error) {
682  $db->commit();
683 
684  // Define output language
685  if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
686  $outputlangs = $langs;
687  $newlang = '';
688  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
689  $newlang = GETPOST('lang_id', 'aZ09');
690  }
691  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
692  $newlang = $object->thirdparty->default_lang;
693  }
694  if (!empty($newlang)) {
695  $outputlangs = new Translate("", $conf);
696  $outputlangs->setDefaultLang($newlang);
697  }
698  $model = $object->model_pdf;
699 
700  $ret = $object->fetch($id); // Reload to get new records
701  $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
702  if ($result < 0) {
703  dol_print_error($db, $result);
704  }
705  }
706 
707  header('Location: '.$_SERVER["PHP_SELF"].'?id='.$id);
708  exit();
709  } else {
710  $db->rollback();
711  $action = 'create';
712  }
713  } else {
714  setEventMessages($object->error, $object->errors, 'errors');
715  $db->rollback();
716  $action = 'create';
717  }
718  }
719  }
720  } elseif ($action == 'classifybilled' && $usercanclose) {
721  // Classify billed
722  $db->begin();
723 
724  $result = $object->classifyBilled($user, 0, '');
725  if ($result < 0) {
726  setEventMessages($object->error, $object->errors, 'errors');
727  $error++;
728  }
729 
730  if (!$error) {
731  $db->commit();
732  } else {
733  $db->rollback();
734  }
735  } elseif ($action == 'confirm_closeas' && $usercanclose && !GETPOST('cancel', 'alpha')) {
736  // Close proposal
737  if (!(GETPOSTINT('statut') > 0)) {
738  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CloseAs")), null, 'errors');
739  $action = 'closeas';
740  } elseif (GETPOSTINT('statut') == $object::STATUS_SIGNED || GETPOSTINT('statut') == $object::STATUS_NOTSIGNED) {
741  $locationTarget = '';
742  // prevent browser refresh from closing proposal several times
743  if ($object->statut == $object::STATUS_VALIDATED || (getDolGlobalString('PROPAL_SKIP_ACCEPT_REFUSE') && $object->statut == $object::STATUS_DRAFT)) {
744  $db->begin();
745 
746  $result = $object->closeProposal($user, GETPOSTINT('statut'), GETPOSTINT('note_private'));
747  if ($result < 0) {
748  setEventMessages($object->error, $object->errors, 'errors');
749  $error++;
750  } else {
751  // Needed if object linked modified by trigger (because linked objects can't be fetched two times : linkedObjectsFullLoaded)
752  $locationTarget = DOL_URL_ROOT . '/comm/propal/card.php?id=' . $object->id;
753  }
754 
755  $deposit = null;
756 
757  $deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
758 
759  if (
760  !$error && GETPOSTINT('statut') == $object::STATUS_SIGNED && GETPOSTINT('generate_deposit') == 'on'
761  && !empty($deposit_percent_from_payment_terms) && isModEnabled('invoice') && $user->hasRight('facture', 'creer')
762  ) {
763  require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
764 
765  $date = dol_mktime(0, 0, 0, GETPOSTINT('datefmonth'), GETPOSTINT('datefday'), GETPOSTINT('datefyear'));
766  $forceFields = array();
767 
768  if (GETPOSTISSET('date_pointoftax')) {
769  $forceFields['date_pointoftax'] = dol_mktime(0, 0, 0, GETPOSTINT('date_pointoftaxmonth'), GETPOSTINT('date_pointoftaxday'), GETPOSTINT('date_pointoftaxyear'));
770  }
771 
772  $deposit = Facture::createDepositFromOrigin($object, $date, GETPOSTINT('cond_reglement_id'), $user, 0, GETPOSTINT('validate_generated_deposit') == 'on', $forceFields);
773 
774  if ($deposit) {
775  setEventMessage('DepositGenerated');
776  $locationTarget = DOL_URL_ROOT . '/compta/facture/card.php?id=' . $deposit->id;
777  } else {
778  $error++;
779  setEventMessages($object->error, $object->errors, 'errors');
780  }
781  }
782 
783  if (!$error) {
784  $db->commit();
785 
786  if ($deposit && !getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
787  $ret = $deposit->fetch($deposit->id); // Reload to get new records
788  $outputlangs = $langs;
789 
790  if (getDolGlobalInt('MAIN_MULTILANGS')) {
791  $outputlangs = new Translate('', $conf);
792  $outputlangs->setDefaultLang($deposit->thirdparty->default_lang);
793  $outputlangs->load('products');
794  }
795 
796  $result = $deposit->generateDocument($deposit->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
797 
798  if ($result < 0) {
799  setEventMessages($deposit->error, $deposit->errors, 'errors');
800  }
801  }
802 
803  if ($locationTarget) {
804  header('Location: ' . $locationTarget);
805  exit;
806  }
807  } else {
808  $db->rollback();
809  $action = '';
810  }
811  }
812  }
813  } elseif ($action == 'confirm_reopen' && $usercanclose && !GETPOST('cancel', 'alpha')) {
814  // Reopen proposal
815  // prevent browser refresh from reopening proposal several times
817  $db->begin();
818 
819  $newstatus = (getDolGlobalInt('PROPAL_SKIP_ACCEPT_REFUSE') ? Propal::STATUS_DRAFT : Propal::STATUS_VALIDATED);
820  $result = $object->reopen($user, $newstatus);
821  if ($result < 0) {
822  setEventMessages($object->error, $object->errors, 'errors');
823  $error++;
824  } else {
825  $object->statut = $newstatus;
826  $object->status = $newstatus;
827  }
828 
829  if (!$error) {
830  $db->commit();
831  } else {
832  $db->rollback();
833  }
834  }
835  } elseif ($action == 'import_lines_from_object'
836  && $user->hasRight('propal', 'creer')
837  && $object->statut == Propal::STATUS_DRAFT
838  ) {
839  // add lines from objectlinked
840  $fromElement = GETPOST('fromelement');
841  $fromElementid = GETPOST('fromelementid');
842  $importLines = GETPOST('line_checkbox');
843 
844  if (!empty($importLines) && is_array($importLines) && !empty($fromElement) && ctype_alpha($fromElement) && !empty($fromElementid)) {
845  if ($fromElement == 'commande') {
846  dol_include_once('/'.$fromElement.'/class/'.$fromElement.'.class.php');
847  $lineClassName = 'OrderLine';
848  } elseif ($fromElement == 'propal') {
849  dol_include_once('/comm/'.$fromElement.'/class/'.$fromElement.'.class.php');
850  $lineClassName = 'PropaleLigne';
851  } elseif ($fromElement == 'facture') {
852  dol_include_once('/compta/'.$fromElement.'/class/'.$fromElement.'.class.php');
853  $lineClassName = 'FactureLigne';
854  }
855  $nextRang = count($object->lines) + 1;
856  $importCount = 0;
857  $error = 0;
858  foreach ($importLines as $lineId) {
859  $lineId = intval($lineId);
860  $originLine = new $lineClassName($db);
861  if (intval($fromElementid) > 0 && $originLine->fetch($lineId) > 0) {
862  $originLine->fetch_optionals();
863  $desc = $originLine->desc;
864  $pu_ht = $originLine->subprice;
865  $qty = $originLine->qty;
866  $txtva = $originLine->tva_tx;
867  $txlocaltax1 = $originLine->localtax1_tx;
868  $txlocaltax2 = $originLine->localtax2_tx;
869  $fk_product = $originLine->fk_product;
870  $remise_percent = $originLine->remise_percent;
871  $date_start = $originLine->date_start;
872  $date_end = $originLine->date_end;
873  $fk_code_ventilation = 0;
874  $info_bits = $originLine->info_bits;
875  $fk_remise_except = $originLine->fk_remise_except;
876  $price_base_type = 'HT';
877  $pu_ttc = 0;
878  $type = $originLine->product_type;
879  $rang = $nextRang++;
880  $special_code = $originLine->special_code;
881  $origin = $originLine->element;
882  $origin_id = $originLine->id;
883  $fk_parent_line = 0;
884  $fk_fournprice = $originLine->fk_fournprice;
885  $pa_ht = $originLine->pa_ht;
886  $label = $originLine->label;
887  $array_options = $originLine->array_options;
888  $situation_percent = 100;
889  $fk_prev_id = '';
890  $fk_unit = $originLine->fk_unit;
891  $pu_ht_devise = $originLine->multicurrency_subprice;
892 
893  $res = $object->addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1, $txlocaltax2, $fk_product, $remise_percent, $price_base_type, $pu_ttc, $info_bits, $type, $rang, $special_code, $fk_parent_line, $fk_fournprice, $pa_ht, $label, $date_start, $date_end, $array_options, $fk_unit, $origin, $origin_id, $pu_ht_devise, $fk_remise_except);
894 
895  if ($res > 0) {
896  $importCount++;
897  } else {
898  $error++;
899  }
900  } else {
901  $error++;
902  }
903  }
904 
905  if ($error) {
906  setEventMessages($langs->trans('ErrorsOnXLines', $error), null, 'errors');
907  }
908  }
909  }
910 
911  include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
912 
913  // Actions to send emails
914  $actiontypecode = 'AC_OTH_AUTO';
915  $triggersendname = 'PROPAL_SENTBYMAIL';
916  $autocopy = 'MAIN_MAIL_AUTOCOPY_PROPOSAL_TO';
917  $trackid = 'pro'.$object->id;
918  include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
919 
920 
921  // Go back to draft
922  if ($action == 'modif' && $usercancreate) {
923  $object->setDraft($user);
924 
925  if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
926  // Define output language
927  $outputlangs = $langs;
928  if (getDolGlobalInt('MAIN_MULTILANGS')) {
929  $outputlangs = new Translate("", $conf);
930  $newlang = (GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $object->thirdparty->default_lang);
931  $outputlangs->setDefaultLang($newlang);
932  }
933  $ret = $object->fetch($id); // Reload to get new records
934  if ($ret > 0) {
935  $object->fetch_thirdparty();
936  }
937  $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
938  }
939  } elseif ($action == "setabsolutediscount" && $usercancreate) {
940  if (GETPOSTINT("remise_id")) {
941  if ($object->id > 0) {
942  $result = $object->insert_discount(GETPOSTINT("remise_id"));
943  if ($result < 0) {
944  setEventMessages($object->error, $object->errors, 'errors');
945  }
946  }
947  }
948  } elseif ($action == 'addline' && GETPOST('submitforalllines', 'aZ09') && (GETPOST('alldate_start', 'alpha') || GETPOST('alldate_end', 'alpha')) && $usercancreate) {
949  // Define date start and date end for all line
950  $alldate_start = dol_mktime(GETPOST('alldate_starthour'), GETPOST('alldate_startmin'), 0, GETPOST('alldate_startmonth'), GETPOST('alldate_startday'), GETPOST('alldate_startyear'));
951  $alldate_end = dol_mktime(GETPOST('alldate_endhour'), GETPOST('alldate_endmin'), 0, GETPOST('alldate_endmonth'), GETPOST('alldate_endday'), GETPOST('alldate_endyear'));
952  foreach ($object->lines as $line) {
953  if ($line->product_type == 1) { // only service line
954  $result = $object->updateline($line->id, $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, $line->desc, 'HT', $line->info_bits, $line->special_code, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->product_type, $alldate_start, $alldate_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice);
955  }
956  }
957  } elseif ($action == 'addline' && GETPOST('submitforalllines', 'alpha') && GETPOST('vatforalllines', 'alpha') !== '' && $usercancreate) {
958  // Define a vat_rate for all lines
959  $vat_rate = (GETPOST('vatforalllines') ? GETPOST('vatforalllines') : 0);
960  $vat_rate = str_replace('*', '', $vat_rate);
961  $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty, $mysoc);
962  $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty, $mysoc);
963  foreach ($object->lines as $line) {
964  $result = $object->updateline($line->id, $line->subprice, $line->qty, $line->remise_percent, $vat_rate, $localtax1_rate, $localtax2_rate, $line->desc, 'HT', $line->info_bits, $line->special_code, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->product_type, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice);
965  }
966  } elseif ($action == 'addline' && GETPOST('submitforalllines', 'alpha') && GETPOST('remiseforalllines', 'alpha') !== '' && $usercancreate) {
967  // Define a discount for all lines
968  $remise_percent = (GETPOST('remiseforalllines') ? GETPOST('remiseforalllines') : 0);
969  $remise_percent = str_replace('*', '', $remise_percent);
970  foreach ($object->lines as $line) {
971  $tvatx= $line->tva_tx;
972  if (!empty($line->vat_src_code)) {
973  $tvatx .= ' ('.$line->vat_src_code.')';
974  }
975  $result = $object->updateline($line->id, $line->subprice, $line->qty, $remise_percent, $tvatx, $line->localtax1_tx, $line->localtax2_tx, $line->desc, 'HT', $line->info_bits, $line->special_code, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->product_type, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice);
976  }
977  } elseif ($action == 'addline' && GETPOST('submitforallmargins', 'alpha') && GETPOST('marginforalllines') !== '' && $usercancreate) {
978  // Define margin
979  $margin_rate = (GETPOST('marginforalllines') ? GETPOST('marginforalllines') : 0);
980  foreach ($object->lines as &$line) {
981  $subprice = price2num($line->pa_ht * (1 + $margin_rate / 100), 'MU');
982  $prod = new Product($db);
983  $prod->fetch($line->fk_product);
984  if ($prod->price_min > $subprice) {
985  $price_subprice = price($subprice, 0, $outlangs, 1, -1, -1, 'auto');
986  $price_price_min = price($prod->price_min, 0, $outlangs, 1, -1, -1, 'auto');
987  setEventMessages($prod->ref.' - '.$prod->label.' ('.$price_subprice.' < '.$price_price_min.' '.strtolower($langs->trans("MinPrice")).')'."\n", null, 'warnings');
988  }
989  // Manage $line->subprice and $line->multicurrency_subprice
990  $multicurrency_subprice = (float) $subprice * $line->multicurrency_subprice / $line->subprice;
991  // Update DB
992  $result = $object->updateline($line->id, $subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_rate, $line->localtax2_rate, $line->desc, 'HT', $line->info_bits, $line->special_code, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->product_type, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $multicurrency_subprice);
993  // Update $object with new margin info
994  $line->price = $subprice;
995  $line->marge_tx = $margin_rate;
996  $line->marque_tx = $margin_rate * $line->pa_ht / (float) $subprice;
997  $line->total_ht = $line->qty * (float) $subprice;
998  $line->total_tva = $line->tva_tx * $line->qty * (float) $subprice;
999  $line->total_ttc = (1 + $line->tva_tx) * $line->qty * (float) $subprice;
1000  // Manage $line->subprice and $line->multicurrency_subprice
1001  $line->multicurrency_total_ht = $line->qty * (float) $subprice * $line->multicurrency_subprice / $line->subprice;
1002  $line->multicurrency_total_tva = $line->tva_tx * $line->qty * (float) $subprice * $line->multicurrency_subprice / $line->subprice;
1003  $line->multicurrency_total_ttc = (1 + $line->tva_tx) * $line->qty * (float) $subprice * $line->multicurrency_subprice / $line->subprice;
1004  // Used previous $line->subprice and $line->multicurrency_subprice above, now they can be set to their new values
1005  $line->subprice = $subprice;
1006  $line->multicurrency_subprice = $multicurrency_subprice;
1007  }
1008  } elseif ($action == 'addline' && !GETPOST('submitforalllines', 'alpha') && !GETPOST('submitforallmargins', 'alpha') && $usercancreate) { // Add line
1009  // Set if we used free entry or predefined product
1010  $predef = '';
1011  $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
1012 
1013  $price_ht = '';
1014  $price_ht_devise = '';
1015  $price_ttc = '';
1016  $price_ttc_devise = '';
1017 
1018  // TODO Implement if (getDolGlobalInt('MAIN_UNIT_PRICE_WITH_TAX_IS_FOR_ALL_TAXES'))
1019 
1020  if (GETPOST('price_ht') !== '') {
1021  $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
1022  }
1023  if (GETPOST('multicurrency_price_ht') !== '') {
1024  $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU', 2);
1025  }
1026  if (GETPOST('price_ttc') !== '') {
1027  $price_ttc = price2num(GETPOST('price_ttc'), 'MU', 2);
1028  }
1029  if (GETPOST('multicurrency_price_ttc') !== '') {
1030  $price_ttc_devise = price2num(GETPOST('multicurrency_price_ttc'), 'CU', 2);
1031  }
1032 
1033  $prod_entry_mode = GETPOST('prod_entry_mode', 'aZ09');
1034  if ($prod_entry_mode == 'free') {
1035  $idprod = 0;
1036  } else {
1037  $idprod = GETPOSTINT('idprod');
1038 
1039  if (getDolGlobalString('MAIN_DISABLE_FREE_LINES') && $idprod <= 0) {
1040  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")), null, 'errors');
1041  $error++;
1042  }
1043  }
1044 
1045  $tva_tx = GETPOST('tva_tx', 'alpha');
1046 
1047  $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS', 2);
1048  $remise_percent = (GETPOSTISSET('remise_percent'.$predef) ? price2num(GETPOST('remise_percent'.$predef, 'alpha'), '', 2) : 0);
1049  if (empty($remise_percent)) {
1050  $remise_percent = 0;
1051  }
1052 
1053  // Extrafields
1054  $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
1055  $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
1056  // Unset extrafield
1057  if (is_array($extralabelsline)) {
1058  // Get extra fields
1059  foreach ($extralabelsline as $key => $value) {
1060  unset($_POST["options_".$key]);
1061  }
1062  }
1063 
1064  if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && GETPOST('type') < 0) {
1065  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
1066  $error++;
1067  }
1068 
1069  if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && $price_ht === '' && $price_ht_devise === '' && $price_ttc === '' && $price_ttc_devise === '') { // Unit price can be 0 but not ''. Also price can be negative for proposal.
1070  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
1071  $error++;
1072  }
1073  if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && empty($product_desc)) {
1074  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Description")), null, 'errors');
1075  $error++;
1076  }
1077 
1078  if (!$error && isModEnabled('variants') && $prod_entry_mode != 'free') {
1079  if ($combinations = GETPOST('combinations', 'array')) {
1080  //Check if there is a product with the given combination
1081  $prodcomb = new ProductCombination($db);
1082 
1083  if ($res = $prodcomb->fetchByProductCombination2ValuePairs($idprod, $combinations)) {
1084  $idprod = $res->fk_product_child;
1085  } else {
1086  setEventMessages($langs->trans('ErrorProductCombinationNotFound'), null, 'errors');
1087  $error++;
1088  }
1089  }
1090  }
1091 
1092  $propal_qty_requirement = (getDolGlobalString('PROPAL_ENABLE_NEGATIVE_QTY') ? ($qty >= 0 || $qty <= 0) : $qty >= 0);
1093  if (!$error && $propal_qty_requirement && (!empty($product_desc) || (!empty($idprod) && $idprod > 0))) {
1094  $pu_ht = 0;
1095  $pu_ttc = 0;
1096  $pu_ht_devise = 0;
1097  $pu_ttc_devise = 0;
1098  $price_min = 0;
1099  $price_min_ttc = 0;
1100  $tva_npr = 0;
1101  $price_base_type = (GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT');
1102 
1103  $db->begin();
1104 
1105  // $tva_tx can be 'x.x (XXX)'
1106 
1107  // Ecrase $pu par celui du produit
1108  // Ecrase $desc par celui du produit
1109  // Replaces $fk_unit with the product unit
1110  if (!empty($idprod) && $idprod > 0) {
1111  $prod = new Product($db);
1112  $prod->fetch($idprod);
1113 
1114  $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
1115 
1116  // Update if prices fields are defined
1117  /*$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
1118  $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
1119  if (empty($tva_tx)) {
1120  $tva_npr = 0;
1121  }*/
1122 
1123  // Price unique per product
1124  $pu_ht = $prod->price;
1125  $pu_ttc = $prod->price_ttc;
1126  $price_min = $prod->price_min;
1127  $price_min_ttc = $prod->price_min_ttc;
1128  $price_base_type = $prod->price_base_type;
1129 
1130  // If price per segment
1131  if (getDolGlobalString('PRODUIT_MULTIPRICES') && $object->thirdparty->price_level) {
1132  $pu_ht = $prod->multiprices[$object->thirdparty->price_level];
1133  $pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
1134  $price_min = $prod->multiprices_min[$object->thirdparty->price_level];
1135  $price_min_ttc = $prod->multiprices_min_ttc[$object->thirdparty->price_level];
1136  $price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
1137  if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility
1138  if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) {
1139  $tva_tx = $prod->multiprices_tva_tx[$object->thirdparty->price_level];
1140  }
1141  if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) {
1142  $tva_npr = $prod->multiprices_recuperableonly[$object->thirdparty->price_level];
1143  }
1144  }
1145  } elseif (getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) {
1146  // If price per customer
1147  require_once DOL_DOCUMENT_ROOT.'/product/class/productcustomerprice.class.php';
1148 
1149  $prodcustprice = new ProductCustomerPrice($db);
1150 
1151  $filter = array('t.fk_product' => $prod->id, 't.fk_soc' => $object->thirdparty->id);
1152 
1153  $result = $prodcustprice->fetchAll('', '', 0, 0, $filter);
1154  if ($result) {
1155  // If there is some prices specific to the customer
1156  if (count($prodcustprice->lines) > 0) {
1157  $pu_ht = price($prodcustprice->lines[0]->price);
1158  $pu_ttc = price($prodcustprice->lines[0]->price_ttc);
1159  $price_min = price($prodcustprice->lines[0]->price_min);
1160  $price_min_ttc = price($prodcustprice->lines[0]->price_min_ttc);
1161  $price_base_type = $prodcustprice->lines[0]->price_base_type;
1162  /*$tva_tx = ($prodcustprice->lines[0]->default_vat_code ? $prodcustprice->lines[0]->tva_tx.' ('.$prodcustprice->lines[0]->default_vat_code.' )' : $prodcustprice->lines[0]->tva_tx);
1163  if ($prodcustprice->lines[0]->default_vat_code && !preg_match('/\‍(.*\‍)/', $tva_tx)) {
1164  $tva_tx .= ' ('.$prodcustprice->lines[0]->default_vat_code.')';
1165  }
1166  $tva_npr = $prodcustprice->lines[0]->recuperableonly;
1167  if (empty($tva_tx)) {
1168  $tva_npr = 0;
1169  }*/
1170  }
1171  }
1172  } elseif (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY')) {
1173  // If price per quantity
1174  if ($prod->prices_by_qty[0]) { // yes, this product has some prices per quantity
1175  // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
1176  $pqp = GETPOSTINT('pbq');
1177 
1178  // Search price into product_price_by_qty from $prod->id
1179  foreach ($prod->prices_by_qty_list[0] as $priceforthequantityarray) {
1180  if ($priceforthequantityarray['rowid'] != $pqp) {
1181  continue;
1182  }
1183  // We found the price
1184  if ($priceforthequantityarray['price_base_type'] == 'HT') {
1185  $pu_ht = $priceforthequantityarray['unitprice'];
1186  } else {
1187  $pu_ttc = $priceforthequantityarray['unitprice'];
1188  }
1189  // Note: the remise_percent or price by qty is used to set data on form, so we will use value from POST.
1190  break;
1191  }
1192  }
1193  } elseif (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
1194  // If price per quantity and customer
1195  if ($prod->prices_by_qty[$object->thirdparty->price_level]) { // yes, this product has some prices per quantity
1196  // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
1197  $pqp = GETPOSTINT('pbq');
1198 
1199  // Search price into product_price_by_qty from $prod->id
1200  foreach ($prod->prices_by_qty_list[$object->thirdparty->price_level] as $priceforthequantityarray) {
1201  if ($priceforthequantityarray['rowid'] != $pqp) {
1202  continue;
1203  }
1204  // We found the price
1205  if ($priceforthequantityarray['price_base_type'] == 'HT') {
1206  $pu_ht = $priceforthequantityarray['unitprice'];
1207  } else {
1208  $pu_ttc = $priceforthequantityarray['unitprice'];
1209  }
1210  // Note: the remise_percent or price by qty is used to set data on form, so we will use value from POST.
1211  break;
1212  }
1213  }
1214  }
1215 
1216  $tmpvat = price2num(preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx));
1217  $tmpprodvat = price2num(preg_replace('/\s*\‍(.*\‍)/', '', (string) $prod->tva_tx));
1218 
1219  // Set unit price to use
1220  if (!empty($price_ht) || (string) $price_ht === '0') {
1221  $pu_ht = price2num($price_ht, 'MU');
1222  $pu_ttc = price2num((float) $pu_ht * (1 + ((float) $tmpvat / 100)), 'MU');
1223  } elseif (!empty($price_ht_devise) || (string) $price_ht_devise === '0') {
1224  $pu_ht_devise = price2num($price_ht_devise, 'MU');
1225  $pu_ht = '';
1226  $pu_ttc = '';
1227  } elseif (!empty($price_ttc) || (string) $price_ttc === '0') {
1228  $pu_ttc = price2num($price_ttc, 'MU');
1229  $pu_ht = price2num((float) $pu_ttc / (1 + ((float) $tmpvat / 100)), 'MU');
1230  } elseif ($tmpvat != $tmpprodvat) {
1231  // Is this still used ?
1232  if ($price_base_type != 'HT') {
1233  $pu_ht = price2num((float) $pu_ttc / (1 + ($tmpvat / 100)), 'MU');
1234  } else {
1235  $pu_ttc = price2num((float) $pu_ht * (1 + ($tmpvat / 100)), 'MU');
1236  }
1237  }
1238 
1239  $desc = '';
1240 
1241  // Define output language
1242  if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
1243  $outputlangs = $langs;
1244  $newlang = '';
1245  if (empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1246  $newlang = GETPOST('lang_id', 'aZ09');
1247  }
1248  if (empty($newlang)) {
1249  $newlang = $object->thirdparty->default_lang;
1250  }
1251  if (!empty($newlang)) {
1252  $outputlangs = new Translate("", $conf);
1253  $outputlangs->setDefaultLang($newlang);
1254  }
1255 
1256  $desc = (!empty($prod->multilangs[$outputlangs->defaultlang]["description"])) ? $prod->multilangs[$outputlangs->defaultlang]["description"] : $prod->description;
1257  } else {
1258  $desc = $prod->description;
1259  }
1260 
1261  //If text set in desc is the same as product description (as now it's preloaded) we add it only one time
1262  if ($product_desc == $desc && getDolGlobalString('PRODUIT_AUTOFILL_DESC')) {
1263  $product_desc = '';
1264  }
1265 
1266  if (!empty($product_desc) && getDolGlobalString('MAIN_NO_CONCAT_DESCRIPTION')) {
1267  $desc = $product_desc;
1268  } else {
1269  $desc = dol_concatdesc($desc, $product_desc, '', getDolGlobalString('MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION'));
1270  }
1271 
1272  // Add custom code and origin country into description
1273  if (!getDolGlobalString('MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE') && (!empty($prod->customcode) || !empty($prod->country_code))) {
1274  $tmptxt = '(';
1275  // Define output language
1276  if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
1277  $outputlangs = $langs;
1278  $newlang = '';
1279  if (empty($newlang) && GETPOST('lang_id', 'alpha')) {
1280  $newlang = GETPOST('lang_id', 'alpha');
1281  }
1282  if (empty($newlang)) {
1283  $newlang = $object->thirdparty->default_lang;
1284  }
1285  if (!empty($newlang)) {
1286  $outputlangs = new Translate("", $conf);
1287  $outputlangs->setDefaultLang($newlang);
1288  $outputlangs->load('products');
1289  }
1290  if (!empty($prod->customcode)) {
1291  $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomCode").': '.$prod->customcode;
1292  }
1293  if (!empty($prod->customcode) && !empty($prod->country_code)) {
1294  $tmptxt .= ' - ';
1295  }
1296  if (!empty($prod->country_code)) {
1297  $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, 0, $db, $outputlangs, 0);
1298  }
1299  } else {
1300  if (!empty($prod->customcode)) {
1301  $tmptxt .= $langs->transnoentitiesnoconv("CustomCode").': '.$prod->customcode;
1302  }
1303  if (!empty($prod->customcode) && !empty($prod->country_code)) {
1304  $tmptxt .= ' - ';
1305  }
1306  if (!empty($prod->country_code)) {
1307  $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, 0, $db, $langs, 0);
1308  }
1309  }
1310  $tmptxt .= ')';
1311  $desc = dol_concatdesc($desc, $tmptxt);
1312  }
1313 
1314  $type = $prod->type;
1315  $fk_unit = $prod->fk_unit;
1316  } else {
1317  $pu_ht = price2num($price_ht, 'MU');
1318  $pu_ttc = price2num($price_ttc, 'MU');
1319  $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
1320  if (empty($tva_tx)) {
1321  $tva_npr = 0;
1322  }
1323  $tva_tx = str_replace('*', '', $tva_tx);
1324  $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
1325  $desc = $product_desc;
1326  $type = GETPOST('type');
1327  $fk_unit = GETPOST('units', 'alpha');
1328  $pu_ht_devise = price2num($price_ht_devise, 'MU');
1329  $pu_ttc_devise = price2num($price_ttc_devise, 'MU');
1330 
1331  if ($pu_ttc && !$pu_ht) {
1332  $price_base_type = 'TTC';
1333  }
1334  }
1335 
1336  $info_bits = 0;
1337  if ($tva_npr) {
1338  $info_bits |= 0x01;
1339  }
1340 
1341  // Local Taxes
1342  $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $tva_npr);
1343  $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $tva_npr);
1344 
1345  // Margin
1346  $fournprice = price2num(GETPOST('fournprice'.$predef) ? GETPOST('fournprice'.$predef) : '');
1347  $buyingprice = price2num(GETPOST('buying_price'.$predef) != '' ? GETPOST('buying_price'.$predef) : ''); // If buying_price is '0', we must keep this value
1348 
1349  $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'));
1350  $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'));
1351 
1352  // Prepare a price equivalent for minimum price check
1353  $pu_equivalent = $pu_ht;
1354  $pu_equivalent_ttc = $pu_ttc;
1355  $currency_tx = $object->multicurrency_tx;
1356 
1357  // Check if we have a foreign currency
1358  // If so, we update the pu_equiv as the equivalent price in base currency
1359  if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') {
1360  $pu_equivalent = (float) $pu_ht_devise * (float) $currency_tx;
1361  }
1362  if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') {
1363  $pu_equivalent_ttc = (float) $pu_ttc_devise * (float) $currency_tx;
1364  }
1365 
1366  // TODO $pu_equivalent or $pu_equivalent_ttc must be calculated from the one not null taking into account all taxes
1367  /*
1368  if ($pu_equivalent) {
1369  $tmp = calcul_price_total(1, $pu_equivalent, 0, $tva_tx, -1, -1, 0, 'HT', $info_bits, $type);
1370  $pu_equivalent_ttc = ...
1371  } else {
1372  $tmp = calcul_price_total(1, $pu_equivalent_ttc, 0, $tva_tx, -1, -1, 0, 'TTC', $info_bits, $type);
1373  $pu_equivalent_ht = ...
1374  }
1375  */
1376 
1377  //var_dump(price2num($price_min)); var_dump(price2num($pu_ht)); var_dump($remise_percent);
1378  //var_dump(price2num($price_min_ttc)); var_dump(price2num($pu_ttc)); var_dump($remise_percent);exit;
1379 
1380  // Check price is not lower than minimum
1381  if ($usermustrespectpricemin) {
1382  if ($pu_equivalent && $price_min && (((float) price2num($pu_equivalent) * (1 - $remise_percent / 100)) < price2num($price_min)) && $price_base_type == 'HT') {
1383  $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1384  setEventMessages($mesg, null, 'errors');
1385  $error++;
1386  } elseif ($pu_equivalent_ttc && $price_min_ttc && (((float) price2num($pu_equivalent_ttc) * (1 - $remise_percent / 100)) < price2num($price_min_ttc)) && $price_base_type == 'TTC') {
1387  $mesg = $langs->trans("CantBeLessThanMinPriceInclTax", price(price2num($price_min_ttc, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1388  setEventMessages($mesg, null, 'errors');
1389  $error++;
1390  }
1391  }
1392 
1393  if (!$error) {
1394  // Insert line
1395  $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $price_base_type, $pu_ttc, $info_bits, $type, min($rank, count($object->lines) + 1), 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $date_start, $date_end, $array_options, $fk_unit, '', 0, $pu_ht_devise);
1396 
1397  if ($result > 0) {
1398  $db->commit();
1399 
1400  if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1401  // Define output language
1402  $outputlangs = $langs;
1403  if (getDolGlobalInt('MAIN_MULTILANGS')) {
1404  $outputlangs = new Translate("", $conf);
1405  $newlang = (GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $object->thirdparty->default_lang);
1406  $outputlangs->setDefaultLang($newlang);
1407  }
1408  $ret = $object->fetch($id); // Reload to get new records
1409  if ($ret > 0) {
1410  $object->fetch_thirdparty();
1411  }
1412  $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1413  }
1414 
1415  unset($_POST['prod_entry_mode']);
1416 
1417  unset($_POST['qty']);
1418  unset($_POST['type']);
1419  unset($_POST['remise_percent']);
1420  unset($_POST['price_ht']);
1421  unset($_POST['multicurrency_price_ht']);
1422  unset($_POST['price_ttc']);
1423  unset($_POST['tva_tx']);
1424  unset($_POST['product_ref']);
1425  unset($_POST['product_label']);
1426  unset($_POST['product_desc']);
1427  unset($_POST['fournprice']);
1428  unset($_POST['buying_price']);
1429  unset($_POST['np_marginRate']);
1430  unset($_POST['np_markRate']);
1431  unset($_POST['dp_desc']);
1432  unset($_POST['idprod']);
1433  unset($_POST['units']);
1434 
1435  unset($_POST['date_starthour']);
1436  unset($_POST['date_startmin']);
1437  unset($_POST['date_startsec']);
1438  unset($_POST['date_startday']);
1439  unset($_POST['date_startmonth']);
1440  unset($_POST['date_startyear']);
1441  unset($_POST['date_endhour']);
1442  unset($_POST['date_endmin']);
1443  unset($_POST['date_endsec']);
1444  unset($_POST['date_endday']);
1445  unset($_POST['date_endmonth']);
1446  unset($_POST['date_endyear']);
1447  } else {
1448  $db->rollback();
1449 
1450  setEventMessages($object->error, $object->errors, 'errors');
1451  }
1452  }
1453  }
1454  } elseif ($action == 'updateline' && $usercancreate && GETPOST('save')) {
1455  // Update a line within proposal
1456 
1457  // Clean parameters
1458  $description = dol_htmlcleanlastbr(GETPOST('product_desc', 'restricthtml'));
1459 
1460  // Define info_bits
1461  $info_bits = 0;
1462  if (preg_match('/\*/', GETPOST('tva_tx'))) {
1463  $info_bits |= 0x01;
1464  }
1465 
1466  // Define vat_rate
1467  $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
1468  $vat_rate = str_replace('*', '', $vat_rate);
1469  $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty, $mysoc);
1470  $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty, $mysoc);
1471  $pu_ht = price2num(GETPOST('price_ht'), '', 2);
1472  $pu_ttc = price2num(GETPOST('price_ttc'), '', 2);
1473 
1474  // Add buying price
1475  $fournprice = price2num(GETPOST('fournprice') ? GETPOST('fournprice') : '');
1476  $buyingprice = price2num(GETPOST('buying_price') != '' ? GETPOST('buying_price') : ''); // If buying_price is '0', we must keep this value
1477 
1478  $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), '', 2);
1479  $pu_ttc_devise = price2num(GETPOST('multicurrency_subprice_ttc'), '', 2);
1480 
1481  $date_start = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear'));
1482  $date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear'));
1483 
1484  $remise_percent = price2num(GETPOST('remise_percent'), '', 2);
1485  if (empty($remise_percent)) {
1486  $remise_percent = 0;
1487  }
1488 
1489  // Prepare a price equivalent for minimum price check
1490  $pu_equivalent = $pu_ht;
1491  $pu_equivalent_ttc = $pu_ttc;
1492 
1493  $currency_tx = $object->multicurrency_tx;
1494 
1495  // Check if we have a foreign currency
1496  // If so, we update the pu_equiv as the equivalent price in base currency
1497  if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') {
1498  $pu_equivalent = (float) $pu_ht_devise * (float) $currency_tx;
1499  }
1500  if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') {
1501  $pu_equivalent_ttc = (float) $pu_ttc_devise * (float) $currency_tx;
1502  }
1503 
1504  // TODO $pu_equivalent or $pu_equivalent_ttc must be calculated from the one not null taking into account all taxes
1505  /*
1506  if ($pu_equivalent) {
1507  $tmp = calcul_price_total(1, $pu_equivalent, 0, $vat_rate, -1, -1, 0, 'HT', $info_bits, $type);
1508  $pu_equivalent_ttc = ...
1509  } else {
1510  $tmp = calcul_price_total(1, $pu_equivalent_ttc, 0, $vat_rate, -1, -1, 0, 'TTC', $info_bits, $type);
1511  $pu_equivalent_ht = ...
1512  }
1513  */
1514 
1515  // Extrafields
1516  $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
1517  $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
1518  // Unset extrafield
1519  if (is_array($extralabelsline)) {
1520  // Get extra fields
1521  foreach ($extralabelsline as $key => $value) {
1522  unset($_POST["options_".$key]);
1523  }
1524  }
1525 
1526  // Define special_code for special lines
1527  $special_code = GETPOSTINT('special_code');
1528  if (!GETPOST('qty')) {
1529  $special_code = 3;
1530  }
1531 
1532  // Check minimum price
1533  $productid = GETPOSTINT('productid');
1534  if (!empty($productid)) {
1535  $product = new Product($db);
1536  $res = $product->fetch($productid);
1537 
1538  $type = $product->type;
1539  $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : '');
1540 
1541  $price_min = $product->price_min;
1542  if (getDolGlobalString('PRODUIT_MULTIPRICES') && !empty($object->thirdparty->price_level)) {
1543  $price_min = $product->multiprices_min[$object->thirdparty->price_level];
1544  }
1545  $price_min_ttc = $product->price_min_ttc;
1546  if (getDolGlobalString('PRODUIT_MULTIPRICES') && !empty($object->thirdparty->price_level)) {
1547  $price_min_ttc = $product->multiprices_min_ttc[$object->thirdparty->price_level];
1548  }
1549 
1550  //var_dump(price2num($price_min)); var_dump(price2num($pu_ht)); var_dump($remise_percent);
1551  //var_dump(price2num($price_min_ttc)); var_dump(price2num($pu_ttc)); var_dump($remise_percent);exit;
1552 
1553  // Check price is not lower than minimum
1554  if ($usermustrespectpricemin) {
1555  if ($pu_equivalent && $price_min && (((float) price2num($pu_equivalent) * (1 - (float) $remise_percent / 100)) < (float) price2num($price_min)) && $price_base_type == 'HT') {
1556  $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1557  setEventMessages($mesg, null, 'errors');
1558  $error++;
1559  $action = 'editline';
1560  } elseif ($pu_equivalent_ttc && $price_min_ttc && (((float) price2num($pu_equivalent_ttc) * (1 - (float) $remise_percent / 100)) < (float) price2num($price_min_ttc)) && $price_base_type == 'TTC') {
1561  $mesg = $langs->trans("CantBeLessThanMinPriceInclTax", price(price2num($price_min_ttc, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1562  setEventMessages($mesg, null, 'errors');
1563  $error++;
1564  $action = 'editline';
1565  }
1566  }
1567  } else {
1568  $type = GETPOST('type');
1569  $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
1570 
1571  // Check parameters
1572  if (GETPOST('type') < 0) {
1573  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
1574  $error++;
1575  }
1576  }
1577 
1578  if (!$error) {
1579  $db->begin();
1580 
1581  if (!$user->hasRight('margins', 'creer')) {
1582  foreach ($object->lines as &$line) {
1583  if ($line->id == GETPOSTINT('lineid')) {
1584  $fournprice = $line->fk_fournprice;
1585  $buyingprice = $line->pa_ht;
1586  break;
1587  }
1588  }
1589  }
1590 
1591  $qty = price2num(GETPOST('qty', 'alpha'), 'MS');
1592 
1593  $pu = $pu_ht;
1594  $price_base_type = 'HT';
1595  if (empty($pu) && !empty($pu_ttc)) {
1596  $pu = $pu_ttc;
1597  $price_base_type = 'TTC';
1598  }
1599 
1600  $result = $object->updateline(GETPOSTINT('lineid'), $pu, $qty, $remise_percent, $vat_rate, $localtax1_rate, $localtax2_rate, $description, $price_base_type, $info_bits, $special_code, GETPOST('fk_parent_line'), 0, $fournprice, $buyingprice, $label, $type, $date_start, $date_end, $array_options, GETPOST("units"), $pu_ht_devise);
1601 
1602  if ($result >= 0) {
1603  $db->commit();
1604 
1605  if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1606  // Define output language
1607  $outputlangs = $langs;
1608  if (getDolGlobalInt('MAIN_MULTILANGS')) {
1609  $outputlangs = new Translate("", $conf);
1610  $newlang = (GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $object->thirdparty->default_lang);
1611  $outputlangs->setDefaultLang($newlang);
1612  }
1613  $ret = $object->fetch($id); // Reload to get new records
1614  if ($ret > 0) {
1615  $object->fetch_thirdparty();
1616  }
1617  $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1618  }
1619 
1620  unset($_POST['qty']);
1621  unset($_POST['type']);
1622  unset($_POST['productid']);
1623  unset($_POST['remise_percent']);
1624  unset($_POST['price_ht']);
1625  unset($_POST['multicurrency_price_ht']);
1626  unset($_POST['price_ttc']);
1627  unset($_POST['tva_tx']);
1628  unset($_POST['product_ref']);
1629  unset($_POST['product_label']);
1630  unset($_POST['product_desc']);
1631  unset($_POST['fournprice']);
1632  unset($_POST['buying_price']);
1633 
1634  unset($_POST['date_starthour']);
1635  unset($_POST['date_startmin']);
1636  unset($_POST['date_startsec']);
1637  unset($_POST['date_startday']);
1638  unset($_POST['date_startmonth']);
1639  unset($_POST['date_startyear']);
1640  unset($_POST['date_endhour']);
1641  unset($_POST['date_endmin']);
1642  unset($_POST['date_endsec']);
1643  unset($_POST['date_endday']);
1644  unset($_POST['date_endmonth']);
1645  unset($_POST['date_endyear']);
1646  } else {
1647  $db->rollback();
1648 
1649  setEventMessages($object->error, $object->errors, 'errors');
1650  }
1651  }
1652  } elseif ($action == 'updateline' && $usercancreate && GETPOST('cancel', 'alpha')) {
1653  header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id); // To re-display card in edit mode
1654  exit();
1655  } elseif ($action == 'classin' && $usercancreate) {
1656  // Set project
1657  $object->setProject(GETPOSTINT('projectid'));
1658  } elseif ($action == 'setavailability' && $usercancreate) {
1659  // Delivery time
1660  $result = $object->set_availability($user, GETPOSTINT('availability_id'));
1661  } elseif ($action == 'setdemandreason' && $usercancreate) {
1662  // Origin of the commercial proposal
1663  $result = $object->set_demand_reason($user, GETPOSTINT('demand_reason_id'));
1664  } elseif ($action == 'setconditions' && $usercancreate) {
1665  // Terms of payment
1666  $result = $object->setPaymentTerms(GETPOSTINT('cond_reglement_id'), GETPOSTINT('cond_reglement_id_deposit_percent'));
1667  //} elseif ($action == 'setremisepercent' && $usercancreate) {
1668  // $result = $object->set_remise_percent($user, price2num(GETPOST('remise_percent'), '', 2));
1669  //} elseif ($action == 'setremiseabsolue' && $usercancreate) {
1670  // $result = $object->set_remise_absolue($user, price2num(GETPOST('remise_absolue'), 'MU', 2));
1671  } elseif ($action == 'setmode' && $usercancreate) {
1672  // Payment choice
1673  $result = $object->setPaymentMethods(GETPOSTINT('mode_reglement_id'));
1674  } elseif ($action == 'setmulticurrencycode' && $usercancreate) {
1675  // Multicurrency Code
1676  $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha'));
1677  } elseif ($action == 'setmulticurrencyrate' && $usercancreate) {
1678  // Multicurrency rate
1679  $result = $object->setMulticurrencyRate(price2num(GETPOST('multicurrency_tx')), GETPOSTINT('calculation_mode'));
1680  } elseif ($action == 'setbankaccount' && $usercancreate) {
1681  // bank account
1682  $result = $object->setBankAccount(GETPOSTINT('fk_account'));
1683  } elseif ($action == 'setshippingmethod' && $usercancreate) {
1684  // shipping method
1685  $result = $object->setShippingMethod(GETPOSTINT('shipping_method_id'));
1686  } elseif ($action == 'setwarehouse' && $usercancreate) {
1687  // warehouse
1688  $result = $object->setWarehouse(GETPOSTINT('warehouse_id'));
1689  } elseif ($action == 'update_extras') {
1690  $object->oldcopy = dol_clone($object, 2);
1691  $attribute_name = GETPOST('attribute', 'restricthtml');
1692 
1693  // Fill array 'array_options' with data from update form
1694  $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
1695  if ($ret < 0) {
1696  $error++;
1697  }
1698  if (!$error) {
1699  $result = $object->updateExtraField($attribute_name, 'PROPAL_MODIFY');
1700  if ($result < 0) {
1701  setEventMessages($object->error, $object->errors, 'errors');
1702  $error++;
1703  }
1704  }
1705  if ($error) {
1706  $action = 'edit_extras';
1707  }
1708  }
1709 
1710  if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB') && $usercancreate) {
1711  if ($action == 'addcontact') {
1712  if ($object->id > 0) {
1713  $contactid = (GETPOST('userid') ? GETPOST('userid') : GETPOST('contactid'));
1714  $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
1715  $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09'));
1716  }
1717 
1718  if ($result >= 0) {
1719  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1720  exit();
1721  } else {
1722  if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
1723  $langs->load("errors");
1724  setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
1725  } else {
1726  setEventMessages($object->error, $object->errors, 'errors');
1727  }
1728  }
1729  } elseif ($action == 'swapstatut') {
1730  // Toggle the status of a contact
1731  if ($object->fetch($id) > 0) {
1732  $result = $object->swapContactStatus(GETPOSTINT('ligne'));
1733  } else {
1734  dol_print_error($db);
1735  }
1736  } elseif ($action == 'deletecontact') {
1737  // Delete a contact
1738  $object->fetch($id);
1739  $result = $object->delete_contact($lineid);
1740 
1741  if ($result >= 0) {
1742  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1743  exit();
1744  } else {
1745  dol_print_error($db);
1746  }
1747  }
1748  }
1749 
1750  // Actions to build doc
1751  $upload_dir = !empty($conf->propal->multidir_output[$object->entity]) ? $conf->propal->multidir_output[$object->entity] : $conf->propal->dir_output;
1752  $permissiontoadd = $usercancreate;
1753  include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
1754 }
1755 
1756 
1757 /*
1758  * View
1759  */
1760 
1761 $form = new Form($db);
1762 $formfile = new FormFile($db);
1763 $formpropal = new FormPropal($db);
1764 $formmargin = new FormMargin($db);
1765 if (isModEnabled('project')) {
1766  $formproject = new FormProjets($db);
1767 }
1768 
1769 $title = $object->ref." - ".$langs->trans('Card');
1770 if ($action == 'create') {
1771  $title = $langs->trans("NewPropal");
1772 }
1773 $help_url = 'EN:Commercial_Proposals|FR:Proposition_commerciale|ES:Presupuestos|DE:Modul_Angebote';
1774 
1775 llxHeader('', $title, $help_url);
1776 
1777 $now = dol_now();
1778 
1779 // Add new proposal
1780 if ($action == 'create') {
1781  $currency_code = $conf->currency;
1782 
1783  print load_fiche_titre($langs->trans("NewProp"), '', 'propal');
1784 
1785  $soc = new Societe($db);
1786  if ($socid > 0) {
1787  $res = $soc->fetch($socid);
1788  }
1789 
1790  $currency_code = $conf->currency;
1791 
1792  $cond_reglement_id = GETPOSTINT('cond_reglement_id');
1793  $deposit_percent = GETPOST('cond_reglement_id_deposit_percent', 'alpha');
1794  $mode_reglement_id = GETPOSTINT('mode_reglement_id');
1795  $fk_account = GETPOSTINT('fk_account');
1796  $datepropal = (empty($datepropal) ? (!getDolGlobalString('MAIN_AUTOFILL_DATE_PROPOSAL') ? -1 : '') : $datepropal);
1797 
1798  // Load objectsrc
1799  if (!empty($origin) && !empty($originid)) {
1800  // Parse element/subelement (ex: project_task)
1801  $element = $subelement = $origin;
1802  $regs = array();
1803  if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
1804  $element = $regs[1];
1805  $subelement = $regs[2];
1806  }
1807 
1808  if ($element == 'project') {
1809  $projectid = $originid;
1810  } else {
1811  // For compatibility
1812  if ($element == 'order' || $element == 'commande') {
1813  $element = $subelement = 'commande';
1814  }
1815  if ($element == 'propal') {
1816  $element = 'comm/propal';
1817  $subelement = 'propal';
1818  }
1819  if ($element == 'contract') {
1820  $element = $subelement = 'contrat';
1821  }
1822  if ($element == 'shipping') {
1823  $element = $subelement = 'expedition';
1824  }
1825 
1826  dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
1827 
1828  $classname = ucfirst($subelement);
1829  $objectsrc = new $classname($db);
1830  $objectsrc->fetch($originid);
1831  if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
1832  $objectsrc->fetch_lines();
1833  }
1834  $objectsrc->fetch_thirdparty();
1835 
1836  $projectid = (!empty($objectsrc->fk_project) ? $objectsrc->fk_project : 0);
1837  $ref_client = (!empty($objectsrc->ref_client) ? $objectsrc->ref_client : '');
1838 
1839  $soc = $objectsrc->thirdparty;
1840 
1841  $cond_reglement_id = (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_id) ? $soc->cond_reglement_id : 0));
1842  $mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_id) ? $soc->mode_reglement_id : 0));
1843  $warehouse_id = (!empty($objectsrc->warehouse_id) ? $objectsrc->warehouse_id : (!empty($soc->warehouse_id) ? $soc->warehouse_id : 0));
1844 
1845  // Replicate extrafields
1846  $objectsrc->fetch_optionals();
1847  $object->array_options = $objectsrc->array_options;
1848 
1849  if (isModEnabled("multicurrency")) {
1850  if (!empty($objectsrc->multicurrency_code)) {
1851  $currency_code = $objectsrc->multicurrency_code;
1852  }
1853  if (getDolGlobalString('MULTICURRENCY_USE_ORIGIN_TX') && !empty($objectsrc->multicurrency_tx)) {
1854  $currency_tx = $objectsrc->multicurrency_tx;
1855  }
1856  }
1857  }
1858  } else {
1859  $cond_reglement_id = empty($soc->cond_reglement_id) ? $cond_reglement_id : $soc->cond_reglement_id;
1860  $deposit_percent = empty($soc->deposit_percent) ? $deposit_percent : $soc->deposit_percent;
1861  $mode_reglement_id = empty($soc->mode_reglement_id) ? $mode_reglement_id : $soc->mode_reglement_id;
1862  $fk_account = empty($soc->fk_account) ? $fk_account : $soc->fk_account;
1863  $shipping_method_id = $soc->shipping_method_id;
1864  $warehouse_id = $soc->fk_warehouse;
1865  $remise_percent = $soc->remise_percent;
1866 
1867  if (isModEnabled("multicurrency") && !empty($soc->multicurrency_code)) {
1868  $currency_code = $soc->multicurrency_code;
1869  }
1870  }
1871 
1872  // If form was posted (but error returned), we must reuse the value posted in priority (standard Dolibarr behaviour)
1873  if (!GETPOST('changecompany')) {
1874  if (GETPOSTISSET('cond_reglement_id')) {
1875  $cond_reglement_id = GETPOSTINT('cond_reglement_id');
1876  }
1877  if (GETPOSTISSET('deposit_percent')) {
1878  $deposit_percent = price2num(GETPOST('deposit_percent', 'alpha'));
1879  }
1880  if (GETPOSTISSET('mode_reglement_id')) {
1881  $mode_reglement_id = GETPOSTINT('mode_reglement_id');
1882  }
1883  if (GETPOSTISSET('cond_reglement_id')) {
1884  $fk_account = GETPOSTINT('fk_account');
1885  }
1886  }
1887 
1888  // Warehouse default if null
1889  if ($soc->fk_warehouse > 0) {
1890  $warehouse_id = $soc->fk_warehouse;
1891  }
1892  if (isModEnabled('stock') && empty($warehouse_id) && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER')) {
1893  if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE')) {
1894  $warehouse_id = getDolGlobalString('MAIN_DEFAULT_WAREHOUSE');
1895  }
1896  if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER')) {
1897  $warehouse_id = $user->fk_warehouse;
1898  }
1899  }
1900 
1901  print '<form name="addprop" action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1902  print '<input type="hidden" name="token" value="'.newToken().'">';
1903  print '<input type="hidden" name="action" value="add">';
1904  print '<input type="hidden" name="changecompany" value="0">'; // will be set to 1 by javascript so we know post is done after a company change
1905  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1906  if ($origin != 'project' && $originid) {
1907  print '<input type="hidden" name="origin" value="'.$origin.'">';
1908  print '<input type="hidden" name="originid" value="'.$originid.'">';
1909  } elseif ($origin == 'project' && !empty($projectid)) {
1910  print '<input type="hidden" name="projectid" value="'.$projectid.'">';
1911  }
1912 
1913  print dol_get_fiche_head();
1914 
1915  // Call Hook tabContentCreateProposal
1916  $parameters = array();
1917  // Note that $action and $object may be modified by hook
1918  $reshook = $hookmanager->executeHooks('tabContentCreateProposal', $parameters, $object, $action);
1919  if (empty($reshook)) {
1920  print '<table class="border centpercent">';
1921 
1922  // Reference
1923  print '<tr class="field_ref"><td class="titlefieldcreate fieldrequired">'.$langs->trans('Ref').'</td><td class="valuefieldcreate">'.$langs->trans("Draft").'</td></tr>';
1924 
1925  // Ref customer
1926  print '<tr class="field_ref_client"><td class="titlefieldcreate">'.$langs->trans('RefCustomer').'</td><td class="valuefieldcreate">';
1927  print '<input type="text" name="ref_client" value="'.(!empty($ref_client) ? $ref_client : GETPOST('ref_client')).'"></td>';
1928  print '</tr>';
1929 
1930  // Third party
1931  print '<tr class="field_socid">';
1932  print '<td class="titlefieldcreate fieldrequired">'.$langs->trans('Customer').'</td>';
1933  $shipping_method_id = 0;
1934  if ($socid > 0) {
1935  print '<td class="valuefieldcreate">';
1936  print $soc->getNomUrl(1, 'customer');
1937  print '<input type="hidden" name="socid" value="'.$soc->id.'">';
1938  print '</td>';
1939  if (getDolGlobalString('SOCIETE_ASK_FOR_SHIPPING_METHOD') && !empty($soc->shipping_method_id)) {
1940  $shipping_method_id = $soc->shipping_method_id;
1941  }
1942  //$warehouse_id = $soc->warehouse_id;
1943  } else {
1944  print '<td class="valuefieldcreate">';
1945  $filter = '((s.client:IN:1,2,3) AND (s.status:=:1))';
1946  print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', $filter, 'SelectThirdParty', 1, 0, null, 0, 'minwidth300 maxwidth500 widthcentpercentminusxx');
1947  // reload page to retrieve customer information
1948  if (!getDolGlobalString('RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED')) {
1949  print '<script>
1950  $(document).ready(function() {
1951  $("#socid").change(function() {
1952  console.log("We have changed the company - Reload page");
1953  var socid = $(this).val();
1954  // reload page
1955  $("input[name=action]").val("create");
1956  $("input[name=changecompany]").val("1");
1957  $("form[name=addprop]").submit();
1958  });
1959  });
1960  </script>';
1961  }
1962  print ' <a href="'.DOL_URL_ROOT.'/societe/card.php?action=create&client=3&fournisseur=0&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create').'"><span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("AddThirdParty").'"></span></a>';
1963  print '</td>';
1964  }
1965  print '</tr>'."\n";
1966 
1967  if ($socid > 0) {
1968  // Contacts (ask contact only if thirdparty already defined).
1969  print '<tr class="field_contactid"><td class="titlefieldcreate">'.$langs->trans("DefaultContact").'</td><td class="valuefieldcreate">';
1970  print img_picto('', 'contact', 'class="pictofixedwidth"');
1971  //print $form->selectcontacts($soc->id, $contactid, 'contactid', 1, '', '', 0, 'minwidth300 widthcentpercentminusx');
1972  print $form->select_contact($soc->id, $contactid, 'contactid', 1, '', '', 1, 'maxwidth300 widthcentpercentminusx', true);
1973  print '</td></tr>';
1974 
1975  // Third party discounts info line
1976  print '<tr class="field_discount_info"><td class="titlefieldcreate">'.$langs->trans('Discounts').'</td><td class="valuefieldcreate">';
1977 
1978  $absolute_discount = $soc->getAvailableDiscounts();
1979 
1980  $thirdparty = $soc;
1981  $discount_type = 0;
1982  $backtopage = $_SERVER["PHP_SELF"].'?socid='.$thirdparty->id.'&action='.$action.'&origin='.urlencode((string) (GETPOST('origin'))).'&originid='.urlencode((string) (GETPOSTINT('originid')));
1983  include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
1984  print '</td></tr>';
1985  }
1986 
1987  $newdatepropal = dol_mktime(0, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'), 'tzserver');
1988  // Date
1989  print '<tr class="field_addprop"><td class="titlefieldcreate fieldrequired">'.$langs->trans('DatePropal').'</td><td class="valuefieldcreate">';
1990  print img_picto('', 'action', 'class="pictofixedwidth"');
1991  print $form->selectDate($newdatepropal ? $newdatepropal : $datepropal, '', 0, 0, 0, "addprop", 1, 1);
1992  print '</td></tr>';
1993 
1994  // Validaty duration
1995  print '<tr class="field_duree_validitee"><td class="titlefieldcreate fieldrequired">'.$langs->trans("ValidityDuration").'</td><td class="valuefieldcreate">'.img_picto('', 'clock', 'class="pictofixedwidth"').'<input name="duree_validite" class="width50" value="'.(GETPOSTISSET('duree_validite') ? GETPOST('duree_validite', 'alphanohtml') : $conf->global->PROPALE_VALIDITY_DURATION).'"> '.$langs->trans("days").'</td></tr>';
1996 
1997  // Terms of payment
1998  print '<tr class="field_cond_reglement_id"><td class="nowrap">'.$langs->trans('PaymentConditionsShort').'</td><td>';
1999  print img_picto('', 'payment', 'class="pictofixedwidth"');
2000  // at last resort we take the payment term id which may be filled by default values set (if not getpostisset)
2001  print $form->getSelectConditionsPaiements($cond_reglement_id, 'cond_reglement_id', 1, 1, 0, '', $deposit_percent);
2002  print '</td></tr>';
2003 
2004  // Mode of payment
2005  print '<tr class="field_mode_reglement_id"><td class="titlefieldcreate">'.$langs->trans('PaymentMode').'</td><td class="valuefieldcreate">';
2006  print img_picto('', 'bank', 'class="pictofixedwidth"');
2007  print $form->select_types_paiements($mode_reglement_id, 'mode_reglement_id', 'CRDT', 0, 1, 0, 0, 1, 'maxwidth200 widthcentpercentminusx', 1);
2008  print '</td></tr>';
2009 
2010  // Bank Account
2011  if (getDolGlobalString('BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL') && isModEnabled("bank")) {
2012  print '<tr class="field_fk_account"><td class="titlefieldcreate">'.$langs->trans('BankAccount').'</td><td class="valuefieldcreate">';
2013  print img_picto('', 'bank_account', 'class="pictofixedwidth"').$form->select_comptes($fk_account, 'fk_account', 0, '', 1, '', 0, 'maxwidth200 widthcentpercentminusx', 1);
2014  print '</td></tr>';
2015  }
2016 
2017  // Source / Channel - What trigger creation
2018  print '<tr class="field_demand_reason_id"><td class="titlefieldcreate">'.$langs->trans('Source').'</td><td class="valuefieldcreate">';
2019  print img_picto('', 'question', 'class="pictofixedwidth"');
2020  $form->selectInputReason((GETPOSTISSET('demand_reason_id') ? GETPOSTINT('demand_reason_id') : ''), 'demand_reason_id', "SRC_PROP", 1, 'maxwidth200 widthcentpercentminusx');
2021  print '</td></tr>';
2022 
2023  // Shipping Method
2024  if (isModEnabled("shipping")) {
2025  if (getDolGlobalString('SOCIETE_ASK_FOR_SHIPPING_METHOD') && !empty($soc->shipping_method_id)) {
2026  $shipping_method_id = $soc->shipping_method_id;
2027  }
2028  print '<tr class="field_shipping_method_id"><td class="titlefieldcreate">'.$langs->trans('SendingMethod').'</td><td class="valuefieldcreate">';
2029  print img_picto('', 'dolly', 'class="pictofixedwidth"');
2030  $form->selectShippingMethod((GETPOSTISSET('shipping_method_id') ? GETPOSTINT('shipping_method_id') : $shipping_method_id), 'shipping_method_id', '', 1, '', 0, 'maxwidth200 widthcentpercentminusx');
2031  print '</td></tr>';
2032  }
2033 
2034  // Warehouse
2035  if (isModEnabled('stock') && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL')) {
2036  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2037  $formproduct = new FormProduct($db);
2038  print '<tr class="field_warehouse_id"><td class="titlefieldcreate">'.$langs->trans('Warehouse').'</td><td class="valuefieldcreate">';
2039  print img_picto('', 'stock', 'class="pictofixedwidth"').$formproduct->selectWarehouses($warehouse_id, 'warehouse_id', '', 1, 0, 0, '', 0, 0, array(), 'maxwidth500 widthcentpercentminusxx');
2040  print '</td></tr>';
2041  }
2042 
2043  // Delivery delay
2044  print '<tr class="field_availability_id"><td class="titlefieldcreate">'.$langs->trans('AvailabilityPeriod');
2045  if (isModEnabled('order')) {
2046  print ' ('.$langs->trans('AfterOrder').')';
2047  }
2048  print '</td><td class="valuefieldcreate">';
2049  print img_picto('', 'clock', 'class="pictofixedwidth"');
2050  $form->selectAvailabilityDelay((GETPOSTISSET('availability_id') ? GETPOSTINT('availability_id') : ''), 'availability_id', '', 1, 'maxwidth200 widthcentpercentminusx');
2051  print '</td></tr>';
2052 
2053  // Delivery date (or manufacturing)
2054  print '<tr class="field_date_livraison"><td class="titlefieldcreate">'.$langs->trans("DeliveryDate").'</td>';
2055  print '<td class="valuefieldcreate">';
2056  print img_picto('', 'action', 'class="pictofixedwidth"');
2057  if (is_numeric(getDolGlobalString('DATE_LIVRAISON_WEEK_DELAY'))) { // If value set to 0 or a num, not empty
2058  $tmpdte = time() + (7 * getDolGlobalInt('DATE_LIVRAISON_WEEK_DELAY') * 24 * 60 * 60);
2059  $syear = date("Y", $tmpdte);
2060  $smonth = date("m", $tmpdte);
2061  $sday = date("d", $tmpdte);
2062  print $form->selectDate($syear."-".$smonth."-".$sday, 'date_livraison', 0, 0, 0, "addprop");
2063  } else {
2064  print $form->selectDate(-1, 'date_livraison', 0, 0, 0, "addprop", 1, 1);
2065  }
2066  print '</td></tr>';
2067 
2068  // Project
2069  if (isModEnabled('project')) {
2070  $langs->load("projects");
2071  print '<tr class="field_projectid">';
2072  print '<td class="titlefieldcreate">'.$langs->trans("Project").'</td><td class="valuefieldcreate">';
2073  print img_picto('', 'project', 'class="pictofixedwidth"').$formproject->select_projects(($soc->id > 0 ? $soc->id : -1), $projectid, 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500 widthcentpercentminusxx');
2074  print ' <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 paddingleft" title="'.$langs->trans("AddProject").'"></span></a>';
2075  print '</td>';
2076  print '</tr>';
2077  }
2078 
2079  // Incoterms
2080  if (isModEnabled('incoterm')) {
2081  print '<tr class="field_incoterm_id">';
2082  print '<td class="titlefieldcreate"><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $soc->label_incoterms, 1).'</label></td>';
2083  print '<td class="valuefieldcreate maxwidthonsmartphone">';
2084  print img_picto('', 'incoterm', 'class="pictofixedwidth"');
2085  print $form->select_incoterms((!empty($soc->fk_incoterms) ? $soc->fk_incoterms : ''), (!empty($soc->location_incoterms) ? $soc->location_incoterms : ''));
2086  print '</td></tr>';
2087  }
2088 
2089  // Template to use by default
2090  print '<tr class="field_model">';
2091  print '<td class="titlefieldcreate">'.$langs->trans("DefaultModel").'</td>';
2092  print '<td class="valuefieldcreate">';
2093  print img_picto('', 'pdf', 'class="pictofixedwidth"');
2094  $liste = ModelePDFPropales::liste_modeles($db);
2095  $preselected = (getDolGlobalString('PROPALE_ADDON_PDF_ODT_DEFAULT') ? $conf->global->PROPALE_ADDON_PDF_ODT_DEFAULT : getDolGlobalString("PROPALE_ADDON_PDF"));
2096  print $form->selectarray('model', $liste, $preselected, 0, 0, 0, '', 0, 0, 0, '', 'maxwidth200 widthcentpercentminusx', 1);
2097  print "</td></tr>";
2098 
2099  // Multicurrency
2100  if (isModEnabled("multicurrency")) {
2101  print '<tr class="field_currency">';
2102  print '<td class="titlefieldcreate">'.$form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0).'</td>';
2103  print '<td class="valuefieldcreate maxwidthonsmartphone">';
2104  print img_picto('', 'currency', 'class="pictofixedwidth"').$form->selectMultiCurrency(((GETPOSTISSET('multicurrency_code') && !GETPOST('changecompany')) ? GETPOST('multicurrency_code') : $currency_code), 'multicurrency_code', 0);
2105  print '</td></tr>';
2106  }
2107 
2108  // Public note
2109  print '<tr class="field_note_public">';
2110  print '<td class="titlefieldcreate tdtop">'.$langs->trans('NotePublic').'</td>';
2111  print '<td class="valuefieldcreate">';
2112  $note_public = $object->getDefaultCreateValueFor('note_public', (!empty($objectsrc) ? $objectsrc->note_public : (getDolGlobalString('PROPALE_ADDON_NOTE_PUBLIC_DEFAULT') ? $conf->global->PROPALE_ADDON_NOTE_PUBLIC_DEFAULT : null)), 'restricthtml');
2113  $doleditor = new DolEditor('note_public', $note_public, '', 80, 'dolibarr_notes', 'In', 0, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
2114  print $doleditor->Create(1);
2115 
2116  // Private note
2117  if (empty($user->socid)) {
2118  print '<tr class="field_note_private">';
2119  print '<td class="titlefieldcreate tdtop">'.$langs->trans('NotePrivate').'</td>';
2120  print '<td class="valuefieldcreate">';
2121  $note_private = $object->getDefaultCreateValueFor('note_private', ((!empty($origin) && !empty($originid) && is_object($objectsrc)) ? $objectsrc->note_private : null));
2122  $doleditor = new DolEditor('note_private', $note_private, '', 80, 'dolibarr_notes', 'In', 0, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
2123  print $doleditor->Create(1);
2124  // print '<textarea name="note_private" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'.</textarea>
2125  print '</td></tr>';
2126  }
2127 
2128  // Other attributes
2129  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php';
2130 
2131  // Lines from source
2132  if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
2133  // TODO for compatibility
2134  if ($origin == 'contrat') {
2135  // Calcul contrat->price (HT), contrat->total (TTC), contrat->tva
2136  //$objectsrc->remise_absolue = $remise_absolue; // deprecated
2137  //$objectsrc->remise_percent = $remise_percent;
2138  $objectsrc->update_price(1, 'auto', 1);
2139  }
2140 
2141  print "\n<!-- ".$classname." info -->";
2142  print "\n";
2143  print '<input type="hidden" name="amount" value="'.$objectsrc->total_ht.'">'."\n";
2144  print '<input type="hidden" name="total" value="'.$objectsrc->total_ttc.'">'."\n";
2145  print '<input type="hidden" name="tva" value="'.$objectsrc->total_tva.'">'."\n";
2146  print '<input type="hidden" name="origin" value="'.$objectsrc->element.'">';
2147  print '<input type="hidden" name="originid" value="'.$objectsrc->id.'">';
2148 
2149  $newclassname = $classname;
2150  if ($newclassname == 'Propal') {
2151  $newclassname = 'CommercialProposal';
2152  } elseif ($newclassname == 'Commande') {
2153  $newclassname = 'Order';
2154  } elseif ($newclassname == 'Expedition') {
2155  $newclassname = 'Sending';
2156  } elseif ($newclassname == 'Fichinter') {
2157  $newclassname = 'Intervention';
2158  }
2159 
2160  print '<tr><td>'.$langs->trans($newclassname).'</td><td>'.$objectsrc->getNomUrl(1).'</td></tr>';
2161  print '<tr><td>'.$langs->trans('AmountHT').'</td><td>'.price($objectsrc->total_ht, 0, $langs, 1, -1, -1, $conf->currency).'</td></tr>';
2162  print '<tr><td>'.$langs->trans('AmountVAT').'</td><td>'.price($objectsrc->total_tva, 0, $langs, 1, -1, -1, $conf->currency)."</td></tr>";
2163  if ($mysoc->localtax1_assuj == "1" || $objectsrc->total_localtax1 != 0) { // Localtax1
2164  print '<tr><td>'.$langs->transcountry("AmountLT1", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax1, 0, $langs, 1, -1, -1, $conf->currency)."</td></tr>";
2165  }
2166 
2167  if ($mysoc->localtax2_assuj == "1" || $objectsrc->total_localtax2 != 0) { // Localtax2
2168  print '<tr><td>'.$langs->transcountry("AmountLT2", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax2, 0, $langs, 1, -1, -1, $conf->currency)."</td></tr>";
2169  }
2170  print '<tr><td>'.$langs->trans('AmountTTC').'</td><td>'.price($objectsrc->total_ttc, 0, $langs, 1, -1, -1, $conf->currency)."</td></tr>";
2171 
2172  if (isModEnabled("multicurrency")) {
2173  print '<tr><td>'.$langs->trans('MulticurrencyAmountHT').'</td><td>'.price($objectsrc->multicurrency_total_ht).'</td></tr>';
2174  print '<tr><td>'.$langs->trans('MulticurrencyAmountVAT').'</td><td>'.price($objectsrc->multicurrency_total_tva)."</td></tr>";
2175  print '<tr><td>'.$langs->trans('MulticurrencyAmountTTC').'</td><td>'.price($objectsrc->multicurrency_total_ttc)."</td></tr>";
2176  }
2177  }
2178 
2179  print "</table>\n";
2180 
2181 
2182  /*
2183  * Combobox for copy function
2184  */
2185 
2186  if (!getDolGlobalString('PROPAL_CLONE_ON_CREATE_PAGE')) {
2187  print '<input type="hidden" name="createmode" value="empty">';
2188  }
2189 
2190  if (getDolGlobalString('PROPAL_CLONE_ON_CREATE_PAGE')) {
2191  print '<br><table>';
2192 
2193  // For backward compatibility
2194  print '<tr>';
2195  print '<td><input type="radio" name="createmode" value="copy"></td>';
2196  print '<td>'.$langs->trans("CopyPropalFrom").' </td>';
2197  print '<td>';
2198  $liste_propal = array();
2199  $liste_propal [0] = '';
2200 
2201  $sql = "SELECT p.rowid as id, p.ref, s.nom";
2202  $sql .= " FROM ".MAIN_DB_PREFIX."propal p";
2203  $sql .= ", ".MAIN_DB_PREFIX."societe s";
2204  $sql .= " WHERE s.rowid = p.fk_soc";
2205  $sql .= " AND p.entity IN (".getEntity('propal').")";
2206  $sql .= " AND p.fk_statut <> 0";
2207  $sql .= " ORDER BY Id";
2208 
2209  $resql = $db->query($sql);
2210  if ($resql) {
2211  $num = $db->num_rows($resql);
2212  $i = 0;
2213  while ($i < $num) {
2214  $row = $db->fetch_row($resql);
2215  $propalRefAndSocName = $row[1]." - ".$row[2];
2216  $liste_propal[$row[0]] = $propalRefAndSocName;
2217  $i++;
2218  }
2219  print $form->selectarray("copie_propal", $liste_propal, 0);
2220  } else {
2221  dol_print_error($db);
2222  }
2223  print '</td></tr>';
2224 
2225  print '<tr><td class="tdtop"><input type="radio" name="createmode" value="empty" checked></td>';
2226  print '<td valign="top" colspan="2">'.$langs->trans("CreateEmptyPropal").'</td></tr>';
2227  print '</table>';
2228  }
2229  }
2230 
2231  print dol_get_fiche_end();
2232 
2233  $langs->load("bills");
2234 
2235  print $form->buttonsSaveCancel("CreateDraft");
2236 
2237  print "</form>";
2238 
2239 
2240  // Show origin lines
2241  if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
2242  print '<br>';
2243 
2244  $title = $langs->trans('ProductsAndServices');
2245  print load_fiche_titre($title);
2246 
2247  print '<div class="div-table-responsive-no-min">';
2248  print '<table class="noborder centpercent">';
2249 
2250  $objectsrc->printOriginLinesList();
2251 
2252  print '</table>';
2253  print '</div>';
2254  }
2255 } elseif ($object->id > 0) {
2256  /*
2257  * Show object in view mode
2258  */
2259  $object->fetch_thirdparty();
2260  if ($object->thirdparty) {
2261  $soc = $object->thirdparty;
2262  } else {
2263  $soc = new Societe($db);
2264  }
2265 
2266  $head = propal_prepare_head($object);
2267  print dol_get_fiche_head($head, 'comm', $langs->trans('Proposal'), -1, 'propal');
2268 
2269  $formconfirm = '';
2270 
2271  // Clone confirmation
2272  if ($action == 'clone') {
2273  // Create an array for form
2274  $filter = '(s.client:IN:1,2,3)';
2275  $formquestion = array(
2276  // 'text' => $langs->trans("ConfirmClone"),
2277  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2278  array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOSTINT('socid'), 'socid', $filter, '', 0, 0, null, 0, 'maxwidth300')),
2279  array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans('PuttingPricesUpToDate'), 'value' => 0),
2280  array('type' => 'checkbox', 'name' => 'update_desc', 'label' => $langs->trans('PuttingDescUpToDate'), 'value' => 0),
2281  );
2282  if (getDolGlobalString('PROPAL_CLONE_DATE_DELIVERY') && !empty($object->delivery_date)) {
2283  $formquestion[] = array('type' => 'date', 'name' => 'date_delivery', 'label' => $langs->trans("DeliveryDate"), 'value' => $object->delivery_date);
2284  }
2285  // Incomplete payment. We ask if reason = discount or other
2286  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmClonePropal', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
2287  }
2288 
2289  if ($action == 'closeas') {
2290  //Form to close proposal (signed or not)
2291  $formquestion = array();
2292  if (!getDolGlobalString('PROPAL_SKIP_ACCEPT_REFUSE')) {
2293  $formquestion[] = array('type' => 'select', 'name' => 'statut', 'label' => '<span class="fieldrequired">'.$langs->trans("CloseAs").'</span>', 'values' => array($object::STATUS_SIGNED => $object->LibStatut($object::STATUS_SIGNED), $object::STATUS_NOTSIGNED => $object->LibStatut($object::STATUS_NOTSIGNED)));
2294  }
2295  $formquestion[] = array('type' => 'text', 'name' => 'note_private', 'label' => $langs->trans("Note"), 'value' => ''); // Field to complete private note (not replace)
2296 
2297  if (getDolGlobalInt('PROPOSAL_SUGGEST_DOWN_PAYMENT_INVOICE_CREATION')) {
2298  // This is a hidden option:
2299  // Suggestion to create invoice during proposal signature is not enabled by default.
2300  // Such choice should be managed by the workflow module and trigger. This option generates conflicts with some setup.
2301  // It may also break step of creating an order when invoicing must be done from orders and not from proposal
2302  $deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
2303 
2304  if (!empty($deposit_percent_from_payment_terms) && isModEnabled('invoice') && $user->hasRight('facture', 'creer')) {
2305  require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
2306 
2307  $object->fetchObjectLinked();
2308 
2309  $eligibleForDepositGeneration = true;
2310 
2311  if (array_key_exists('facture', $object->linkedObjects)) {
2312  foreach ($object->linkedObjects['facture'] as $invoice) {
2313  if ($invoice->type == Facture::TYPE_DEPOSIT) {
2314  $eligibleForDepositGeneration = false;
2315  break;
2316  }
2317  }
2318  }
2319 
2320  if ($eligibleForDepositGeneration && array_key_exists('commande', $object->linkedObjects)) {
2321  foreach ($object->linkedObjects['commande'] as $order) {
2322  $order->fetchObjectLinked();
2323 
2324  if (array_key_exists('facture', $order->linkedObjects)) {
2325  foreach ($order->linkedObjects['facture'] as $invoice) {
2326  if ($invoice->type == Facture::TYPE_DEPOSIT) {
2327  $eligibleForDepositGeneration = false;
2328  break 2;
2329  }
2330  }
2331  }
2332  }
2333  }
2334 
2335 
2336  if ($eligibleForDepositGeneration) {
2337  $formquestion[] = array(
2338  'type' => 'checkbox',
2339  'tdclass' => 'showonlyifsigned',
2340  'name' => 'generate_deposit',
2341  'morecss' => 'margintoponly marginbottomonly',
2342  'label' => $form->textwithpicto($langs->trans('GenerateDeposit', $object->deposit_percent), $langs->trans('DepositGenerationPermittedByThePaymentTermsSelected'))
2343  );
2344 
2345  $formquestion[] = array(
2346  'type' => 'date',
2347  'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2348  'name' => 'datef',
2349  'label' => $langs->trans('DateInvoice'),
2350  'value' => dol_now(),
2351  'datenow' => true
2352  );
2353 
2354  if (getDolGlobalString('INVOICE_POINTOFTAX_DATE')) {
2355  $formquestion[] = array(
2356  'type' => 'date',
2357  'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2358  'name' => 'date_pointoftax',
2359  'label' => $langs->trans('DatePointOfTax'),
2360  'value' => dol_now(),
2361  'datenow' => true
2362  );
2363  }
2364 
2365  $paymentTermsSelect = $form->getSelectConditionsPaiements(0, 'cond_reglement_id', -1, 0, 1, 'minwidth200');
2366 
2367  $formquestion[] = array(
2368  'type' => 'other',
2369  'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2370  'name' => 'cond_reglement_id',
2371  'label' => $langs->trans('PaymentTerm'),
2372  'value' => $paymentTermsSelect
2373  );
2374 
2375  $formquestion[] = array(
2376  'type' => 'checkbox',
2377  'tdclass' => 'showonlyifgeneratedeposit',
2378  'name' => 'validate_generated_deposit',
2379  'morecss' => 'margintoponly marginbottomonly',
2380  'label' => $langs->trans('ValidateGeneratedDeposit')
2381  );
2382 
2383  $formquestion[] = array(
2384  'type' => 'onecolumn',
2385  'value' => '
2386  <script>
2387  let signedValue = ' . $object::STATUS_SIGNED . ';
2388 
2389  $(document).ready(function() {
2390  $("[name=generate_deposit]").change(function () {
2391  let $self = $(this);
2392  let $target = $(".showonlyifgeneratedeposit").parent(".tagtr");
2393 
2394  if (! $self.parents(".tagtr").is(":hidden") && $self.is(":checked")) {
2395  $target.show();
2396  } else {
2397  $target.hide();
2398  }
2399 
2400  return true;
2401  });
2402 
2403  $("#statut").change(function() {
2404  let $target = $(".showonlyifsigned").parent(".tagtr");
2405 
2406  if ($(this).val() == signedValue) {
2407  $target.show();
2408  } else {
2409  $target.hide();
2410  }
2411 
2412  $("[name=generate_deposit]").trigger("change");
2413 
2414  return true;
2415  });
2416 
2417  $("#statut").trigger("change");
2418  });
2419  </script>
2420  '
2421  );
2422  }
2423  }
2424  }
2425 
2426  if (isModEnabled('notification')) {
2427  require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2428  $notify = new Notify($db);
2429  $formquestion = array_merge($formquestion, array(
2430  array('type' => 'onecolumn', 'value' => $notify->confirmMessage('PROPAL_CLOSE_SIGNED', $object->socid, $object)),
2431  ));
2432  }
2433 
2434  if (!getDolGlobalString('PROPAL_SKIP_ACCEPT_REFUSE')) {
2435  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('SetAcceptedRefused'), '', 'confirm_closeas', $formquestion, '', 1, 250);
2436  } else {
2437  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?statut=3&id=' . $object->id, $langs->trans('Close'), '', 'confirm_closeas', $formquestion, '', 1, 250);
2438  }
2439  } elseif ($action == 'cancel') {
2440  // Confirm cancel
2441  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans("CancelPropal"), $langs->trans('ConfirmCancelPropal', $object->ref), 'confirm_cancel', '', 0, 1);
2442  } elseif ($action == 'delete') {
2443  // Confirm delete
2444  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteProp'), $langs->trans('ConfirmDeleteProp', $object->ref), 'confirm_delete', '', 0, 1);
2445  } elseif ($action == 'reopen') {
2446  // Confirm reopen
2447  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ReOpen'), $langs->trans('ConfirmReOpenProp', $object->ref), 'confirm_reopen', '', 0, 1);
2448  } elseif ($action == 'ask_deleteline') {
2449  // Confirmation delete product/service line
2450  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 0, 1);
2451  } elseif ($action == 'validate') {
2452  // Confirm validate proposal
2453  $error = 0;
2454 
2455  // We verify whether the object is provisionally numbering
2456  $ref = substr($object->ref, 1, 4);
2457  if ($ref == 'PROV' || $ref == '') {
2458  $numref = $object->getNextNumRef($soc);
2459  if (empty($numref)) {
2460  $error++;
2461  setEventMessages($object->error, $object->errors, 'errors');
2462  }
2463  } else {
2464  $numref = $object->ref;
2465  }
2466 
2467  $text = $langs->trans('ConfirmValidateProp', $numref);
2468  if (isModEnabled('notification')) {
2469  require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2470  $notify = new Notify($db);
2471  $text .= '<br>';
2472  $text .= $notify->confirmMessage('PROPAL_VALIDATE', $object->socid, $object);
2473  }
2474 
2475  // mandatoryPeriod
2476  $nbMandated = 0;
2477  foreach ($object->lines as $line) {
2478  $res = $line->fetch_product();
2479  if ($res > 0) {
2480  if ($line->product->isService() && $line->product->isMandatoryPeriod() && (empty($line->date_start) || empty($line->date_end))) {
2481  $nbMandated++;
2482  break;
2483  }
2484  }
2485  }
2486  if ($nbMandated > 0) {
2487  if (getDolGlobalString('SERVICE_STRICT_MANDATORY_PERIOD')) {
2488  setEventMessages($langs->trans("mandatoryPeriodNeedTobeSetMsgValidate"), null, 'errors');
2489  $error++;
2490  } else {
2491  $text .= '<div><span class="clearboth nowraponall warning">'.img_warning().$langs->trans("mandatoryPeriodNeedTobeSetMsgValidate").'</span></div>';
2492  }
2493  }
2494 
2495  if (!$error) {
2496  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateProp'), $text, 'confirm_validate', '', 0, 1, 240);
2497  }
2498  }
2499 
2500  // Call Hook formConfirm
2501  $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
2502  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2503  if (empty($reshook)) {
2504  $formconfirm .= $hookmanager->resPrint;
2505  } elseif ($reshook > 0) {
2506  $formconfirm = $hookmanager->resPrint;
2507  }
2508 
2509  // Print form confirm
2510  print $formconfirm;
2511 
2512 
2513  // Proposal card
2514 
2515  $linkback = '<a href="'.DOL_URL_ROOT.'/comm/propal/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
2516 
2517  $morehtmlref = '<div class="refidno">';
2518  // Ref customer
2519  $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $usercancreate, 'string', '', 0, 1);
2520  $morehtmlref .= $form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $usercancreate, 'string'.(isset($conf->global->THIRDPARTY_REF_INPUT_SIZE) ? ':' . getDolGlobalString('THIRDPARTY_REF_INPUT_SIZE') : ''), '', null, null, '', 1);
2521  // Thirdparty
2522  $morehtmlref .= '<br><span class="hideonsmartphone">'.$langs->trans('ThirdParty').' : </span>'.$soc->getNomUrl(1, 'customer');
2523  if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $soc->id > 0) {
2524  $morehtmlref .= ' (<a href="'.DOL_URL_ROOT.'/comm/propal/list.php?socid='.$soc->id.'&search_societe='.urlencode($soc->name).'">'.$langs->trans("OtherProposals").'</a>)';
2525  }
2526  // Project
2527  if (isModEnabled('project')) {
2528  $langs->load("projects");
2529  $morehtmlref .= '<br>';
2530  if ($usercancreate) {
2531  $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
2532  if ($action != 'classify') {
2533  $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
2534  }
2535  $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
2536  } else {
2537  if (!empty($object->fk_project)) {
2538  $proj = new Project($db);
2539  $proj->fetch($object->fk_project);
2540  $morehtmlref .= $proj->getNomUrl(1);
2541  if ($proj->title) {
2542  $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
2543  }
2544  }
2545  }
2546  }
2547  $morehtmlref .= '</div>';
2548 
2549 
2550  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
2551 
2552  // Call Hook tabContentViewProposal
2553  $parameters = array();
2554  // Note that $action and $object may be modified by hook
2555  $reshook = $hookmanager->executeHooks('tabContentViewProposal', $parameters, $object, $action);
2556  if (empty($reshook)) {
2557  print '<div class="fichecenter">';
2558  print '<div class="fichehalfleft">';
2559  print '<div class="underbanner clearboth"></div>';
2560 
2561  print '<table class="border tableforfield centpercent">';
2562 
2563  // Link for thirdparty discounts
2564  if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
2565  $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
2566  $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
2567  } else {
2568  $filterabsolutediscount = "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')";
2569  $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')";
2570  }
2571 
2572  print '<tr><td class="titlefield">'.$langs->trans('Discounts').'</td><td>';
2573 
2574  $absolute_discount = $soc->getAvailableDiscounts('', $filterabsolutediscount);
2575  $absolute_creditnote = $soc->getAvailableDiscounts('', $filtercreditnote);
2576  $absolute_discount = price2num($absolute_discount, 'MT');
2577  $absolute_creditnote = price2num($absolute_creditnote, 'MT');
2578 
2579  $caneditfield = ($object->statut != Propal::STATUS_SIGNED && $object->statut != Propal::STATUS_BILLED);
2580 
2581  $thirdparty = $soc;
2582  $discount_type = 0;
2583  $backtopage = $_SERVER["PHP_SELF"].'?id='.$object->id;
2584  include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
2585 
2586  print '</td></tr>';
2587 
2588  // Date of proposal
2589  print '<tr>';
2590  print '<td>';
2591  // print '<table class="nobordernopadding" width="100%"><tr><td>';
2592  // print $langs->trans('DatePropal');
2593  // print '</td>';
2594  // if ($action != 'editdate' && $usercancreate && $caneditfield) {
2595  // print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editdate&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetDate'), 1).'</a></td>';
2596  // }
2597 
2598  // print '</tr></table>';
2599  $editenable = $usercancreate && $caneditfield && $object->statut == Propal::STATUS_DRAFT;
2600  print $form->editfieldkey("DatePropal", 'date', '', $object, $editenable);
2601  print '</td><td class="valuefield">';
2602  if ($action == 'editdate' && $usercancreate && $caneditfield) {
2603  print '<form name="editdate" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2604  print '<input type="hidden" name="token" value="'.newToken().'">';
2605  print '<input type="hidden" name="action" value="setdate">';
2606  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
2607  print $form->selectDate($object->date, 're', 0, 0, 0, "editdate");
2608  print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
2609  print '</form>';
2610  } else {
2611  if ($object->date) {
2612  print dol_print_date($object->date, 'day');
2613  } else {
2614  print '&nbsp;';
2615  }
2616  }
2617  print '</td>';
2618 
2619  // Date end proposal
2620  print '<tr>';
2621  print '<td>';
2622  print '<table class="nobordernopadding centpercent"><tr><td>';
2623  print $langs->trans('DateEndPropal');
2624  print '</td>';
2625  if ($action != 'editecheance' && $usercancreate && $caneditfield) {
2626  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editecheance&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetConditions'), 1).'</a></td>';
2627  }
2628  print '</tr></table>';
2629  print '</td><td class="valuefield">';
2630  if ($action == 'editecheance' && $usercancreate && $caneditfield) {
2631  print '<form name="editecheance" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2632  print '<input type="hidden" name="token" value="'.newToken().'">';
2633  print '<input type="hidden" name="action" value="setecheance">';
2634  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
2635  print $form->selectDate($object->fin_validite, 'ech', 0, 0, 0, "editecheance");
2636  print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
2637  print '</form>';
2638  } else {
2639  if (!empty($object->fin_validite)) {
2640  print dol_print_date($object->fin_validite, 'day');
2641  if ($object->statut == Propal::STATUS_VALIDATED && $object->fin_validite < ($now - $conf->propal->cloture->warning_delay)) {
2642  print img_warning($langs->trans("Late"));
2643  }
2644  } else {
2645  print '&nbsp;';
2646  }
2647  }
2648  print '</td>';
2649  print '</tr>';
2650 
2651  // Payment term
2652  print '<tr><td>';
2653  print '<table class="nobordernopadding" width="100%"><tr><td>';
2654  print $langs->trans('PaymentConditionsShort');
2655  print '</td>';
2656  if ($action != 'editconditions' && $usercancreate && $caneditfield) {
2657  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editconditions&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetConditions'), 1).'</a></td>';
2658  }
2659  print '</tr></table>';
2660  print '</td><td class="valuefield">';
2661  if ($action == 'editconditions' && $usercancreate && $caneditfield) {
2662  $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 0, '', 1, $object->deposit_percent);
2663  } else {
2664  $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none', 0, '', 1, $object->deposit_percent);
2665  }
2666  print '</td>';
2667  print '</tr>';
2668 
2669  // Payment mode
2670  print '<tr class="field_mode_reglement_id">';
2671  print '<td class="titlefieldcreate">';
2672  print '<table class="nobordernopadding centpercent"><tr><td>';
2673  print $langs->trans('PaymentMode');
2674  print '</td>';
2675  if ($action != 'editmode' && $usercancreate && $caneditfield) {
2676  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editmode&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetMode'), 1).'</a></td>';
2677  }
2678  print '</tr></table>';
2679  print '</td><td class="valuefieldcreate">';
2680  if ($action == 'editmode' && $usercancreate && $caneditfield) {
2681  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
2682  } else {
2683  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'none');
2684  }
2685  print '</td></tr>';
2686 
2687  // Delivery date
2688  $langs->load('deliveries');
2689  print '<tr><td>';
2690  print $form->editfieldkey($langs->trans('DeliveryDate'), 'date_livraison', $object->delivery_date, $object, $usercancreate && $caneditfield, 'datepicker');
2691  print '</td><td class="valuefieldedit">';
2692  print $form->editfieldval($langs->trans('DeliveryDate'), 'date_livraison', $object->delivery_date, $object, $usercancreate && $caneditfield, 'datepicker');
2693  print '</td>';
2694  print '</tr>';
2695 
2696  // Delivery delay
2697  print '<tr class="fielddeliverydelay"><td>';
2698  print '<table class="nobordernopadding" width="100%"><tr><td>';
2699  if (isModEnabled('order')) {
2700  print $form->textwithpicto($langs->trans('AvailabilityPeriod'), $langs->trans('AvailabilityPeriod').' ('.$langs->trans('AfterOrder').')');
2701  } else {
2702  print $langs->trans('AvailabilityPeriod');
2703  }
2704  print '</td>';
2705  if ($action != 'editavailability' && $usercancreate && $caneditfield) {
2706  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editavailability&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetAvailability'), 1).'</a></td>';
2707  }
2708  print '</tr></table>';
2709  print '</td><td class="valuefield">';
2710  if ($action == 'editavailability' && $usercancreate && $caneditfield) {
2711  $form->form_availability($_SERVER['PHP_SELF'].'?id='.$object->id, $object->availability_id, 'availability_id', 1);
2712  } else {
2713  $form->form_availability($_SERVER['PHP_SELF'].'?id='.$object->id, $object->availability_id, 'none', 1);
2714  }
2715 
2716  print '</td>';
2717  print '</tr>';
2718 
2719  // Shipping Method
2720  if (isModEnabled("shipping")) {
2721  print '<tr><td>';
2722  print '<table class="nobordernopadding centpercent"><tr><td>';
2723  print $langs->trans('SendingMethod');
2724  print '</td>';
2725  if ($action != 'editshippingmethod' && $usercancreate && $caneditfield) {
2726  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editshippingmethod&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetShippingMode'), 1).'</a></td>';
2727  }
2728  print '</tr></table>';
2729  print '</td><td class="valuefield">';
2730  if ($action == 'editshippingmethod' && $usercancreate && $caneditfield) {
2731  $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'shipping_method_id', 1);
2732  } else {
2733  $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'none');
2734  }
2735  print '</td>';
2736  print '</tr>';
2737  }
2738 
2739  // Warehouse
2740  if (isModEnabled('stock') && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL')) {
2741  $langs->load('stocks');
2742  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2743  $formproduct = new FormProduct($db);
2744  print '<tr class="field_warehouse_id"><td class="titlefieldcreate">';
2745  $editenable = $usercancreate;
2746  print $form->editfieldkey("Warehouse", 'warehouse', '', $object, $editenable);
2747  print '</td><td class="valuefieldcreate">';
2748  if ($action == 'editwarehouse') {
2749  $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'warehouse_id', 1);
2750  } else {
2751  $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'none');
2752  }
2753  print '</td>';
2754  print '</tr>';
2755  }
2756 
2757  // Origin of demand
2758  print '<tr><td>';
2759  print '<table class="nobordernopadding centpercent"><tr><td>';
2760  print $langs->trans('Source');
2761  print '</td>';
2762  if ($action != 'editdemandreason' && $usercancreate) {
2763  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editdemandreason&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetDemandReason'), 1).'</a></td>';
2764  }
2765  print '</tr></table>';
2766  print '</td><td class="valuefield">';
2767  if ($action == 'editdemandreason' && $usercancreate) {
2768  $form->formInputReason($_SERVER['PHP_SELF'].'?id='.$object->id, $object->demand_reason_id, 'demand_reason_id', 1);
2769  } else {
2770  $form->formInputReason($_SERVER['PHP_SELF'].'?id='.$object->id, $object->demand_reason_id, 'none');
2771  }
2772  print '</td>';
2773  print '</tr>';
2774 
2775  // Multicurrency
2776  if (isModEnabled("multicurrency")) {
2777  // Multicurrency code
2778  print '<tr>';
2779  print '<td>';
2780  print '<table class="nobordernopadding" width="100%"><tr><td>';
2781  print $form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0);
2782  print '</td>';
2783  if ($action != 'editmulticurrencycode' && $object->statut == $object::STATUS_DRAFT && $usercancreate) {
2784  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editmulticurrencycode&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1).'</a></td>';
2785  }
2786  print '</tr></table>';
2787  print '</td><td class="valuefield">';
2788  if ($object->statut == $object::STATUS_DRAFT && $action == 'editmulticurrencycode' && $usercancreate) {
2789  $form->form_multicurrency_code($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_code, 'multicurrency_code');
2790  } else {
2791  $form->form_multicurrency_code($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_code, 'none');
2792  }
2793  print '</td></tr>';
2794 
2795  // Multicurrency rate
2796  if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) {
2797  print '<tr>';
2798  print '<td>';
2799  print '<table class="nobordernopadding" width="100%"><tr>';
2800  print '<td>';
2801  print $form->editfieldkey('CurrencyRate', 'multicurrency_tx', '', $object, 0);
2802  print '</td>';
2803  if ($action != 'editmulticurrencyrate' && $object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency && $usercancreate) {
2804  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editmulticurrencyrate&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1).'</a></td>';
2805  }
2806  print '</tr></table>';
2807  print '</td><td class="valuefield">';
2808  if ($object->statut == $object::STATUS_DRAFT && ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') && $usercancreate) {
2809  if ($action == 'actualizemulticurrencyrate') {
2810  list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
2811  }
2812  $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, 'multicurrency_tx', $object->multicurrency_code);
2813  } else {
2814  $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
2815  if ($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
2816  print '<div class="inline-block"> &nbsp; &nbsp; &nbsp; &nbsp; ';
2817  print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=actualizemulticurrencyrate">'.$langs->trans("ActualizeCurrency").'</a>';
2818  print '</div>';
2819  }
2820  }
2821  print '</td></tr>';
2822  }
2823  }
2824 
2825  if ($soc->outstanding_limit) {
2826  // Outstanding Bill
2827  print '<tr><td>';
2828  print $langs->trans('OutstandingBill');
2829  print '</td><td class="valuefield">';
2830  $arrayoutstandingbills = $soc->getOutstandingBills();
2831  print($arrayoutstandingbills['opened'] > $soc->outstanding_limit ? img_warning() : '');
2832  print price($arrayoutstandingbills['opened']).' / ';
2833  print price($soc->outstanding_limit, 0, $langs, 1, - 1, - 1, $conf->currency);
2834  print '</td>';
2835  print '</tr>';
2836  }
2837 
2838  if (getDolGlobalString('BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL') && isModEnabled("bank")) {
2839  // Bank Account
2840  print '<tr><td>';
2841  print '<table width="100%" class="nobordernopadding"><tr><td>';
2842  print $langs->trans('BankAccount');
2843  print '</td>';
2844  if ($action != 'editbankaccount' && $usercancreate) {
2845  print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editbankaccount&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetBankAccount'), 1).'</a></td>';
2846  }
2847  print '</tr></table>';
2848  print '</td><td class="valuefield">';
2849  if ($action == 'editbankaccount') {
2850  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1);
2851  } else {
2852  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
2853  }
2854  print '</td>';
2855  print '</tr>';
2856  }
2857 
2858  $tmparray = $object->getTotalWeightVolume();
2859  $totalWeight = isset($tmparray['weight']) ? $tmparray['weight'] : 0;
2860  $totalVolume = isset($tmparray['volume']) ? $tmparray['volume'] : 0;
2861  if ($totalWeight) {
2862  print '<tr><td>'.$langs->trans("CalculatedWeight").'</td>';
2863  print '<td class="valuefield">';
2864  print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND) ? $conf->global->MAIN_WEIGHT_DEFAULT_ROUND : -1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT) ? $conf->global->MAIN_WEIGHT_DEFAULT_UNIT : 'no', 0);
2865  print '</td></tr>';
2866  }
2867  if ($totalVolume) {
2868  print '<tr><td>'.$langs->trans("CalculatedVolume").'</td>';
2869  print '<td class="valuefield">';
2870  print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND) ? $conf->global->MAIN_VOLUME_DEFAULT_ROUND : -1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT) ? $conf->global->MAIN_VOLUME_DEFAULT_UNIT : 'no', 0);
2871  print '</td></tr>';
2872  }
2873 
2874  // Incoterms
2875  if (isModEnabled('incoterm')) {
2876  print '<tr><td>';
2877  print '<table width="100%" class="nobordernopadding"><tr><td>';
2878  print $langs->trans('IncotermLabel');
2879  print '<td><td class="right">';
2880  if ($action != 'editincoterm' && $usercancreate && $caneditfield) {
2881  print '<a class="editfielda" href="'.DOL_URL_ROOT.'/comm/propal/card.php?id='.$object->id.'&action=editincoterm&token='.newToken().'">'.img_edit().'</a>';
2882  } else {
2883  print '&nbsp;';
2884  }
2885  print '</td></tr></table>';
2886  print '</td>';
2887  print '<td class="valuefield">';
2888  if ($action == 'editincoterm' && $usercancreate && $caneditfield) {
2889  print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
2890  } else {
2891  print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
2892  }
2893  print '</td></tr>';
2894  }
2895 
2896  // Other attributes
2897  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
2898 
2899  print '</table>';
2900 
2901  print '</div>';
2902  print '<div class="fichehalfright">';
2903  print '<div class="underbanner clearboth"></div>';
2904 
2905  print '<table class="border tableforfield centpercent">';
2906 
2907  print '<tr>';
2908  print '<td class="titlefieldmiddle">' . $langs->trans('AmountHT') . '</td>';
2909  print '<td class="nowrap amountcard right">' . price($object->total_ht, 0, $langs, 1, -1, -1, $conf->currency) . '</td>';
2910  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2911  print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ht, 0, $langs, 1, -1, -1, $object->multicurrency_code) . '</td>';
2912  }
2913  print '</tr>';
2914 
2915  print '<tr>';
2916  print '<td class="titlefieldmiddle">' . $langs->trans('AmountVAT') . '</td>';
2917  print '<td class="nowrap amountcard right">' . price($object->total_tva, 0, $langs, 1, -1, -1, $conf->currency) . '</td>';
2918  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2919  print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_tva, 0, $langs, 1, -1, -1, $object->multicurrency_code) . '</td>';
2920  }
2921  print '</tr>';
2922 
2923  if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) {
2924  print '<tr>';
2925  print '<td class="titlefieldmiddle">' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
2926  print '<td class="nowrap amountcard right">' . price($object->total_localtax1, 0, $langs, 1, -1, -1, $conf->currency) . '</td>';
2927  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2928  $object->multicurrency_total_localtax1 = price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT');
2929 
2930  print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_localtax1, 0, $langs, 1, -1, -1, $object->multicurrency_code) . '</td>';
2931  }
2932  print '</tr>';
2933  }
2934 
2935  if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) {
2936  print '<tr>';
2937  print '<td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
2938  print '<td class="nowrap amountcard right">' . price($object->total_localtax2, 0, $langs, 1, -1, -1, $conf->currency) . '</td>';
2939  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2940  $object->multicurrency_total_localtax2 = price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT');
2941 
2942  print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_localtax2, 0, $langs, 1, -1, -1, $object->multicurrency_code) . '</td>';
2943  }
2944  print '</tr>';
2945  }
2946 
2947  print '<tr>';
2948  print '<td>' . $langs->trans('AmountTTC') . '</td>';
2949  print '<td class="nowrap amountcard right">' . price($object->total_ttc, 0, $langs, 1, -1, -1, $conf->currency) . '</td>';
2950  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2951  print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ttc, 0, $langs, 1, -1, -1, $object->multicurrency_code) . '</td>';
2952  }
2953  print '</tr>';
2954 
2955  print '</table>';
2956 
2957  // Margin Infos
2958  if (isModEnabled('margin')) {
2959  $formmargin->displayMarginInfos($object);
2960  }
2961 
2962  print '</div>';
2963  print '</div>';
2964 
2965  print '<div class="clearboth"></div><br>';
2966 
2967  if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
2968  $blocname = 'contacts';
2969  $title = $langs->trans('ContactsAddresses');
2970  include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
2971  }
2972 
2973  if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
2974  $blocname = 'notes';
2975  $title = $langs->trans('Notes');
2976  include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
2977  }
2978 
2979  /*
2980  * Lines
2981  */
2982 
2983  // Get object lines
2984  $result = $object->getLinesArray();
2985 
2986  // Add products/services form
2987  //$forceall = 1;
2988  global $inputalsopricewithtax;
2989  $inputalsopricewithtax = 1;
2990 
2991  print ' <form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">
2992  <input type="hidden" name="token" value="' . newToken().'">
2993  <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">
2994  <input type="hidden" name="mode" value="">
2995  <input type="hidden" name="page_y" value="">
2996  <input type="hidden" name="backtopage" value="'.$backtopage.'">
2997  <input type="hidden" name="id" value="' . $object->id.'">
2998  ';
2999 
3000  if (!empty($conf->use_javascript_ajax) && $object->statut == Propal::STATUS_DRAFT) {
3001  include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
3002  }
3003 
3004  print '<div class="div-table-responsive-no-min">';
3005  if (!empty($object->lines) || ($object->statut == Propal::STATUS_DRAFT && $usercancreate && $action != 'selectlines' && $action != 'editline')) {
3006  print '<table id="tablelines" class="noborder noshadow centpercent">';
3007  }
3008 
3009  if (!empty($object->lines)) {
3010  $object->printObjectLines($action, $mysoc, $object->thirdparty, $lineid, 1);
3011  }
3012 
3013  // Form to add new line
3014  if ($object->statut == Propal::STATUS_DRAFT && $usercancreate && $action != 'selectlines') {
3015  if ($action != 'editline') {
3016  $parameters = array();
3017  $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
3018  if ($reshook < 0) {
3019  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
3020  }
3021  if (empty($reshook)) {
3022  $object->formAddObjectLine(1, $mysoc, $soc);
3023  }
3024  } else {
3025  $parameters = array();
3026  $reshook = $hookmanager->executeHooks('formEditObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
3027  }
3028  }
3029 
3030  if (!empty($object->lines) || ($object->statut == Propal::STATUS_DRAFT && $usercancreate && $action != 'selectlines' && $action != 'editline')) {
3031  print '</table>';
3032  }
3033  print '</div>';
3034 
3035  print "</form>\n";
3036  }
3037 
3038  print dol_get_fiche_end();
3039 
3040 
3041  /*
3042  * Button Actions
3043  */
3044 
3045  if ($action != 'presend') {
3046  print '<div class="tabsAction">';
3047 
3048  $parameters = array();
3049  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
3050  // modified by hook
3051  if (empty($reshook)) {
3052  if ($action != 'editline') {
3053  // Validate
3054  if (($object->statut == Propal::STATUS_DRAFT && $object->total_ttc >= 0 && count($object->lines) > 0)
3055  || ($object->statut == Propal::STATUS_DRAFT && getDolGlobalString('PROPAL_ENABLE_NEGATIVE') && count($object->lines) > 0)) {
3056  if ($usercanvalidate) {
3057  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=validate&token='.newToken().'">'.(!getDolGlobalString('PROPAL_SKIP_ACCEPT_REFUSE') ? $langs->trans('Validate') : $langs->trans('ValidateAndSign')).'</a>';
3058  } else {
3059  print '<a class="butActionRefused classfortooltip" href="#">'.$langs->trans('Validate').'</a>';
3060  }
3061  }
3062  // Create event
3063  /*if (isModEnabled('agenda') && !empty($conf->global->MAIN_ADD_EVENT_ON_ELEMENT_CARD)) // Add hidden condition because this is not a "workflow" action so should appears somewhere else on page.
3064  {
3065  print '<a class="butAction" href="' . DOL_URL_ROOT . '/comm/action/card.php?action=create&amp;origin=' . $object->element . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid . '">' . $langs->trans("AddAction") . '</a></div>';
3066  }*/
3067  // Edit
3068  if ($object->statut == Propal::STATUS_VALIDATED && $usercancreate) {
3069  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=modif&token='.newToken().'">'.$langs->trans('Modify').'</a>';
3070  }
3071 
3072  // ReOpen
3073  if (((getDolGlobalString('PROPAL_REOPEN_UNSIGNED_ONLY') && $object->statut == Propal::STATUS_NOTSIGNED) || (!getDolGlobalString('PROPAL_REOPEN_UNSIGNED_ONLY') && ($object->statut == Propal::STATUS_SIGNED || $object->statut == Propal::STATUS_NOTSIGNED || $object->statut == Propal::STATUS_BILLED || $object->statut == Propal::STATUS_CANCELED))) && $usercanclose) {
3074  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().(!getDolGlobalString('MAIN_JUMP_TAG') ? '' : '#reopen').'"';
3075  print '>'.$langs->trans('ReOpen').'</a>';
3076  }
3077 
3078  // Send
3079  if (empty($user->socid)) {
3080  if ($object->statut == Propal::STATUS_VALIDATED || $object->statut == Propal::STATUS_SIGNED || getDolGlobalString('PROPOSAL_SENDBYEMAIL_FOR_ALL_STATUS')) {
3081  print dolGetButtonAction('', $langs->trans('SendMail'), 'default', $_SERVER["PHP_SELF"].'?action=presend&token='.newToken().'&id='.$object->id.'&mode=init#formmailbeforetitle', '', $usercansend);
3082  }
3083  }
3084 
3085  // Create a sale order
3086  if (isModEnabled('order') && $object->statut == Propal::STATUS_SIGNED) {
3087  if ($usercancreateorder) {
3088  print '<a class="butAction" href="'.DOL_URL_ROOT.'/commande/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddOrder").'</a>';
3089  }
3090  }
3091 
3092  // Create a purchase order
3093  if (getDolGlobalString('WORKFLOW_CAN_CREATE_PURCHASE_ORDER_FROM_PROPOSAL')) {
3094  if ($object->statut == Propal::STATUS_SIGNED && isModEnabled("supplier_order")) {
3095  if ($usercancreatepurchaseorder) {
3096  print '<a class="butAction" href="'.DOL_URL_ROOT.'/fourn/commande/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddPurchaseOrder").'</a>';
3097  }
3098  }
3099  }
3100 
3101  // Create an intervention
3102  if (isModEnabled("service") && isModEnabled('intervention') && $object->statut == Propal::STATUS_SIGNED) {
3103  if ($usercancreateintervention) {
3104  $langs->load("interventions");
3105  print '<a class="butAction" href="'.DOL_URL_ROOT.'/fichinter/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddIntervention").'</a>';
3106  }
3107  }
3108 
3109  // Create contract
3110  if (isModEnabled('contract') && $object->statut == Propal::STATUS_SIGNED) {
3111  $langs->load("contracts");
3112 
3113  if ($usercancreatecontract) {
3114  print '<a class="butAction" href="'.DOL_URL_ROOT.'/contrat/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans('AddContract').'</a>';
3115  }
3116  }
3117 
3118  // Create an invoice and classify billed
3119  if ($object->statut == Propal::STATUS_SIGNED && !getDolGlobalString('PROPOSAL_ARE_NOT_BILLABLE')) {
3120  if (isModEnabled('invoice') && $usercancreateinvoice) {
3121  print '<a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("CreateBill").'</a>';
3122  }
3123 
3124  $arrayofinvoiceforpropal = $object->getInvoiceArrayList();
3125  if ((is_array($arrayofinvoiceforpropal) && count($arrayofinvoiceforpropal) > 0) || !getDolGlobalString('WORKFLOW_PROPAL_NEED_INVOICE_TO_BE_CLASSIFIED_BILLED')) {
3126  if ($usercanclose) {
3127  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifybilled&token='.newToken().'&socid='.$object->socid.'">'.$langs->trans("ClassifyBilled").'</a>';
3128  } else {
3129  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotEnoughPermissions").'">'.$langs->trans("ClassifyBilled").'</a>';
3130  }
3131  }
3132  }
3133 
3134  if (!getDolGlobalString('PROPAL_SKIP_ACCEPT_REFUSE')) {
3135  // Close as accepted/refused
3136  if ($object->statut == Propal::STATUS_VALIDATED) {
3137  if ($usercanclose) {
3138  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=closeas&token='.newToken().(!getDolGlobalString('MAIN_JUMP_TAG') ? '' : '#close').'"';
3139  print '>'.$langs->trans('SetAcceptedRefused').'</a>';
3140  } else {
3141  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotEnoughPermissions").'"';
3142  print '>'.$langs->trans('SetAcceptedRefused').'</a>';
3143  }
3144  }
3145  } else {
3146  // Set not signed (close)
3147  if ($object->statut == Propal::STATUS_DRAFT && $usercanclose) {
3148  print '<a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&token='.newToken().'&action=closeas&token='.newToken() . (!getDolGlobalString('MAIN_JUMP_TAG') ? '' : '#close') . '"';
3149  print '>' . $langs->trans('SetRefusedAndClose') . '</a>';
3150  }
3151  }
3152 
3153  // Cancel propal
3154  if ($object->status > Propal::STATUS_DRAFT && $usercanclose) {
3155  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=cancel&token='.newToken().'">'.$langs->trans("CancelPropal").'</a>';
3156  }
3157 
3158  // Clone
3159  if ($usercancreate) {
3160  print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&socid='.$object->socid.'&action=clone&token='.newToken().'&object='.$object->element.'">'.$langs->trans("ToClone").'</a>';
3161  }
3162 
3163  // Delete
3164  print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken(), 'delete', $usercandelete);
3165  }
3166  }
3167 
3168  print '</div>';
3169  }
3170 
3171  //Select mail models is same action as presend
3172  if (GETPOST('modelselected')) {
3173  $action = 'presend';
3174  }
3175 
3176  if ($action != 'presend') {
3177  print '<div class="fichecenter"><div class="fichehalfleft">';
3178  print '<a name="builddoc"></a>'; // ancre
3179  /*
3180  * Generated documents
3181  */
3182  $objref = dol_sanitizeFileName($object->ref);
3183  $filedir = $conf->propal->multidir_output[$object->entity]."/".dol_sanitizeFileName($object->ref);
3184  $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
3185  $genallowed = $usercanread;
3186  $delallowed = $usercancreate;
3187 
3188  print $formfile->showdocuments('propal', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', 0, '', $soc->default_lang, '', $object);
3189 
3190  // Show links to link elements
3191  $linktoelem = $form->showLinkToObjectBlock($object, null, array('propal'));
3192 
3193  $compatibleImportElementsList = false;
3194  if ($user->hasRight('propal', 'creer') && $object->statut == Propal::STATUS_DRAFT) {
3195  $compatibleImportElementsList = array('commande', 'propal', 'facture'); // import from linked elements
3196  }
3197  $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem, $compatibleImportElementsList);
3198 
3199  // Show online signature link
3200  $useonlinesignature = getDolGlobalInt('PROPOSAL_ALLOW_ONLINESIGN');
3201 
3202  if ($object->statut != Propal::STATUS_DRAFT && $useonlinesignature) {
3203  print '<br><!-- Link to sign -->';
3204  require_once DOL_DOCUMENT_ROOT.'/core/lib/signature.lib.php';
3205  print showOnlineSignatureUrl('proposal', $object->ref, $object).'<br>';
3206  }
3207 
3208  print '</div><div class="fichehalfright">';
3209 
3210  $MAXEVENT = 10;
3211 
3212  $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/comm/propal/agenda.php?id='.$object->id);
3213 
3214  // List of actions on element
3215  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
3216  $formactions = new FormActions($db);
3217  $somethingshown = $formactions->showactions($object, 'propal', $socid, 1, '', $MAXEVENT, '', $morehtmlcenter); // Show all action for thirdparty
3218 
3219  print '</div></div>';
3220  }
3221 
3222  // Presend form
3223  $modelmail = 'propal_send';
3224  $defaulttopic = 'SendPropalRef';
3225  $diroutput = $conf->propal->multidir_output[$object->entity];
3226  $trackid = 'pro'.$object->id;
3227 
3228  include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
3229 }
3230 
3231 // End of page
3232 llxFooter();
3233 $db->close();
if($user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition: card.php:58
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:55
llxFooter()
Empty footer.
Definition: wrapper.php:69
Class to manage a WYSIWYG editor.
Class to manage standard extra fields.
static createDepositFromOrigin(CommonObject $origin, $date, $payment_terms_id, User $user, $notrigger=0, $autoValidateDeposit=false, $overrideFields=array())
Creates a deposit from a proposal or an order by grouping lines by VAT rates.
const TYPE_DEPOSIT
Deposit invoice.
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 permettant la generation de composants html autre Only common components are here.
Class with static methods for building HTML components related to products Only components common to ...
Class to manage building of HTML components.
Class to manage generation of HTML components for proposal management.
static liste_modeles($db, $maxfilenamelength=0)
Return list of active generation modules.
static getIdAndTxFromCode($dbs, $code, $date_document='')
Get id and rate of currency from code.
Class to manage the table of subscription to notifications.
Class ProductCombination Used to represent the relation between a product and one of its variants.
File of class to manage predefined price products or services by customer.
Class to manage products or services.
Class to manage projects.
Class to manage proposals.
const STATUS_DRAFT
Draft status.
const STATUS_SIGNED
Signed quote.
const STATUS_NOTSIGNED
Not signed quote.
const STATUS_BILLED
Billed or processed quote.
const STATUS_CANCELED
Canceled status.
const STATUS_VALIDATED
Validated status.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
getCountry($searchkey, $withcode='', $dbtouse=null, $outputlangs=null, $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
$parameters
Actions.
Definition: card.php:84
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('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') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:751
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0)
Set event message in dol_events session object.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
GETPOSTISARRAY($paramname, $method=0)
Return true if the parameter $paramname is submit from a POST OR GET as an array.
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 a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no', $use_short_label=0)
Output a dimension with best unit.
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_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
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.
GETPOSTFLOAT($paramname, $rounding='')
Return the value of a $_GET or $_POST supervariable, converted into float.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
getDictionaryValue($tablename, $field, $id, $checkentity=false, $rowidfield='rowid')
Return the value of a filed into a dictionary for the record $id.
get_localtax($vatrate, $local, $thirdparty_buyer=null, $thirdparty_seller=null, $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate,...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
$formconfirm
if ($action == 'delbookkeepingyear') {
div float
Unit price before taxes.
Definition: style.css.php:963
propal_prepare_head($object)
Prepare array with list of tabs.
Definition: propal.lib.php:32
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.