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