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