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