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