dolibarr 19.0.3
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 if (!empty($origin) && !empty($originid)) {
1770 // Parse element/subelement (ex: project_task)
1771 $element = $subelement = $origin;
1772 $regs = array();
1773 if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
1774 $element = $regs[1];
1775 $subelement = $regs[2];
1776 }
1777
1778 if ($element == 'project') {
1779 $projectid = $originid;
1780 } else {
1781 // For compatibility
1782 if ($element == 'order' || $element == 'commande') {
1783 $element = $subelement = 'commande';
1784 }
1785 if ($element == 'propal') {
1786 $element = 'comm/propal';
1787 $subelement = 'propal';
1788 }
1789 if ($element == 'contract') {
1790 $element = $subelement = 'contrat';
1791 }
1792 if ($element == 'shipping') {
1793 $element = $subelement = 'expedition';
1794 }
1795
1796 dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
1797
1798 $classname = ucfirst($subelement);
1799 $objectsrc = new $classname($db);
1800 $objectsrc->fetch($originid);
1801 if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
1802 $objectsrc->fetch_lines();
1803 }
1804 $objectsrc->fetch_thirdparty();
1805
1806 $projectid = (!empty($objectsrc->fk_project) ? $objectsrc->fk_project : 0);
1807 $ref_client = (!empty($objectsrc->ref_client) ? $objectsrc->ref_client : '');
1808
1809 $soc = $objectsrc->thirdparty;
1810
1811 $cond_reglement_id = (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_id) ? $soc->cond_reglement_id : 0));
1812 $mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_id) ? $soc->mode_reglement_id : 0));
1813 $warehouse_id = (!empty($objectsrc->warehouse_id) ? $objectsrc->warehouse_id : (!empty($soc->warehouse_id) ? $soc->warehouse_id : 0));
1814
1815 // Replicate extrafields
1816 $objectsrc->fetch_optionals();
1817 $object->array_options = $objectsrc->array_options;
1818
1819 if (isModEnabled("multicurrency")) {
1820 if (!empty($objectsrc->multicurrency_code)) {
1821 $currency_code = $objectsrc->multicurrency_code;
1822 }
1823 if (getDolGlobalString('MULTICURRENCY_USE_ORIGIN_TX') && !empty($objectsrc->multicurrency_tx)) {
1824 $currency_tx = $objectsrc->multicurrency_tx;
1825 }
1826 }
1827 }
1828 } else {
1829 $cond_reglement_id = empty($soc->cond_reglement_id) ? $cond_reglement_id : $soc->cond_reglement_id;
1830 $deposit_percent = empty($soc->deposit_percent) ? $deposit_percent : $soc->deposit_percent;
1831 $mode_reglement_id = empty($soc->mode_reglement_id) ? $mode_reglement_id : $soc->mode_reglement_id;
1832 $fk_account = empty($soc->fk_account) ? $fk_account : $soc->fk_account;
1833 $shipping_method_id = $soc->shipping_method_id;
1834 $warehouse_id = $soc->fk_warehouse;
1835 $remise_percent = $soc->remise_percent;
1836
1837 if (isModEnabled("multicurrency") && !empty($soc->multicurrency_code)) {
1838 $currency_code = $soc->multicurrency_code;
1839 }
1840 }
1841
1842 // If form was posted (but error returned), we must reuse the value posted in priority (standard Dolibarr behaviour)
1843 if (!GETPOST('changecompany')) {
1844 if (GETPOSTISSET('cond_reglement_id')) {
1845 $cond_reglement_id = GETPOST('cond_reglement_id', 'int');
1846 }
1847 if (GETPOSTISSET('deposit_percent')) {
1848 $deposit_percent = price2num(GETPOST('deposit_percent', 'alpha'));
1849 }
1850 if (GETPOSTISSET('mode_reglement_id')) {
1851 $mode_reglement_id = GETPOST('mode_reglement_id', 'int');
1852 }
1853 if (GETPOSTISSET('cond_reglement_id')) {
1854 $fk_account = GETPOST('fk_account', 'int');
1855 }
1856 }
1857
1858 // Warehouse default if null
1859 if ($soc->fk_warehouse > 0) {
1860 $warehouse_id = $soc->fk_warehouse;
1861 }
1862 if (isModEnabled('stock') && empty($warehouse_id) && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER')) {
1863 if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE')) {
1864 $warehouse_id = $conf->global->MAIN_DEFAULT_WAREHOUSE;
1865 }
1866 if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER')) {
1867 $warehouse_id = $user->fk_warehouse;
1868 }
1869 }
1870
1871 print '<form name="addprop" action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1872 print '<input type="hidden" name="token" value="'.newToken().'">';
1873 print '<input type="hidden" name="action" value="add">';
1874 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
1875 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1876 if ($origin != 'project' && $originid) {
1877 print '<input type="hidden" name="origin" value="'.$origin.'">';
1878 print '<input type="hidden" name="originid" value="'.$originid.'">';
1879 } elseif ($origin == 'project' && !empty($projectid)) {
1880 print '<input type="hidden" name="projectid" value="'.$projectid.'">';
1881 }
1882
1883 print dol_get_fiche_head();
1884
1885 // Call Hook tabContentCreateProposal
1886 $parameters = array();
1887 // Note that $action and $object may be modified by hook
1888 $reshook = $hookmanager->executeHooks('tabContentCreateProposal', $parameters, $object, $action);
1889 if (empty($reshook)) {
1890 print '<table class="border centpercent">';
1891
1892 // Reference
1893 print '<tr class="field_ref"><td class="titlefieldcreate fieldrequired">'.$langs->trans('Ref').'</td><td class="valuefieldcreate">'.$langs->trans("Draft").'</td></tr>';
1894
1895 // Ref customer
1896 print '<tr class="field_ref_client"><td class="titlefieldcreate">'.$langs->trans('RefCustomer').'</td><td class="valuefieldcreate">';
1897 print '<input type="text" name="ref_client" value="'.(!empty($ref_client) ? $ref_client : GETPOST('ref_client')).'"></td>';
1898 print '</tr>';
1899
1900 // Third party
1901 print '<tr class="field_socid">';
1902 print '<td class="titlefieldcreate fieldrequired">'.$langs->trans('Customer').'</td>';
1903 $shipping_method_id = 0;
1904 if ($socid > 0) {
1905 print '<td class="valuefieldcreate">';
1906 print $soc->getNomUrl(1, 'customer');
1907 print '<input type="hidden" name="socid" value="'.$soc->id.'">';
1908 print '</td>';
1909 if (getDolGlobalString('SOCIETE_ASK_FOR_SHIPPING_METHOD') && !empty($soc->shipping_method_id)) {
1910 $shipping_method_id = $soc->shipping_method_id;
1911 }
1912 //$warehouse_id = $soc->warehouse_id;
1913 } else {
1914 print '<td class="valuefieldcreate">';
1915 $filter = '((s.client:IN:1,2,3) AND (s.status:=:1))';
1916 print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', $filter, 'SelectThirdParty', 1, 0, null, 0, 'minwidth300 maxwidth500 widthcentpercentminusxx');
1917 // reload page to retrieve customer informations
1918 if (!getDolGlobalString('RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED')) {
1919 print '<script>
1920 $(document).ready(function() {
1921 $("#socid").change(function() {
1922 console.log("We have changed the company - Reload page");
1923 var socid = $(this).val();
1924 // reload page
1925 $("input[name=action]").val("create");
1926 $("input[name=changecompany]").val("1");
1927 $("form[name=addprop]").submit();
1928 });
1929 });
1930 </script>';
1931 }
1932 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>';
1933 print '</td>';
1934 }
1935 print '</tr>'."\n";
1936
1937 if ($socid > 0) {
1938 // Contacts (ask contact only if thirdparty already defined).
1939 print '<tr class="field_contactid"><td class="titlefieldcreate">'.$langs->trans("DefaultContact").'</td><td class="valuefieldcreate">';
1940 print img_picto('', 'contact', 'class="pictofixedwidth"');
1941 print $form->selectcontacts($soc->id, $contactid, 'contactid', 1, '', '', 0, 'minwidth300');
1942 print '</td></tr>';
1943
1944 // Third party discounts info line
1945 print '<tr class="field_discount_info"><td class="titlefieldcreate">'.$langs->trans('Discounts').'</td><td class="valuefieldcreate">';
1946
1947 $absolute_discount = $soc->getAvailableDiscounts();
1948
1949 $thirdparty = $soc;
1950 $discount_type = 0;
1951 $backtopage = $_SERVER["PHP_SELF"].'?socid='.$thirdparty->id.'&action='.$action.'&origin='.urlencode(GETPOST('origin')).'&originid='.urlencode(GETPOSTINT('originid'));
1952 include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
1953 print '</td></tr>';
1954 }
1955
1956 // Date
1957 print '<tr class="field_addprop"><td class="titlefieldcreate fieldrequired">'.$langs->trans('DatePropal').'</td><td class="valuefieldcreate">';
1958 print img_picto('', 'action', 'class="pictofixedwidth"');
1959 print $form->selectDate('', '', '', '', '', "addprop", 1, 1);
1960 print '</td></tr>';
1961
1962 // Validaty duration
1963 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>';
1964
1965 // Terms of payment
1966 print '<tr class="field_cond_reglement_id"><td class="nowrap">'.$langs->trans('PaymentConditionsShort').'</td><td>';
1967 print img_picto('', 'payment', 'class="pictofixedwidth"');
1968 // at last resort we take the payment term id which may be filled by default values set (if not getpostisset)
1969 print $form->getSelectConditionsPaiements($cond_reglement_id, 'cond_reglement_id', 1, 1, 0, '', $deposit_percent);
1970 print '</td></tr>';
1971
1972 // Mode of payment
1973 print '<tr class="field_mode_reglement_id"><td class="titlefieldcreate">'.$langs->trans('PaymentMode').'</td><td class="valuefieldcreate">';
1974 print img_picto('', 'bank', 'class="pictofixedwidth"');
1975 print $form->select_types_paiements($mode_reglement_id, 'mode_reglement_id', 'CRDT', 0, 1, 0, 0, 1, 'maxwidth200 widthcentpercentminusx', 1);
1976 print '</td></tr>';
1977
1978 // Bank Account
1979 if (getDolGlobalString('BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL') && isModEnabled("banque")) {
1980 print '<tr class="field_fk_account"><td class="titlefieldcreate">'.$langs->trans('BankAccount').'</td><td class="valuefieldcreate">';
1981 print img_picto('', 'bank_account', 'class="pictofixedwidth"').$form->select_comptes($fk_account, 'fk_account', 0, '', 1, '', 0, 'maxwidth200 widthcentpercentminusx', 1);
1982 print '</td></tr>';
1983 }
1984
1985 // Source / Channel - What trigger creation
1986 print '<tr class="field_demand_reason_id"><td class="titlefieldcreate">'.$langs->trans('Source').'</td><td class="valuefieldcreate">';
1987 print img_picto('', 'question', 'class="pictofixedwidth"');
1988 $form->selectInputReason((GETPOSTISSET('demand_reason_id') ? GETPOST('demand_reason_id', 'int') : ''), 'demand_reason_id', "SRC_PROP", 1, 'maxwidth200 widthcentpercentminusx');
1989 print '</td></tr>';
1990
1991 // Shipping Method
1992 if (isModEnabled("expedition")) {
1993 if (getDolGlobalString('SOCIETE_ASK_FOR_SHIPPING_METHOD') && !empty($soc->shipping_method_id)) {
1994 $shipping_method_id = $soc->shipping_method_id;
1995 }
1996 print '<tr class="field_shipping_method_id"><td class="titlefieldcreate">'.$langs->trans('SendingMethod').'</td><td class="valuefieldcreate">';
1997 print img_picto('', 'dolly', 'class="pictofixedwidth"');
1998 $form->selectShippingMethod((GETPOSTISSET('shipping_method_id') ? GETPOST('shipping_method_id', 'int') : $shipping_method_id), 'shipping_method_id', '', 1, '', 0, 'maxwidth200 widthcentpercentminusx');
1999 print '</td></tr>';
2000 }
2001
2002 // Warehouse
2003 if (isModEnabled('stock') && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL')) {
2004 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2005 $formproduct = new FormProduct($db);
2006 print '<tr class="field_warehouse_id"><td class="titlefieldcreate">'.$langs->trans('Warehouse').'</td><td class="valuefieldcreate">';
2007 print img_picto('', 'stock', 'class="pictofixedwidth"').$formproduct->selectWarehouses($warehouse_id, 'warehouse_id', '', 1, 0, 0, '', 0, 0, array(), 'maxwidth500 widthcentpercentminusxx');
2008 print '</td></tr>';
2009 }
2010
2011 // Delivery delay
2012 print '<tr class="field_availability_id"><td class="titlefieldcreate">'.$langs->trans('AvailabilityPeriod');
2013 if (isModEnabled('commande')) {
2014 print ' ('.$langs->trans('AfterOrder').')';
2015 }
2016 print '</td><td class="valuefieldcreate">';
2017 print img_picto('', 'clock', 'class="pictofixedwidth"');
2018 $form->selectAvailabilityDelay((GETPOSTISSET('availability_id') ? GETPOST('availability_id', 'int') : ''), 'availability_id', '', 1, 'maxwidth200 widthcentpercentminusx');
2019 print '</td></tr>';
2020
2021 // Delivery date (or manufacturing)
2022 print '<tr class="field_date_livraison"><td class="titlefieldcreate">'.$langs->trans("DeliveryDate").'</td>';
2023 print '<td class="valuefieldcreate">';
2024 print img_picto('', 'action', 'class="pictofixedwidth"');
2025 if (is_numeric(getDolGlobalString('DATE_LIVRAISON_WEEK_DELAY'))) { // If value set to 0 or a num, not empty
2026 $tmpdte = time() + (7 * getDolGlobalInt('DATE_LIVRAISON_WEEK_DELAY') * 24 * 60 * 60);
2027 $syear = date("Y", $tmpdte);
2028 $smonth = date("m", $tmpdte);
2029 $sday = date("d", $tmpdte);
2030 print $form->selectDate($syear."-".$smonth."-".$sday, 'date_livraison', '', '', '', "addprop");
2031 } else {
2032 print $form->selectDate(-1, 'date_livraison', '', '', '', "addprop", 1, 1);
2033 }
2034 print '</td></tr>';
2035
2036 // Project
2037 if (isModEnabled('project')) {
2038 $langs->load("projects");
2039 print '<tr class="field_projectid">';
2040 print '<td class="titlefieldcreate">'.$langs->trans("Project").'</td><td class="valuefieldcreate">';
2041 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');
2042 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>';
2043 print '</td>';
2044 print '</tr>';
2045 }
2046
2047 // Incoterms
2048 if (isModEnabled('incoterm')) {
2049 print '<tr class="field_incoterm_id">';
2050 print '<td class="titlefieldcreate"><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $soc->label_incoterms, 1).'</label></td>';
2051 print '<td class="valuefieldcreate maxwidthonsmartphone">';
2052 print img_picto('', 'incoterm', 'class="pictofixedwidth"');
2053 print $form->select_incoterms((!empty($soc->fk_incoterms) ? $soc->fk_incoterms : ''), (!empty($soc->location_incoterms) ? $soc->location_incoterms : ''));
2054 print '</td></tr>';
2055 }
2056
2057 // Template to use by default
2058 print '<tr class="field_model">';
2059 print '<td class="titlefieldcreate">'.$langs->trans("DefaultModel").'</td>';
2060 print '<td class="valuefieldcreate">';
2061 print img_picto('', 'pdf', 'class="pictofixedwidth"');
2063 $preselected = (getDolGlobalString('PROPALE_ADDON_PDF_ODT_DEFAULT') ? $conf->global->PROPALE_ADDON_PDF_ODT_DEFAULT : getDolGlobalString("PROPALE_ADDON_PDF"));
2064 print $form->selectarray('model', $liste, $preselected, 0, 0, 0, '', 0, 0, 0, '', 'maxwidth200 widthcentpercentminusx', 1);
2065 print "</td></tr>";
2066
2067 // Multicurrency
2068 if (isModEnabled("multicurrency")) {
2069 print '<tr class="field_currency">';
2070 print '<td class="titlefieldcreate">'.$form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0).'</td>';
2071 print '<td class="valuefieldcreate maxwidthonsmartphone">';
2072 print img_picto('', 'currency', 'class="pictofixedwidth"').$form->selectMultiCurrency(((GETPOSTISSET('multicurrency_code') && !GETPOST('changecompany')) ? GETPOST('multicurrency_code') : $currency_code), 'multicurrency_code', 0);
2073 print '</td></tr>';
2074 }
2075
2076 // Public note
2077 print '<tr class="field_note_public">';
2078 print '<td class="titlefieldcreate tdtop">'.$langs->trans('NotePublic').'</td>';
2079 print '<td class="valuefieldcreate">';
2080 $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');
2081 $doleditor = new DolEditor('note_public', $note_public, '', 80, 'dolibarr_notes', 'In', 0, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
2082 print $doleditor->Create(1);
2083
2084 // Private note
2085 if (empty($user->socid)) {
2086 print '<tr class="field_note_private">';
2087 print '<td class="titlefieldcreate tdtop">'.$langs->trans('NotePrivate').'</td>';
2088 print '<td class="valuefieldcreate">';
2089 $note_private = $object->getDefaultCreateValueFor('note_private', ((!empty($origin) && !empty($originid) && is_object($objectsrc)) ? $objectsrc->note_private : null));
2090 $doleditor = new DolEditor('note_private', $note_private, '', 80, 'dolibarr_notes', 'In', 0, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
2091 print $doleditor->Create(1);
2092 // print '<textarea name="note_private" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'.</textarea>
2093 print '</td></tr>';
2094 }
2095
2096 // Other attributes
2097 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php';
2098
2099 // Lines from source
2100 if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
2101 // TODO for compatibility
2102 if ($origin == 'contrat') {
2103 // Calcul contrat->price (HT), contrat->total (TTC), contrat->tva
2104 //$objectsrc->remise_absolue = $remise_absolue; // deprecated
2105 //$objectsrc->remise_percent = $remise_percent;
2106 $objectsrc->update_price(1, 'auto', 1);
2107 }
2108
2109 print "\n<!-- ".$classname." info -->";
2110 print "\n";
2111 print '<input type="hidden" name="amount" value="'.$objectsrc->total_ht.'">'."\n";
2112 print '<input type="hidden" name="total" value="'.$objectsrc->total_ttc.'">'."\n";
2113 print '<input type="hidden" name="tva" value="'.$objectsrc->total_tva.'">'."\n";
2114 print '<input type="hidden" name="origin" value="'.$objectsrc->element.'">';
2115 print '<input type="hidden" name="originid" value="'.$objectsrc->id.'">';
2116
2117 $newclassname = $classname;
2118 if ($newclassname == 'Propal') {
2119 $newclassname = 'CommercialProposal';
2120 } elseif ($newclassname == 'Commande') {
2121 $newclassname = 'Order';
2122 } elseif ($newclassname == 'Expedition') {
2123 $newclassname = 'Sending';
2124 } elseif ($newclassname == 'Fichinter') {
2125 $newclassname = 'Intervention';
2126 }
2127
2128 print '<tr><td>'.$langs->trans($newclassname).'</td><td>'.$objectsrc->getNomUrl(1).'</td></tr>';
2129 print '<tr><td>'.$langs->trans('AmountHT').'</td><td>'.price($objectsrc->total_ht, 0, $langs, 1, -1, -1, $conf->currency).'</td></tr>';
2130 print '<tr><td>'.$langs->trans('AmountVAT').'</td><td>'.price($objectsrc->total_tva, 0, $langs, 1, -1, -1, $conf->currency)."</td></tr>";
2131 if ($mysoc->localtax1_assuj == "1" || $objectsrc->total_localtax1 != 0) { // Localtax1
2132 print '<tr><td>'.$langs->transcountry("AmountLT1", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax1, 0, $langs, 1, -1, -1, $conf->currency)."</td></tr>";
2133 }
2134
2135 if ($mysoc->localtax2_assuj == "1" || $objectsrc->total_localtax2 != 0) { // Localtax2
2136 print '<tr><td>'.$langs->transcountry("AmountLT2", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax2, 0, $langs, 1, -1, -1, $conf->currency)."</td></tr>";
2137 }
2138 print '<tr><td>'.$langs->trans('AmountTTC').'</td><td>'.price($objectsrc->total_ttc, 0, $langs, 1, -1, -1, $conf->currency)."</td></tr>";
2139
2140 if (isModEnabled("multicurrency")) {
2141 print '<tr><td>'.$langs->trans('MulticurrencyAmountHT').'</td><td>'.price($objectsrc->multicurrency_total_ht).'</td></tr>';
2142 print '<tr><td>'.$langs->trans('MulticurrencyAmountVAT').'</td><td>'.price($objectsrc->multicurrency_total_tva)."</td></tr>";
2143 print '<tr><td>'.$langs->trans('MulticurrencyAmountTTC').'</td><td>'.price($objectsrc->multicurrency_total_ttc)."</td></tr>";
2144 }
2145 }
2146
2147 print "</table>\n";
2148
2149
2150 /*
2151 * Combobox for copy function
2152 */
2153
2154 if (!getDolGlobalString('PROPAL_CLONE_ON_CREATE_PAGE')) {
2155 print '<input type="hidden" name="createmode" value="empty">';
2156 }
2157
2158 if (getDolGlobalString('PROPAL_CLONE_ON_CREATE_PAGE')) {
2159 print '<br><table>';
2160
2161 // For backward compatibility
2162 print '<tr>';
2163 print '<td><input type="radio" name="createmode" value="copy"></td>';
2164 print '<td>'.$langs->trans("CopyPropalFrom").' </td>';
2165 print '<td>';
2166 $liste_propal = array();
2167 $liste_propal [0] = '';
2168
2169 $sql = "SELECT p.rowid as id, p.ref, s.nom";
2170 $sql .= " FROM ".MAIN_DB_PREFIX."propal p";
2171 $sql .= ", ".MAIN_DB_PREFIX."societe s";
2172 $sql .= " WHERE s.rowid = p.fk_soc";
2173 $sql .= " AND p.entity IN (".getEntity('propal').")";
2174 $sql .= " AND p.fk_statut <> 0";
2175 $sql .= " ORDER BY Id";
2176
2177 $resql = $db->query($sql);
2178 if ($resql) {
2179 $num = $db->num_rows($resql);
2180 $i = 0;
2181 while ($i < $num) {
2182 $row = $db->fetch_row($resql);
2183 $propalRefAndSocName = $row[1]." - ".$row[2];
2184 $liste_propal[$row[0]] = $propalRefAndSocName;
2185 $i++;
2186 }
2187 print $form->selectarray("copie_propal", $liste_propal, 0);
2188 } else {
2189 dol_print_error($db);
2190 }
2191 print '</td></tr>';
2192
2193 print '<tr><td class="tdtop"><input type="radio" name="createmode" value="empty" checked></td>';
2194 print '<td valign="top" colspan="2">'.$langs->trans("CreateEmptyPropal").'</td></tr>';
2195 print '</table>';
2196 }
2197 }
2198
2199 print dol_get_fiche_end();
2200
2201 $langs->load("bills");
2202
2203 print $form->buttonsSaveCancel("CreateDraft");
2204
2205 print "</form>";
2206
2207
2208 // Show origin lines
2209 if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
2210 print '<br>';
2211
2212 $title = $langs->trans('ProductsAndServices');
2213 print load_fiche_titre($title);
2214
2215 print '<div class="div-table-responsive-no-min">';
2216 print '<table class="noborder centpercent">';
2217
2218 $objectsrc->printOriginLinesList();
2219
2220 print '</table>';
2221 print '</div>';
2222 }
2223} elseif ($object->id > 0) {
2224 /*
2225 * Show object in view mode
2226 */
2227 $object->fetch_thirdparty();
2228 if ($object->thirdparty) {
2229 $soc = $object->thirdparty;
2230 } else {
2231 $soc = new Societe($db);
2232 }
2233
2234 $head = propal_prepare_head($object);
2235 print dol_get_fiche_head($head, 'comm', $langs->trans('Proposal'), -1, 'propal');
2236
2237 $formconfirm = '';
2238
2239 // Clone confirmation
2240 if ($action == 'clone') {
2241 // Create an array for form
2242 $filter = '(s.client:IN:1,2,3)';
2243 $formquestion = array(
2244 // 'text' => $langs->trans("ConfirmClone"),
2245 // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2246 array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter, '', 0, 0, null, 0, 'maxwidth300')),
2247 array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans('PuttingPricesUpToDate'), 'value' => 0),
2248 array('type' => 'checkbox', 'name' => 'update_desc', 'label' => $langs->trans('PuttingDescUpToDate'), 'value' => 0),
2249 );
2250 if (getDolGlobalString('PROPAL_CLONE_DATE_DELIVERY') && !empty($object->delivery_date)) {
2251 $formquestion[] = array('type' => 'date', 'name' => 'date_delivery', 'label' => $langs->trans("DeliveryDate"), 'value' => $object->delivery_date);
2252 }
2253 // Incomplete payment. We ask if reason = discount or other
2254 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmClonePropal', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
2255 }
2256
2257 if ($action == 'closeas') {
2258 //Form to close proposal (signed or not)
2259 $formquestion = array();
2260 if (!getDolGlobalString('PROPAL_SKIP_ACCEPT_REFUSE')) {
2261 $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)));
2262 }
2263 $formquestion[] = array('type' => 'text', 'name' => 'note_private', 'label' => $langs->trans("Note"), 'value' => ''); // Field to complete private note (not replace)
2264
2265 if (getDolGlobalInt('PROPOSAL_SUGGEST_DOWN_PAYMENT_INVOICE_CREATION')) {
2266 // This is a hidden option:
2267 // Suggestion to create invoice during proposal signature is not enabled by default.
2268 // Such choice should be managed by the workflow module and trigger. This option generates conflicts with some setup.
2269 // It may also break step of creating an order when invoicing must be done from orders and not from proposal
2270 $deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
2271
2272 if (!empty($deposit_percent_from_payment_terms) && isModEnabled('facture') && $user->hasRight('facture', 'creer')) {
2273 require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
2274
2275 $object->fetchObjectLinked();
2276
2277 $eligibleForDepositGeneration = true;
2278
2279 if (array_key_exists('facture', $object->linkedObjects)) {
2280 foreach ($object->linkedObjects['facture'] as $invoice) {
2281 if ($invoice->type == Facture::TYPE_DEPOSIT) {
2282 $eligibleForDepositGeneration = false;
2283 break;
2284 }
2285 }
2286 }
2287
2288 if ($eligibleForDepositGeneration && array_key_exists('commande', $object->linkedObjects)) {
2289 foreach ($object->linkedObjects['commande'] as $order) {
2290 $order->fetchObjectLinked();
2291
2292 if (array_key_exists('facture', $order->linkedObjects)) {
2293 foreach ($order->linkedObjects['facture'] as $invoice) {
2294 if ($invoice->type == Facture::TYPE_DEPOSIT) {
2295 $eligibleForDepositGeneration = false;
2296 break 2;
2297 }
2298 }
2299 }
2300 }
2301 }
2302
2303
2304 if ($eligibleForDepositGeneration) {
2305 $formquestion[] = array(
2306 'type' => 'checkbox',
2307 'tdclass' => 'showonlyifsigned',
2308 'name' => 'generate_deposit',
2309 'morecss' => 'margintoponly marginbottomonly',
2310 'label' => $form->textwithpicto($langs->trans('GenerateDeposit', $object->deposit_percent), $langs->trans('DepositGenerationPermittedByThePaymentTermsSelected'))
2311 );
2312
2313 $formquestion[] = array(
2314 'type' => 'date',
2315 'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2316 'name' => 'datef',
2317 'label' => $langs->trans('DateInvoice'),
2318 'value' => dol_now(),
2319 'datenow' => true
2320 );
2321
2322 if (getDolGlobalString('INVOICE_POINTOFTAX_DATE')) {
2323 $formquestion[] = array(
2324 'type' => 'date',
2325 'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2326 'name' => 'date_pointoftax',
2327 'label' => $langs->trans('DatePointOfTax'),
2328 'value' => dol_now(),
2329 'datenow' => true
2330 );
2331 }
2332
2333 $paymentTermsSelect = $form->getSelectConditionsPaiements(0, 'cond_reglement_id', -1, 0, 1, 'minwidth200');
2334
2335 $formquestion[] = array(
2336 'type' => 'other',
2337 'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2338 'name' => 'cond_reglement_id',
2339 'label' => $langs->trans('PaymentTerm'),
2340 'value' => $paymentTermsSelect
2341 );
2342
2343 $formquestion[] = array(
2344 'type' => 'checkbox',
2345 'tdclass' => 'showonlyifgeneratedeposit',
2346 'name' => 'validate_generated_deposit',
2347 'morecss' => 'margintoponly marginbottomonly',
2348 'label' => $langs->trans('ValidateGeneratedDeposit')
2349 );
2350
2351 $formquestion[] = array(
2352 'type' => 'onecolumn',
2353 'value' => '
2354 <script>
2355 let signedValue = ' . $object::STATUS_SIGNED . ';
2356
2357 $(document).ready(function() {
2358 $("[name=generate_deposit]").change(function () {
2359 let $self = $(this);
2360 let $target = $(".showonlyifgeneratedeposit").parent(".tagtr");
2361
2362 if (! $self.parents(".tagtr").is(":hidden") && $self.is(":checked")) {
2363 $target.show();
2364 } else {
2365 $target.hide();
2366 }
2367
2368 return true;
2369 });
2370
2371 $("#statut").change(function() {
2372 let $target = $(".showonlyifsigned").parent(".tagtr");
2373
2374 if ($(this).val() == signedValue) {
2375 $target.show();
2376 } else {
2377 $target.hide();
2378 }
2379
2380 $("[name=generate_deposit]").trigger("change");
2381
2382 return true;
2383 });
2384
2385 $("#statut").trigger("change");
2386 });
2387 </script>
2388 '
2389 );
2390 }
2391 }
2392 }
2393
2394 if (isModEnabled('notification')) {
2395 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2396 $notify = new Notify($db);
2397 $formquestion = array_merge($formquestion, array(
2398 array('type' => 'onecolumn', 'value' => $notify->confirmMessage('PROPAL_CLOSE_SIGNED', $object->socid, $object)),
2399 ));
2400 }
2401
2402 if (!getDolGlobalString('PROPAL_SKIP_ACCEPT_REFUSE')) {
2403 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('SetAcceptedRefused'), '', 'confirm_closeas', $formquestion, '', 1, 250);
2404 } else {
2405 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?statut=3&id=' . $object->id, $langs->trans('Close'), '', 'confirm_closeas', $formquestion, '', 1, 250);
2406 }
2407 } elseif ($action == 'delete') {
2408 // Confirm delete
2409 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteProp'), $langs->trans('ConfirmDeleteProp', $object->ref), 'confirm_delete', '', 0, 1);
2410 } elseif ($action == 'reopen') {
2411 // Confirm reopen
2412 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ReOpen'), $langs->trans('ConfirmReOpenProp', $object->ref), 'confirm_reopen', '', 0, 1);
2413 } elseif ($action == 'ask_deleteline') {
2414 // Confirmation delete product/service line
2415 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 0, 1);
2416 } elseif ($action == 'validate') {
2417 // Confirm validate proposal
2418 $error = 0;
2419
2420 // We verify whether the object is provisionally numbering
2421 $ref = substr($object->ref, 1, 4);
2422 if ($ref == 'PROV' || $ref == '') {
2423 $numref = $object->getNextNumRef($soc);
2424 if (empty($numref)) {
2425 $error++;
2426 setEventMessages($object->error, $object->errors, 'errors');
2427 }
2428 } else {
2429 $numref = $object->ref;
2430 }
2431
2432 $text = $langs->trans('ConfirmValidateProp', $numref);
2433 if (isModEnabled('notification')) {
2434 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2435 $notify = new Notify($db);
2436 $text .= '<br>';
2437 $text .= $notify->confirmMessage('PROPAL_VALIDATE', $object->socid, $object);
2438 }
2439
2440 // mandatoryPeriod
2441 $nbMandated = 0;
2442 foreach ($object->lines as $line) {
2443 $res = $line->fetch_product();
2444 if ($res > 0) {
2445 if ($line->product->isService() && $line->product->isMandatoryPeriod() && (empty($line->date_start) || empty($line->date_end))) {
2446 $nbMandated++;
2447 break;
2448 }
2449 }
2450 }
2451 if ($nbMandated > 0) {
2452 $text .= '<div><span class="clearboth nowraponall warning">'.$langs->trans("mandatoryPeriodNeedTobeSetMsgValidate").'</span></div>';
2453 }
2454
2455 if (!$error) {
2456 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateProp'), $text, 'confirm_validate', '', 0, 1);
2457 }
2458 }
2459
2460 // Call Hook formConfirm
2461 $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
2462 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2463 if (empty($reshook)) {
2464 $formconfirm .= $hookmanager->resPrint;
2465 } elseif ($reshook > 0) {
2466 $formconfirm = $hookmanager->resPrint;
2467 }
2468
2469 // Print form confirm
2470 print $formconfirm;
2471
2472
2473 // Proposal card
2474
2475 $linkback = '<a href="'.DOL_URL_ROOT.'/comm/propal/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
2476
2477 $morehtmlref = '<div class="refidno">';
2478 // Ref customer
2479 $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $usercancreate, 'string', '', 0, 1);
2480 $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);
2481 // Thirdparty
2482 $morehtmlref .= '<br><span class="hideonsmartphone">'.$langs->trans('ThirdParty').' : </span>'.$soc->getNomUrl(1, 'customer');
2483 if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $soc->id > 0) {
2484 $morehtmlref .= ' (<a href="'.DOL_URL_ROOT.'/comm/propal/list.php?socid='.$soc->id.'&search_societe='.urlencode($soc->name).'">'.$langs->trans("OtherProposals").'</a>)';
2485 }
2486 // Project
2487 if (isModEnabled('project')) {
2488 $langs->load("projects");
2489 $morehtmlref .= '<br>';
2490 if ($usercancreate) {
2491 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
2492 if ($action != 'classify') {
2493 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
2494 }
2495 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
2496 } else {
2497 if (!empty($object->fk_project)) {
2498 $proj = new Project($db);
2499 $proj->fetch($object->fk_project);
2500 $morehtmlref .= $proj->getNomUrl(1);
2501 if ($proj->title) {
2502 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
2503 }
2504 }
2505 }
2506 }
2507 $morehtmlref .= '</div>';
2508
2509
2510 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
2511
2512 // Call Hook tabContentViewProposal
2513 $parameters = array();
2514 // Note that $action and $object may be modified by hook
2515 $reshook = $hookmanager->executeHooks('tabContentViewProposal', $parameters, $object, $action);
2516 if (empty($reshook)) {
2517 print '<div class="fichecenter">';
2518 print '<div class="fichehalfleft">';
2519 print '<div class="underbanner clearboth"></div>';
2520
2521 print '<table class="border tableforfield centpercent">';
2522
2523 // Link for thirdparty discounts
2524 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
2525 $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
2526 $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
2527 } else {
2528 $filterabsolutediscount = "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')";
2529 $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')";
2530 }
2531
2532 print '<tr><td class="titlefield">'.$langs->trans('Discounts').'</td><td>';
2533
2534 $absolute_discount = $soc->getAvailableDiscounts('', $filterabsolutediscount);
2535 $absolute_creditnote = $soc->getAvailableDiscounts('', $filtercreditnote);
2536 $absolute_discount = price2num($absolute_discount, 'MT');
2537 $absolute_creditnote = price2num($absolute_creditnote, 'MT');
2538
2539 $caneditfield = ($object->statut != Propal::STATUS_SIGNED && $object->statut != Propal::STATUS_BILLED);
2540
2541 $thirdparty = $soc;
2542 $discount_type = 0;
2543 $backtopage = $_SERVER["PHP_SELF"].'?id='.$object->id;
2544 include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
2545
2546 print '</td></tr>';
2547
2548 // Date of proposal
2549 print '<tr>';
2550 print '<td>';
2551 // print '<table class="nobordernopadding" width="100%"><tr><td>';
2552 // print $langs->trans('DatePropal');
2553 // print '</td>';
2554 // if ($action != 'editdate' && $usercancreate && $caneditfield) {
2555 // 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>';
2556 // }
2557
2558 // print '</tr></table>';
2559 $editenable = $usercancreate && $caneditfield && $object->statut == Propal::STATUS_DRAFT;
2560 print $form->editfieldkey("DatePropal", 'date', '', $object, $editenable);
2561 print '</td><td class="valuefield">';
2562 if ($action == 'editdate' && $usercancreate && $caneditfield) {
2563 print '<form name="editdate" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2564 print '<input type="hidden" name="token" value="'.newToken().'">';
2565 print '<input type="hidden" name="action" value="setdate">';
2566 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
2567 print $form->selectDate($object->date, 're', '', '', 0, "editdate");
2568 print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
2569 print '</form>';
2570 } else {
2571 if ($object->date) {
2572 print dol_print_date($object->date, 'day');
2573 } else {
2574 print '&nbsp;';
2575 }
2576 }
2577 print '</td>';
2578
2579 // Date end proposal
2580 print '<tr>';
2581 print '<td>';
2582 print '<table class="nobordernopadding centpercent"><tr><td>';
2583 print $langs->trans('DateEndPropal');
2584 print '</td>';
2585 if ($action != 'editecheance' && $usercancreate && $caneditfield) {
2586 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>';
2587 }
2588 print '</tr></table>';
2589 print '</td><td class="valuefield">';
2590 if ($action == 'editecheance' && $usercancreate && $caneditfield) {
2591 print '<form name="editecheance" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2592 print '<input type="hidden" name="token" value="'.newToken().'">';
2593 print '<input type="hidden" name="action" value="setecheance">';
2594 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
2595 print $form->selectDate($object->fin_validite, 'ech', '', '', '', "editecheance");
2596 print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
2597 print '</form>';
2598 } else {
2599 if (!empty($object->fin_validite)) {
2600 print dol_print_date($object->fin_validite, 'day');
2601 if ($object->statut == Propal::STATUS_VALIDATED && $object->fin_validite < ($now - $conf->propal->cloture->warning_delay)) {
2602 print img_warning($langs->trans("Late"));
2603 }
2604 } else {
2605 print '&nbsp;';
2606 }
2607 }
2608 print '</td>';
2609 print '</tr>';
2610
2611 // Payment term
2612 print '<tr><td>';
2613 print '<table class="nobordernopadding" width="100%"><tr><td>';
2614 print $langs->trans('PaymentConditionsShort');
2615 print '</td>';
2616 if ($action != 'editconditions' && $usercancreate && $caneditfield) {
2617 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>';
2618 }
2619 print '</tr></table>';
2620 print '</td><td class="valuefield">';
2621 if ($action == 'editconditions' && $usercancreate && $caneditfield) {
2622 $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 0, '', 1, $object->deposit_percent);
2623 } else {
2624 $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none', 0, '', 1, $object->deposit_percent);
2625 }
2626 print '</td>';
2627 print '</tr>';
2628
2629 // Payment mode
2630 print '<tr class="field_mode_reglement_id">';
2631 print '<td class="titlefieldcreate">';
2632 print '<table class="nobordernopadding centpercent"><tr><td>';
2633 print $langs->trans('PaymentMode');
2634 print '</td>';
2635 if ($action != 'editmode' && $usercancreate && $caneditfield) {
2636 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>';
2637 }
2638 print '</tr></table>';
2639 print '</td><td class="valuefieldcreate">';
2640 if ($action == 'editmode' && $usercancreate && $caneditfield) {
2641 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
2642 } else {
2643 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'none');
2644 }
2645 print '</td></tr>';
2646
2647 // Delivery date
2648 $langs->load('deliveries');
2649 print '<tr><td>';
2650 print $form->editfieldkey($langs->trans('DeliveryDate'), 'date_livraison', $object->delivery_date, $object, $usercancreate && $caneditfield, 'datepicker');
2651 print '</td><td class="valuefieldedit">';
2652 print $form->editfieldval($langs->trans('DeliveryDate'), 'date_livraison', $object->delivery_date, $object, $usercancreate && $caneditfield, 'datepicker');
2653 print '</td>';
2654 print '</tr>';
2655
2656 // Delivery delay
2657 print '<tr class="fielddeliverydelay"><td>';
2658 print '<table class="nobordernopadding" width="100%"><tr><td>';
2659 if (isModEnabled('commande')) {
2660 print $form->textwithpicto($langs->trans('AvailabilityPeriod'), $langs->trans('AvailabilityPeriod').' ('.$langs->trans('AfterOrder').')');
2661 } else {
2662 print $langs->trans('AvailabilityPeriod');
2663 }
2664 print '</td>';
2665 if ($action != 'editavailability' && $usercancreate && $caneditfield) {
2666 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>';
2667 }
2668 print '</tr></table>';
2669 print '</td><td class="valuefield">';
2670 if ($action == 'editavailability' && $usercancreate && $caneditfield) {
2671 $form->form_availability($_SERVER['PHP_SELF'].'?id='.$object->id, $object->availability_id, 'availability_id', 1);
2672 } else {
2673 $form->form_availability($_SERVER['PHP_SELF'].'?id='.$object->id, $object->availability_id, 'none', 1);
2674 }
2675
2676 print '</td>';
2677 print '</tr>';
2678
2679 // Shipping Method
2680 if (isModEnabled("expedition")) {
2681 print '<tr><td>';
2682 print '<table class="nobordernopadding centpercent"><tr><td>';
2683 print $langs->trans('SendingMethod');
2684 print '</td>';
2685 if ($action != 'editshippingmethod' && $usercancreate && $caneditfield) {
2686 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>';
2687 }
2688 print '</tr></table>';
2689 print '</td><td class="valuefield">';
2690 if ($action == 'editshippingmethod' && $usercancreate && $caneditfield) {
2691 $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'shipping_method_id', 1);
2692 } else {
2693 $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'none');
2694 }
2695 print '</td>';
2696 print '</tr>';
2697 }
2698
2699 // Warehouse
2700 if (isModEnabled('stock') && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL')) {
2701 $langs->load('stocks');
2702 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2703 $formproduct = new FormProduct($db);
2704 print '<tr class="field_warehouse_id"><td class="titlefieldcreate">';
2705 $editenable = $usercancreate;
2706 print $form->editfieldkey("Warehouse", 'warehouse', '', $object, $editenable);
2707 print '</td><td class="valuefieldcreate">';
2708 if ($action == 'editwarehouse') {
2709 $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'warehouse_id', 1);
2710 } else {
2711 $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'none');
2712 }
2713 print '</td>';
2714 print '</tr>';
2715 }
2716
2717 // Origin of demand
2718 print '<tr><td>';
2719 print '<table class="nobordernopadding centpercent"><tr><td>';
2720 print $langs->trans('Source');
2721 print '</td>';
2722 if ($action != 'editdemandreason' && $usercancreate) {
2723 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>';
2724 }
2725 print '</tr></table>';
2726 print '</td><td class="valuefield">';
2727 if ($action == 'editdemandreason' && $usercancreate) {
2728 $form->formInputReason($_SERVER['PHP_SELF'].'?id='.$object->id, $object->demand_reason_id, 'demand_reason_id', 1);
2729 } else {
2730 $form->formInputReason($_SERVER['PHP_SELF'].'?id='.$object->id, $object->demand_reason_id, 'none');
2731 }
2732 print '</td>';
2733 print '</tr>';
2734
2735 // Multicurrency
2736 if (isModEnabled("multicurrency")) {
2737 // Multicurrency code
2738 print '<tr>';
2739 print '<td>';
2740 print '<table class="nobordernopadding" width="100%"><tr><td>';
2741 print $form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0);
2742 print '</td>';
2743 if ($action != 'editmulticurrencycode' && $object->statut == $object::STATUS_DRAFT && $usercancreate) {
2744 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>';
2745 }
2746 print '</tr></table>';
2747 print '</td><td class="valuefield">';
2748 if ($object->statut == $object::STATUS_DRAFT && $action == 'editmulticurrencycode' && $usercancreate) {
2749 $form->form_multicurrency_code($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_code, 'multicurrency_code');
2750 } else {
2751 $form->form_multicurrency_code($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_code, 'none');
2752 }
2753 print '</td></tr>';
2754
2755 // Multicurrency rate
2756 if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) {
2757 print '<tr>';
2758 print '<td>';
2759 print '<table class="nobordernopadding" width="100%"><tr>';
2760 print '<td>';
2761 print $form->editfieldkey('CurrencyRate', 'multicurrency_tx', '', $object, 0);
2762 print '</td>';
2763 if ($action != 'editmulticurrencyrate' && $object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency && $usercancreate) {
2764 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>';
2765 }
2766 print '</tr></table>';
2767 print '</td><td class="valuefield">';
2768 if ($object->statut == $object::STATUS_DRAFT && ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') && $usercancreate) {
2769 if ($action == 'actualizemulticurrencyrate') {
2770 list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
2771 }
2772 $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, 'multicurrency_tx', $object->multicurrency_code);
2773 } else {
2774 $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
2775 if ($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
2776 print '<div class="inline-block"> &nbsp; &nbsp; &nbsp; &nbsp; ';
2777 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=actualizemulticurrencyrate">'.$langs->trans("ActualizeCurrency").'</a>';
2778 print '</div>';
2779 }
2780 }
2781 print '</td></tr>';
2782 }
2783 }
2784
2785 if ($soc->outstanding_limit) {
2786 // Outstanding Bill
2787 print '<tr><td>';
2788 print $langs->trans('OutstandingBill');
2789 print '</td><td class="valuefield">';
2790 $arrayoutstandingbills = $soc->getOutstandingBills();
2791 print($arrayoutstandingbills['opened'] > $soc->outstanding_limit ? img_warning() : '');
2792 print price($arrayoutstandingbills['opened']).' / ';
2793 print price($soc->outstanding_limit, 0, $langs, 1, - 1, - 1, $conf->currency);
2794 print '</td>';
2795 print '</tr>';
2796 }
2797
2798 if (getDolGlobalString('BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL') && isModEnabled("banque")) {
2799 // Bank Account
2800 print '<tr><td>';
2801 print '<table width="100%" class="nobordernopadding"><tr><td>';
2802 print $langs->trans('BankAccount');
2803 print '</td>';
2804 if ($action != 'editbankaccount' && $usercancreate) {
2805 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>';
2806 }
2807 print '</tr></table>';
2808 print '</td><td class="valuefield">';
2809 if ($action == 'editbankaccount') {
2810 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1);
2811 } else {
2812 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
2813 }
2814 print '</td>';
2815 print '</tr>';
2816 }
2817
2818 $tmparray = $object->getTotalWeightVolume();
2819 $totalWeight = $tmparray['weight'];
2820 $totalVolume = $tmparray['volume'];
2821 if ($totalWeight) {
2822 print '<tr><td>'.$langs->trans("CalculatedWeight").'</td>';
2823 print '<td class="valuefield">';
2824 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);
2825 print '</td></tr>';
2826 }
2827 if ($totalVolume) {
2828 print '<tr><td>'.$langs->trans("CalculatedVolume").'</td>';
2829 print '<td class="valuefield">';
2830 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);
2831 print '</td></tr>';
2832 }
2833
2834 // Incoterms
2835 if (isModEnabled('incoterm')) {
2836 print '<tr><td>';
2837 print '<table width="100%" class="nobordernopadding"><tr><td>';
2838 print $langs->trans('IncotermLabel');
2839 print '<td><td class="right">';
2840 if ($action != 'editincoterm' && $usercancreate && $caneditfield) {
2841 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/comm/propal/card.php?id='.$object->id.'&action=editincoterm&token='.newToken().'">'.img_edit().'</a>';
2842 } else {
2843 print '&nbsp;';
2844 }
2845 print '</td></tr></table>';
2846 print '</td>';
2847 print '<td class="valuefield">';
2848 if ($action == 'editincoterm' && $usercancreate && $caneditfield) {
2849 print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
2850 } else {
2851 print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
2852 }
2853 print '</td></tr>';
2854 }
2855
2856 // Other attributes
2857 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
2858
2859 print '</table>';
2860
2861 print '</div>';
2862 print '<div class="fichehalfright">';
2863 print '<div class="underbanner clearboth"></div>';
2864
2865 print '<table class="border tableforfield centpercent">';
2866
2867 print '<tr>';
2868 print '<td class="titlefieldmiddle">' . $langs->trans('AmountHT') . '</td>';
2869 print '<td class="nowrap amountcard right">' . price($object->total_ht, '', $langs, 1, -1, -1, $conf->currency) . '</td>';
2870 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2871 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ht, '', $langs, 1, -1, -1, $object->multicurrency_code) . '</td>';
2872 }
2873 print '</tr>';
2874
2875 print '<tr>';
2876 print '<td class="titlefieldmiddle">' . $langs->trans('AmountVAT') . '</td>';
2877 print '<td class="nowrap amountcard right">' . price($object->total_tva, '', $langs, 1, -1, -1, $conf->currency) . '</td>';
2878 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2879 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_tva, '', $langs, 1, -1, -1, $object->multicurrency_code) . '</td>';
2880 }
2881 print '</tr>';
2882
2883 if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) {
2884 print '<tr>';
2885 print '<td class="titlefieldmiddle">' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
2886 print '<td class="nowrap amountcard right">' . price($object->total_localtax1, '', $langs, 1, -1, -1, $conf->currency) . '</td>';
2887 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2888 $object->multicurrency_total_localtax1 = price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT');
2889
2890 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_localtax1, '', $langs, 1, -1, -1, $object->multicurrency_code) . '</td>';
2891 }
2892 print '</tr>';
2893 }
2894
2895 if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) {
2896 print '<tr>';
2897 print '<td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
2898 print '<td class="nowrap amountcard right">' . price($object->total_localtax2, '', $langs, 1, -1, -1, $conf->currency) . '</td>';
2899 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2900 $object->multicurrency_total_localtax2 = price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT');
2901
2902 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_localtax2, '', $langs, 1, -1, -1, $object->multicurrency_code) . '</td>';
2903 }
2904 print '</tr>';
2905 }
2906
2907 print '<tr>';
2908 print '<td>' . $langs->trans('AmountTTC') . '</td>';
2909 print '<td class="nowrap amountcard right">' . price($object->total_ttc, '', $langs, 1, -1, -1, $conf->currency) . '</td>';
2910 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2911 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ttc, '', $langs, 1, -1, -1, $object->multicurrency_code) . '</td>';
2912 }
2913 print '</tr>';
2914
2915 print '</table>';
2916
2917 // Margin Infos
2918 if (isModEnabled('margin')) {
2919 $formmargin->displayMarginInfos($object);
2920 }
2921
2922 print '</div>';
2923 print '</div>';
2924
2925 print '<div class="clearboth"></div><br>';
2926
2927 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
2928 $blocname = 'contacts';
2929 $title = $langs->trans('ContactsAddresses');
2930 include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
2931 }
2932
2933 if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
2934 $blocname = 'notes';
2935 $title = $langs->trans('Notes');
2936 include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
2937 }
2938
2939 /*
2940 * Lines
2941 */
2942
2943 // Get object lines
2944 $result = $object->getLinesArray();
2945
2946 // Add products/services form
2947 //$forceall = 1;
2948 global $inputalsopricewithtax;
2949 $inputalsopricewithtax = 1;
2950
2951 print ' <form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">
2952 <input type="hidden" name="token" value="' . newToken().'">
2953 <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">
2954 <input type="hidden" name="mode" value="">
2955 <input type="hidden" name="page_y" value="">
2956 <input type="hidden" name="backtopage" value="'.$backtopage.'">
2957 <input type="hidden" name="id" value="' . $object->id.'">
2958 ';
2959
2960 if (!empty($conf->use_javascript_ajax) && $object->statut == Propal::STATUS_DRAFT) {
2961 include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
2962 }
2963
2964 print '<div class="div-table-responsive-no-min">';
2965 if (!empty($object->lines) || ($object->statut == Propal::STATUS_DRAFT && $usercancreate && $action != 'selectlines' && $action != 'editline')) {
2966 print '<table id="tablelines" class="noborder noshadow centpercent">';
2967 }
2968
2969 if (!empty($object->lines)) {
2970 $object->printObjectLines($action, $mysoc, $object->thirdparty, $lineid, 1);
2971 }
2972
2973 // Form to add new line
2974 if ($object->statut == Propal::STATUS_DRAFT && $usercancreate && $action != 'selectlines') {
2975 if ($action != 'editline') {
2976 $parameters = array();
2977 $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2978 if ($reshook < 0) {
2979 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2980 }
2981 if (empty($reshook)) {
2982 $object->formAddObjectLine(1, $mysoc, $soc);
2983 }
2984 } else {
2985 $parameters = array();
2986 $reshook = $hookmanager->executeHooks('formEditObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2987 }
2988 }
2989
2990 if (!empty($object->lines) || ($object->statut == Propal::STATUS_DRAFT && $usercancreate && $action != 'selectlines' && $action != 'editline')) {
2991 print '</table>';
2992 }
2993 print '</div>';
2994
2995 print "</form>\n";
2996 }
2997
2998 print dol_get_fiche_end();
2999
3000
3001 /*
3002 * Button Actions
3003 */
3004
3005 if ($action != 'presend') {
3006 print '<div class="tabsAction">';
3007
3008 $parameters = array();
3009 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
3010 // modified by hook
3011 if (empty($reshook)) {
3012 if ($action != 'editline') {
3013 // Validate
3014 if (($object->statut == Propal::STATUS_DRAFT && $object->total_ttc >= 0 && count($object->lines) > 0)
3015 || ($object->statut == Propal::STATUS_DRAFT && getDolGlobalString('PROPAL_ENABLE_NEGATIVE') && count($object->lines) > 0)) {
3016 if ($usercanvalidate) {
3017 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>';
3018 } else {
3019 print '<a class="butActionRefused classfortooltip" href="#">'.$langs->trans('Validate').'</a>';
3020 }
3021 }
3022 // Create event
3023 /*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.
3024 {
3025 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>';
3026 }*/
3027 // Edit
3028 if ($object->statut == Propal::STATUS_VALIDATED && $usercancreate) {
3029 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=modif&token='.newToken().'">'.$langs->trans('Modify').'</a>';
3030 }
3031
3032 // ReOpen
3033 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) {
3034 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().(!getDolGlobalString('MAIN_JUMP_TAG') ? '' : '#reopen').'"';
3035 print '>'.$langs->trans('ReOpen').'</a>';
3036 }
3037
3038 // Send
3039 if (empty($user->socid)) {
3040 if ($object->statut == Propal::STATUS_VALIDATED || $object->statut == Propal::STATUS_SIGNED || getDolGlobalString('PROPOSAL_SENDBYEMAIL_FOR_ALL_STATUS')) {
3041 print dolGetButtonAction('', $langs->trans('SendMail'), 'default', $_SERVER["PHP_SELF"].'?action=presend&token='.newToken().'&id='.$object->id.'&mode=init#formmailbeforetitle', '', $usercansend);
3042 }
3043 }
3044
3045 // Create a sale order
3046 if (isModEnabled('commande') && $object->statut == Propal::STATUS_SIGNED) {
3047 if ($usercancreateorder) {
3048 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>';
3049 }
3050 }
3051
3052 // Create a purchase order
3053 if (getDolGlobalString('WORKFLOW_CAN_CREATE_PURCHASE_ORDER_FROM_PROPOSAL')) {
3054 if ($object->statut == Propal::STATUS_SIGNED && isModEnabled("supplier_order")) {
3055 if ($usercancreatepurchaseorder) {
3056 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>';
3057 }
3058 }
3059 }
3060
3061 // Create an intervention
3062 if (isModEnabled("service") && isModEnabled('ficheinter') && $object->statut == Propal::STATUS_SIGNED) {
3063 if ($usercancreateintervention) {
3064 $langs->load("interventions");
3065 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>';
3066 }
3067 }
3068
3069 // Create contract
3070 if (isModEnabled('contrat') && $object->statut == Propal::STATUS_SIGNED) {
3071 $langs->load("contracts");
3072
3073 if ($usercancreatecontract) {
3074 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>';
3075 }
3076 }
3077
3078 // Create an invoice and classify billed
3079 if ($object->statut == Propal::STATUS_SIGNED && !getDolGlobalString('PROPOSAL_ARE_NOT_BILLABLE')) {
3080 if (isModEnabled('facture') && $usercancreateinvoice) {
3081 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>';
3082 }
3083
3084 $arrayofinvoiceforpropal = $object->getInvoiceArrayList();
3085 if ((is_array($arrayofinvoiceforpropal) && count($arrayofinvoiceforpropal) > 0) || !getDolGlobalString('WORKFLOW_PROPAL_NEED_INVOICE_TO_BE_CLASSIFIED_BILLED')) {
3086 if ($usercanclose) {
3087 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifybilled&token='.newToken().'&socid='.$object->socid.'">'.$langs->trans("ClassifyBilled").'</a>';
3088 } else {
3089 print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotEnoughPermissions").'">'.$langs->trans("ClassifyBilled").'</a>';
3090 }
3091 }
3092 }
3093
3094 if (!getDolGlobalString('PROPAL_SKIP_ACCEPT_REFUSE')) {
3095 // Close as accepted/refused
3096 if ($object->statut == Propal::STATUS_VALIDATED) {
3097 if ($usercanclose) {
3098 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=closeas&token='.newToken().(!getDolGlobalString('MAIN_JUMP_TAG') ? '' : '#close').'"';
3099 print '>'.$langs->trans('SetAcceptedRefused').'</a>';
3100 } else {
3101 print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotEnoughPermissions").'"';
3102 print '>'.$langs->trans('SetAcceptedRefused').'</a>';
3103 }
3104 }
3105 } else {
3106 // Set not signed (close)
3107 if ($object->statut == Propal::STATUS_DRAFT && $usercanclose) {
3108 print '<a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&token='.newToken().'&action=closeas&token='.newToken() . (!getDolGlobalString('MAIN_JUMP_TAG') ? '' : '#close') . '"';
3109 print '>' . $langs->trans('SetRefusedAndClose') . '</a>';
3110 }
3111 }
3112
3113 // Clone
3114 if ($usercancreate) {
3115 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>';
3116 }
3117
3118 // Delete
3119 print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken(), 'delete', $usercandelete);
3120 }
3121 }
3122
3123 print '</div>';
3124 }
3125
3126 //Select mail models is same action as presend
3127 if (GETPOST('modelselected')) {
3128 $action = 'presend';
3129 }
3130
3131 if ($action != 'presend') {
3132 print '<div class="fichecenter"><div class="fichehalfleft">';
3133 print '<a name="builddoc"></a>'; // ancre
3134 /*
3135 * Generated documents
3136 */
3137 $objref = dol_sanitizeFileName($object->ref);
3138 $filedir = $conf->propal->multidir_output[$object->entity]."/".dol_sanitizeFileName($object->ref);
3139 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
3140 $genallowed = $usercanread;
3141 $delallowed = $usercancreate;
3142
3143 print $formfile->showdocuments('propal', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', 0, '', $soc->default_lang, '', $object);
3144
3145 // Show links to link elements
3146 $linktoelem = $form->showLinkToObjectBlock($object, null, array('propal'));
3147
3148 $compatibleImportElementsList = false;
3149 if ($user->hasRight('propal', 'creer') && $object->statut == Propal::STATUS_DRAFT) {
3150 $compatibleImportElementsList = array('commande', 'propal', 'facture'); // import from linked elements
3151 }
3152 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem, $compatibleImportElementsList);
3153
3154 // Show online signature link
3155 $useonlinesignature = getDolGlobalInt('PROPOSAL_ALLOW_ONLINESIGN');
3156
3157 if ($object->statut != Propal::STATUS_DRAFT && $useonlinesignature) {
3158 print '<br><!-- Link to sign -->';
3159 require_once DOL_DOCUMENT_ROOT.'/core/lib/signature.lib.php';
3160 print showOnlineSignatureUrl('proposal', $object->ref).'<br>';
3161 }
3162
3163 print '</div><div class="fichehalfright">';
3164
3165 $MAXEVENT = 10;
3166
3167 $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/comm/propal/agenda.php?id='.$object->id);
3168
3169 // List of actions on element
3170 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
3171 $formactions = new FormActions($db);
3172 $somethingshown = $formactions->showactions($object, 'propal', $socid, 1, '', $MAXEVENT, '', $morehtmlcenter); // Show all action for thirdparty
3173
3174 print '</div></div>';
3175 }
3176
3177 // Presend form
3178 $modelmail = 'propal_send';
3179 $defaulttopic = 'SendPropalRef';
3180 $diroutput = $conf->propal->multidir_output[$object->entity];
3181 $trackid = 'pro'.$object->id;
3182
3183 include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
3184}
3185
3186// End of page
3187llxFooter();
3188$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.