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