dolibarr 23.0.3
card.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2015 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
5 * Copyright (C) 2005-2016 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2010-2015 Juanjo Menent <jmenent@2byte.es>
7 * Copyright (C) 2011-2022 Philippe Grand <philippe.grand@atoo-net.com>
8 * Copyright (C) 2012-2016 Marcos García <marcosgdf@gmail.com>
9 * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
10 * Copyright (C) 2014 Ion Agorria <ion@agorria.com>
11 * Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
12 * Copyright (C) 2022 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
13 * Copyright (C) 2022-2024 Charlene Benke <charlene@patas-monkey.com>
14 * Copyright (C) 2023 Joachim Kueter <git-jk@bloxera.com>
15 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
16 * Copyright (C) 2024 Nick Fragoulis
17 * Copyright (C) 2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 3 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program. If not, see <https://www.gnu.org/licenses/>.
31 */
32
40// Load Dolibarr environment
41require '../../main.inc.php';
42require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
43require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
44require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
45require_once DOL_DOCUMENT_ROOT.'/core/class/html.formorder.class.php';
46require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
47require_once DOL_DOCUMENT_ROOT.'/core/lib/fourn.lib.php';
48require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
49require_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_order/modules_commandefournisseur.php';
50require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
51require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
52
53if (isModEnabled('supplier_proposal')) {
54 require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php';
55}
56if (isModEnabled("product")) {
57 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
58}
59if (isModEnabled('project')) {
60 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
61 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
62}
63require_once NUSOAP_PATH.'/nusoap.php'; // Include SOAP
64
65if (isModEnabled('variants')) {
66 require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
67}
68
69if (isModEnabled('stock')) {
70 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php';
71 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
72}
73
83// Load translation files required by the page
84$langs->loadLangs(array('admin', 'orders', 'sendings', 'companies', 'bills', 'propal', 'receptions', 'supplier_proposal', 'products', 'stocks', 'productbatch'));
85if (isModEnabled('incoterm')) {
86 $langs->load('incoterm');
87}
88
89
90// Get Parameters
91$action = GETPOST('action', 'alpha');
92$confirm = GETPOST('confirm', 'alpha');
93$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'purchaseordercard'; // To manage different context of search
94$cancel = GETPOST('cancel', 'alpha');
95$backtopage = GETPOST('backtopage', 'alpha');
96$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
97
98$id = GETPOSTINT('id');
99$ref = GETPOST('ref', 'alpha');
100$socid = GETPOSTINT('socid');
101$projectid = GETPOSTINT('projectid');
102$lineid = GETPOSTINT('lineid');
103$origin = GETPOST('origin', 'alpha');
104$originid = (GETPOSTINT('originid') ? GETPOSTINT('originid') : GETPOSTINT('origin_id')); // For backward compatibility
105$rank = (GETPOSTINT('rank') > 0) ? GETPOSTINT('rank') : -1;
106$stockDelete = GETPOST('stockDelete', 'int');
107
108// PDF
109$hidedetails = (GETPOSTINT('hidedetails') ? GETPOSTINT('hidedetails') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 1 : 0));
110$hidedesc = (GETPOSTINT('hidedesc') ? GETPOSTINT('hidedesc') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 1 : 0));
111$hideref = (GETPOSTINT('hideref') ? GETPOSTINT('hideref') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF') ? 1 : 0));
112
113$datelivraison = dol_mktime(GETPOSTINT('liv_hour'), GETPOSTINT('liv_min'), GETPOSTINT('liv_sec'), GETPOSTINT('liv_month'), GETPOSTINT('liv_day'), GETPOSTINT('liv_year'));
114
115
116// Security check
117if (!empty($user->socid)) {
118 $socid = $user->socid;
119}
120
121// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
122$hookmanager->initHooks(array('ordersuppliercard', 'globalcard'));
123
125$extrafields = new ExtraFields($db);
126
127// fetch optionals attributes and labels
128$extrafields->fetch_name_optionals_label($object->table_element);
129
130if ($user->socid) {
131 $socid = $user->socid;
132}
133
134// Load object
135if ($id > 0 || !empty($ref)) {
136 $ret = $object->fetch($id, $ref);
137 if ($ret < 0) {
138 dol_print_error($db, $object->error);
139 }
140 $ret = $object->fetch_thirdparty();
141 if ($ret < 0) {
142 dol_print_error($db, $object->error);
143 }
144} elseif (!empty($socid) && $socid > 0) {
145 $object->socid = $socid;
146 $ret = $object->fetch_thirdparty();
147 if ($ret < 0) {
148 dol_print_error($db, $object->error);
149 }
150}
151
152// Security check
153$isdraft = (isset($object->status) && ($object->status == $object::STATUS_DRAFT) ? 1 : 0);
154$result = restrictedArea($user, 'fournisseur', $object, 'commande_fournisseur', 'commande', 'fk_soc', 'rowid', $isdraft);
155
156// Common permissions
157$usercanread = ($user->hasRight("fournisseur", "commande", "lire") || $user->hasRight("supplier_order", "lire"));
158$usercancreate = ($user->hasRight("fournisseur", "commande", "creer") || $user->hasRight("supplier_order", "creer"));
159$usercandelete = (($user->hasRight("fournisseur", "commande", "supprimer") || $user->hasRight("supplier_order", "supprimer")) || ($usercancreate && isset($object->status) && $object->status == $object::STATUS_DRAFT));
160
161// Advanced permissions
162$usercanvalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !empty($usercancreate)) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight("fournisseur", "supplier_order_advance", "validate")));
163
164// Additional area permissions
165$usercanapprove = $user->hasRight("fournisseur", "commande", "approuver");
166$usercanapprovesecond = $user->hasRight("fournisseur", "commande", "approve2");
167$usercanorder = $user->hasRight("fournisseur", "commande", "commander");
168if (!isModEnabled('reception')) {
169 $usercanreceive = $user->hasRight("fournisseur", "commande", "receptionner");
170} else {
171 $usercanreceive = $user->hasRight("reception", "creer");
172}
173
174// Permissions for includes
175$permissionnote = $usercancreate; // Used by the include of actions_setnotes.inc.php
176$permissiondellink = $usercancreate; // Used by the include of actions_dellink.inc.php
177$permissiontoedit = $usercancreate; // Used by the include of actions_lineupdown.inc.php
178$permissiontoadd = $usercancreate; // Used by the include of actions_addupdatedelete.inc.php
179$permissiontoeditextra = $permissiontoadd;
180if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
181 // For action 'update_extras', is there a specific permission set for the attribute to update
182 $permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
183}
184
185// Project permission
186$caneditproject = false;
187if (isModEnabled('project')) {
188 $caneditproject = !getDolGlobalString('SUPPLIER_ORDER_FORBID_EDIT_PROJECT') || ($object->status == CommandeFournisseur::STATUS_DRAFT && preg_match('/^[\‍(]?PROV/i', $object->ref));
189}
190
191$error = 0;
192
193
194/*
195 * Actions
196 */
197
198$parameters = array('socid' => $socid);
199$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
200if ($reshook < 0) {
201 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
202}
203
204if (empty($reshook)) {
205 $backurlforlist = DOL_URL_ROOT.'/fourn/commande/list.php'.($socid > 0 ? '?socid='.((int) $socid) : '');
206
207 if (empty($backtopage) || ($cancel && empty($id))) {
208 if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
209 if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
210 $backtopage = $backurlforlist;
211 } else {
212 $backtopage = DOL_URL_ROOT.'/fourn/commande/card.php?id='.((!empty($id) && $id > 0) ? $id : '__ID__');
213 }
214 }
215 }
216
217 if ($cancel) {
218 if (!empty($backtopageforcancel)) {
219 header("Location: ".$backtopageforcancel);
220 exit;
221 } elseif (!empty($backtopage)) {
222 header("Location: ".$backtopage);
223 exit;
224 }
225 $action = '';
226 }
227
228 include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be 'include', not 'include_once'
229
230 include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
231
232 include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; // Must be 'include', not 'include_once'
233
234 if ($action == 'setref_supplier' && $usercancreate) {
235 $result = $object->setValueFrom('ref_supplier', GETPOST('ref_supplier', 'alpha'), '', null, 'text', '', $user, 'ORDER_SUPPLIER_MODIFY');
236 if ($result < 0) {
237 setEventMessages($object->error, $object->errors, 'errors');
238 }
239 }
240
241 // Set incoterm
242 if ($action == 'set_incoterms' && $usercancreate) {
243 $result = $object->setIncoterms(GETPOSTINT('incoterm_id'), GETPOST('location_incoterms'));
244 if ($result < 0) {
245 setEventMessages($object->error, $object->errors, 'errors');
246 }
247 }
248
249 // payment conditions
250 if ($action == 'setconditions' && $usercancreate) {
251 $result = $object->setPaymentTerms(GETPOSTINT('cond_reglement_id'), GETPOSTFLOAT('cond_reglement_id_deposit_percent'));
252 if ($result < 0) {
253 setEventMessages($object->error, $object->errors, 'errors');
254 }
255 }
256
257 // payment mode
258 if ($action == 'setmode' && $usercancreate) {
259 $result = $object->setPaymentMethods(GETPOSTINT('mode_reglement_id'));
260 if ($result < 0) {
261 setEventMessages($object->error, $object->errors, 'errors');
262 }
263 } elseif ($action == 'setmulticurrencycode' && $usercancreate) {
264 // Multicurrency Code
265 $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha'));
266 } elseif ($action == 'setmulticurrencyrate' && $usercancreate) {
267 // Multicurrency rate
268 $result = $object->setMulticurrencyRate(GETPOSTFLOAT('multicurrency_tx'), GETPOSTINT('calculation_mode'));
269 }
270
271 // bank account
272 if ($action == 'setbankaccount' && $usercancreate) {
273 $result = $object->setBankAccount(GETPOSTINT('fk_account'));
274 if ($result < 0) {
275 setEventMessages($object->error, $object->errors, 'errors');
276 }
277 }
278
279 // date of delivery
280 if ($action == 'setdate_livraison' && $usercancreate) {
281 $result = $object->setDeliveryDate($user, $datelivraison);
282 if ($result < 0) {
283 setEventMessages($object->error, $object->errors, 'errors');
284 }
285 }
286
287 // Set project
288 if ($action == 'classin' && $usercancreate && $caneditproject) {
289 $result = $object->setProject($projectid);
290 if ($result < 0) {
291 setEventMessages($object->error, $object->errors, 'errors');
292 }
293 }
294
295 // Set tags
296 if ($action == 'settags' && isModEnabled('category') && $usercancreate) {
297 $result = $object->setCategories(GETPOST('categories', 'array'));
298 if ($result < 0) {
299 setEventMessages($object->error, $object->errors, 'errors');
300 }
301 }
302
303 // Edit Thirdparty
304 if (getDolGlobalString('MAIN_CAN_EDIT_SUPPLIER_ON_SUPPLIER_ORDER') && $action == 'set_thirdparty' && $usercancreate && $object->status == CommandeFournisseur::STATUS_DRAFT) {
305 $new_socid = GETPOSTINT('new_socid');
306 if (!empty($new_socid) && $new_socid != $object->thirdparty->id) {
307 $db->begin();
308
309 // Update supplier
310 $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande_fournisseur';
311 $sql .= ' SET fk_soc = '.((int) $new_socid);
312 $sql .= ' WHERE fk_soc = '.((int) $object->thirdparty->id);
313 $sql .= ' AND rowid = '.((int) $object->id);
314
315 $res = $db->query($sql);
316
317 if (!$res) {
318 $db->rollback();
319 } else {
320 $db->commit();
321
322 // Replace prices for each lines by new supplier prices
323 foreach ($object->lines as $l) {
324 $sql = 'SELECT price, unitprice, tva_tx, ref_fourn';
325 $sql .= ' FROM '.MAIN_DB_PREFIX.'product_fournisseur_price';
326 $sql .= ' WHERE fk_product = '.((int) $l->fk_product);
327 $sql .= ' AND fk_soc = '.((int) $new_socid);
328 $sql .= ' ORDER BY unitprice ASC';
329
330 $resql = $db->query($sql);
331 if ($resql) {
332 $num_row = $db->num_rows($resql);
333 if (empty($num_row)) {
334 // No product price for this supplier !
335 $l->subprice = 0;
336 $l->total_ht = 0;
337 $l->total_tva = 0;
338 $l->total_ttc = 0;
339 $l->ref_supplier = '';
340 $l->update();
341 } else {
342 // No need for loop to keep best supplier price
343 $obj = $db->fetch_object($resql);
344 $l->subprice = $obj->unitprice;
345 $l->total_ht = $obj->price;
346 $l->tva_tx = $obj->tva_tx;
347 $l->total_tva = $l->total_ht * ($obj->tva_tx / 100);
348 $l->total_ttc = $l->total_ht + $l->total_tva;
349 $l->ref_supplier = $obj->ref_fourn;
350 $l->update();
351 }
352 } else {
353 dol_print_error($db);
354 }
355 $db->free($resql);
356 }
357 $object->update_price();
358 }
359 }
360 header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id);
361 exit;
362 }
363
364 if ($action == 'setremisepercent' && $usercancreate) {
365 $result = $object->set_remise($user, price2num(GETPOST('remise_percent')));
366 if ($result < 0) {
367 setEventMessages($object->error, $object->errors, 'errors');
368 }
369 }
370
371 if ($action == 'reopen' && $permissiontoadd) { // no test on permission here, permission to use will depends on status
372 $resSetReopen = $object->setReopen($user);
373 if ($resSetReopen) {
374 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
375 exit;
376 } else {
377 setEventMessages($object->error, $object->errors, 'errors');
378 }
379 }
380
381 /*
382 * Classify supplier order as billed
383 */
384 if ($action == 'classifybilled' && $usercancreate) {
385 $ret = $object->classifyBilled($user);
386 if ($ret < 0) {
387 setEventMessages($object->error, $object->errors, 'errors');
388 }
389 }
390
391 if ($action == 'classifyunbilled' && $usercancreate) {
392 $ret = $object->classifyUnBilled($user);
393 if ($ret < 0) {
394 setEventMessages($object->error, $object->errors, 'errors');
395 }
396 }
397
398 // Add a product line
399 if ($action == 'addline' && GETPOST('submitforalllines', 'aZ09') && (GETPOST('alldate_start', 'alpha') || GETPOST('alldate_end', 'alpha')) && $usercancreate) {
400 // Define date start and date end for all line
401 $alldate_start = dol_mktime(GETPOSTINT('alldate_starthour'), GETPOSTINT('alldate_startmin'), 0, GETPOSTINT('alldate_startmonth'), GETPOSTINT('alldate_startday'), GETPOSTINT('alldate_startyear'));
402 $alldate_end = dol_mktime(GETPOSTINT('alldate_endhour'), GETPOSTINT('alldate_endmin'), 0, GETPOSTINT('alldate_endmonth'), GETPOSTINT('alldate_endday'), GETPOSTINT('alldate_endyear'));
403 foreach ($object->lines as $line) {
404 if ($line->product_type == 1) { // only service line
405 $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, 0, $alldate_start, $alldate_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice, $line->ref_supplier);
406 }
407 }
408 } elseif ($action == 'addline' && GETPOST('submitforalllines', 'aZ09') && GETPOST('vatforalllines', 'alpha') !== '' && $usercancreate) {
409 // Define new vat_rate for all lines
410 $vat_rate = (GETPOST('vatforalllines') ? GETPOST('vatforalllines') : 0);
411 $vat_rate = str_replace('*', '', $vat_rate);
412 $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty, $mysoc);
413 $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty, $mysoc);
414 foreach ($object->lines as $line) {
415 $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $vat_rate, $localtax1_rate, $localtax2_rate, 'HT', $line->info_bits, $line->product_type, 0, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice, $line->ref_supplier);
416 }
417 } elseif ($action == 'addline' && $usercancreate) {
418 $db->begin();
419
420 $langs->load('errors');
421 $error = 0;
422
423 // Set if we used free entry or predefined product
424 $predef = '';
425 $line_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
426 $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'));
427 $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'));
428
429 $prod_entry_mode = GETPOST('prod_entry_mode');
430 if ($prod_entry_mode == 'free') {
431 $idprod = 0;
432 } else {
433 $idprod = GETPOSTINT('idprod');
434 }
435
436 $tva_tx = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0); // Can be '1.2' or '1.2 (CODE)'
437
438 $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
439 $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU', 2);
440 $price_ttc = price2num(GETPOST('price_ttc'), 'MU', 2);
441 $price_ttc_devise = price2num(GETPOST('multicurrency_price_ttc'), 'CU', 2);
442 $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS');
443
444 $remise_percent = (GETPOSTISSET('remise_percent'.$predef) ? price2num(GETPOST('remise_percent'.$predef, 'alpha'), '', 2) : 0);
445 if (empty($remise_percent)) {
446 $remise_percent = 0;
447 }
448
449 // Extrafields
450 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
451 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
452 // Unset extrafield
453 if (is_array($extralabelsline)) {
454 // Get extra fields
455 foreach ($extralabelsline as $key => $value) {
456 unset($_POST["options_".$key]);
457 }
458 }
459
460 if ($prod_entry_mode == 'free' && GETPOST('price_ht') < 0 && $qty < 0) {
461 setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPrice'), $langs->transnoentitiesnoconv('Qty')), null, 'errors');
462 $error++;
463 }
464 if ($prod_entry_mode == 'free' && !GETPOST('idprodfournprice') && GETPOST('type') < 0) {
465 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
466 $error++;
467 }
468 if ($prod_entry_mode == 'free' && GETPOST('price_ht') === '' && GETPOST('price_ttc') === '' && $price_ht_devise === '') { // Unit price can be 0 but not ''
469 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('UnitPrice')), null, 'errors');
470 $error++;
471 }
472 if ($prod_entry_mode == 'free' && !GETPOST('dp_desc')) {
473 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
474 $error++;
475 }
476 if (GETPOST('qty', 'alpha') == '') { // 0 is allowed for order
477 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
478 $error++;
479 }
480
481 if (!$error && isModEnabled('variants') && $prod_entry_mode != 'free') {
482 if ($combinations = GETPOST('combinations', 'array:alphanohtml')) {
483 //Check if there is a product with the given combination
484 $prodcomb = new ProductCombination($db);
485
486 if ($res = $prodcomb->fetchByProductCombination2ValuePairs($idprod, $combinations)) {
487 $idprod = $res->fk_product_child;
488 } else {
489 setEventMessages($langs->trans('ErrorProductCombinationNotFound'), null, 'errors');
490 $error++;
491 }
492 }
493 }
494
495 if ($prod_entry_mode != 'free' && empty($error)) { // With combolist mode idprodfournprice is > 0 or -1. With autocomplete, idprodfournprice is > 0 or ''
496 $productsupplier = new ProductFournisseur($db);
497
498 $idprod = 0;
499 if (GETPOST('idprodfournprice', 'alpha') == -1 || GETPOST('idprodfournprice', 'alpha') == '') {
500 $idprod = -99; // Same behaviour than with combolist. When not select idprodfournprice is now -99 (to avoid conflict with next action that may return -1, -2, ...)
501 }
502
503 $reg = array();
504 if (preg_match('/^idprod_([0-9]+)$/', GETPOST('idprodfournprice', 'alpha'), $reg)) {
505 $idprod = (int) $reg[1];
506 $res = $productsupplier->fetch($idprod); // Load product from its id
507 // Call to init some price properties of $productsupplier
508 // So if a supplier price already exists for another thirdparty (first one found), we use it as reference price
509 if (getDolGlobalString('SUPPLIER_TAKE_FIRST_PRICE_IF_NO_PRICE_FOR_CURRENT_SUPPLIER')) {
510 $fksoctosearch = 0;
511 $productsupplier->get_buyprice(0, -1, $idprod, 'none', $fksoctosearch); // We force qty to -1 to be sure to find if a supplier price exist
512 if ($productsupplier->fourn_socid != $socid) { // The price we found is for another supplier, so we clear supplier price
513 $productsupplier->ref_supplier = '';
514 }
515 } else {
516 $fksoctosearch = $object->thirdparty->id;
517 $productsupplier->get_buyprice(0, -1, $idprod, 'none', $fksoctosearch); // We force qty to -1 to be sure to find if a supplier price exist
518 }
519 } elseif (GETPOSTINT('idprodfournprice') > 0) { // field is not idprod_..., should be int
520 $qtytosearch = (float) $qty; // Just to see if a price exists for the quantity. Not used to find vat.
521 //$qtytosearch = -1; // We force qty to -1 to be sure to find if a supplier price exist
522 $idprod = $productsupplier->get_buyprice(GETPOSTINT('idprodfournprice'), $qtytosearch);
523 $res = $productsupplier->fetch($idprod);
524 }
525
526 if ($idprod > 0) {
527 $label = $productsupplier->label;
528
529 // Define output language
530 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
531 $outputlangs = $langs;
532 $newlang = '';
533 if (/* empty($newlang) && */ GETPOST('lang_id', 'aZ09')) {
534 $newlang = GETPOST('lang_id', 'aZ09');
535 }
536 if (empty($newlang)) {
537 $newlang = $object->thirdparty->default_lang;
538 }
539 if (!empty($newlang)) {
540 $outputlangs = new Translate("", $conf);
541 $outputlangs->setDefaultLang($newlang);
542 }
543 $desc = (!empty($productsupplier->multilangs[$outputlangs->defaultlang]["description"])) ? $productsupplier->multilangs[$outputlangs->defaultlang]["description"] : $productsupplier->description;
544 } else {
545 $desc = $productsupplier->description;
546 }
547 // if we use supplier description of the products
548 if (!empty($productsupplier->desc_supplier) && getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
549 $desc = $productsupplier->desc_supplier;
550 }
551
552 if (getDolGlobalInt('PRODUIT_AUTOFILL_DESC') == 0) {
553 // 'DoNotAutofillButAutoConcat'
554 $desc = dol_concatdesc($desc, $line_desc, false, getDolGlobalString('MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION') ? true : false);
555 } else {
556 //'AutoFillFormFieldBeforeSubmit' or 'DoNotUseDescriptionOfProdut' => User has already done the modification they want
557 $desc = $line_desc;
558 }
559
560 $ref_supplier = $productsupplier->ref_supplier;
561
562 // Get vat rate
563 $tva_npr = 0;
564 if (!GETPOSTISSET('tva_tx')) { // If vat rate not provided from the form (the form has the priority)
565 $tmpidprodfournprice = GETPOST('idprodfournprice', 'alpha'); // can be an id of price, or -1, -2, -99 or 'idprod_...'
566 if (is_numeric($tmpidprodfournprice) && (int) $tmpidprodfournprice > 0) {
567 $tmpidprodfournprice = (int) $tmpidprodfournprice;
568 } else {
569 $tmpidprodfournprice = 0;
570 }
571 $tva_tx = get_default_tva($object->thirdparty, $mysoc, $productsupplier->id, $tmpidprodfournprice);
572 $tva_npr = get_default_npr($object->thirdparty, $mysoc, $productsupplier->id, $tmpidprodfournprice);
573 if (empty($tva_tx)) {
574 $tva_npr = 0;
575 }
576 }
577
578 $localtax1_tx = get_localtax($tva_tx, 1, $mysoc, $object->thirdparty, $tva_npr);
579 $localtax2_tx = get_localtax($tva_tx, 2, $mysoc, $object->thirdparty, $tva_npr);
580
581 $type = $productsupplier->type;
582 if (GETPOST('price_ht') != '' || GETPOST('multicurrency_price_ht') != '') {
583 $price_base_type = 'HT';
584 $pu = price2num($price_ht, 'MU');
585 $pu_devise = price2num($price_ht_devise, 'CU');
586 } elseif (GETPOST('price_ttc') != '' || GETPOST('multicurrency_price_ttc') != '') {
587 $price_base_type = 'TTC';
588 $pu = price2num($price_ttc, 'MU');
589 $pu_devise = price2num($price_ttc_devise, 'CU');
590 } else {
591 $price_base_type = ($productsupplier->fourn_price_base_type ? $productsupplier->fourn_price_base_type : 'HT');
592 if (empty($object->multicurrency_code) || ($productsupplier->fourn_multicurrency_code != $object->multicurrency_code)) { // If object is in a different currency and price not in this currency
593 $pu = $productsupplier->fourn_pu;
594 $pu_devise = 0;
595 } else {
596 $pu = $productsupplier->fourn_pu;
597 $pu_devise = $productsupplier->fourn_multicurrency_unitprice;
598 }
599 }
600
601 if (empty($pu)) {
602 $pu = 0; // If pu is '' or null, we force to have a numeric value
603 }
604
605 $result = $object->addline(
606 $desc,
607 ($price_base_type == 'HT' ? $pu : 0),
608 (float) $qty,
609 $tva_tx,
610 $localtax1_tx,
611 $localtax2_tx,
612 $idprod,
613 $productsupplier->product_fourn_price_id,
614 $ref_supplier,
615 $remise_percent,
616 $price_base_type,
617 ($price_base_type == 'TTC' ? $pu : 0),
618 $type,
619 $tva_npr,
620 0,
621 $date_start,
622 $date_end,
623 $array_options,
624 $productsupplier->fk_unit,
625 $pu_devise,
626 '',
627 0,
628 min($rank, count($object->lines) + 1)
629 );
630 }
631 if ($idprod == -99 || $idprod == 0) {
632 // Product not selected
633 $error++;
634 $langs->load("errors");
635 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")), null, 'errors');
636 }
637 if ($idprod == -1) {
638 // Quantity too low
639 $error++;
640 $langs->load("errors");
641 setEventMessages($langs->trans("ErrorQtyTooLowForThisSupplier"), null, 'errors');
642 }
643 } elseif (empty($error)) { // $price_ht is already set
644 $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
645 $tva_tx = str_replace('*', '', $tva_tx);
646 $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
647 $desc = $line_desc;
648 $type = GETPOSTINT('type');
649 $ref_supplier = GETPOST('fourn_ref', 'alpha');
650
651 $fk_unit = ((string) GETPOST('units')) == '' ? null : GETPOSTINT('units');
652
653 if (!preg_match('/\‍((.*)\‍)/', $tva_tx)) {
654 $tva_tx = price2num($tva_tx); // $txtva can have format '5,1' or '5.1' or '5.1(XXX)', we must clean only if '5,1'
655 }
656
657 // Local Taxes
658 $localtax1_tx = get_localtax($tva_tx, 1, $mysoc, $object->thirdparty);
659 $localtax2_tx = get_localtax($tva_tx, 2, $mysoc, $object->thirdparty);
660
661 if (GETPOST('price_ht') != '' || GETPOST('multicurrency_price_ht') != '') {
662 $pu_ht = price2num($price_ht, 'MU'); // $pu_ht must be rounded according to settings
663 $pu_ttc = '';
664 } else {
665 $pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
666 $pu_ht = price2num((float) $pu_ttc / (1 + ((float) $tva_tx / 100)), 'MU'); // $pu_ht must be rounded according to settings
667 }
668 $price_base_type = 'HT';
669 $pu_ht_devise = price2num($price_ht_devise, 'CU');
670
671 $result = $object->addline($desc, (float) $pu_ht, (float) $qty, $tva_tx, $localtax1_tx, $localtax2_tx, 0, 0, $ref_supplier, $remise_percent, $price_base_type, (float) $pu_ttc, $type, 0, 0, $date_start, $date_end, $array_options, $fk_unit, (float) $pu_ht_devise);
672 }
673
674 //print "xx".$tva_tx; exit;
675 if (!$error && $result > 0) {
676 $db->commit();
677
678 $ret = $object->fetch($object->id); // Reload to get new records
679
680 // Define output language
681 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
682 $outputlangs = $langs;
683 $newlang = '';
684 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */) {
685 $newlang = $object->thirdparty->default_lang;
686 if (GETPOST('lang_id', 'aZ09')) {
687 $newlang = GETPOST('lang_id', 'aZ09');
688 }
689 }
690 if (!empty($newlang)) {
691 $outputlangs = new Translate("", $conf);
692 $outputlangs->setDefaultLang($newlang);
693 }
694 $model = $object->model_pdf;
695 $ret = $object->fetch($id); // Reload to get new records
696
697 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
698 if ($result < 0) {
699 setEventMessages($object->error, $object->errors, 'errors');
700 }
701 }
702
703 unset($_POST ['prod_entry_mode']);
704
705 unset($_POST['qty']);
706 unset($_POST['type']);
707 unset($_POST['remise_percent']);
708 unset($_POST['pu']);
709 unset($_POST['price_ht']);
710 unset($_POST['multicurrency_price_ht']);
711 unset($_POST['price_ttc']);
712 unset($_POST['fourn_ref']);
713 unset($_POST['tva_tx']);
714 unset($_POST['label']);
715 unset($localtax1_tx);
716 unset($localtax2_tx);
717 unset($_POST['np_marginRate']);
718 unset($_POST['np_markRate']);
719 unset($_POST['dp_desc']);
720 unset($_POST['idprodfournprice']);
721 unset($_POST['units']);
722
723 unset($_POST['date_starthour']);
724 unset($_POST['date_startmin']);
725 unset($_POST['date_startsec']);
726 unset($_POST['date_startday']);
727 unset($_POST['date_startmonth']);
728 unset($_POST['date_startyear']);
729 unset($_POST['date_endhour']);
730 unset($_POST['date_endmin']);
731 unset($_POST['date_endsec']);
732 unset($_POST['date_endday']);
733 unset($_POST['date_endmonth']);
734 unset($_POST['date_endyear']);
735 } else {
736 $db->rollback();
737 setEventMessages($object->error, $object->errors, 'errors');
738 }
739
740 $action = '';
741 }
742
743 /*
744 * Updating a line in the order
745 */
746 if ($action == 'updateline' && $usercancreate && !GETPOST('cancel', 'alpha')) {
747 $db->begin();
748
749 $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
750
751 if ($lineid) {
752 $line = new CommandeFournisseurLigne($db);
753 $res = $line->fetch($lineid);
754 if (!$res) {
755 dol_print_error($db);
756 }
757 }
758
759 $productsupplier = new ProductFournisseur($db);
760 if (getDolGlobalInt('SUPPLIER_ORDER_WITH_PREDEFINED_PRICES_ONLY') == 1) { // Not the common case
761 if ($line->fk_product > 0 && $productsupplier->get_buyprice(0, (float) price2num(GETPOSTFLOAT('qty')), $line->fk_product, 'none', GETPOSTINT('socid')) < 0) {
762 setEventMessages($langs->trans("ErrorQtyTooLowForThisSupplier"), null, 'warnings');
763 }
764 }
765
766 $date_start = dol_mktime(GETPOSTINT('date_starthour'), GETPOSTINT('date_startmin'), GETPOSTINT('date_startsec'), GETPOSTINT('date_startmonth'), GETPOSTINT('date_startday'), GETPOSTINT('date_startyear'));
767 $date_end = dol_mktime(GETPOSTINT('date_endhour'), GETPOSTINT('date_endmin'), GETPOSTINT('date_endsec'), GETPOSTINT('date_endmonth'), GETPOSTINT('date_endday'), GETPOSTINT('date_endyear'));
768
769 // Define info_bits
770 $info_bits = 0;
771 if (preg_match('/\*/', $vat_rate)) {
772 $info_bits |= 0x01;
773 }
774
775 // Define vat_rate
776 $vat_rate = str_replace('*', '', $vat_rate);
777 $localtax1_rate = get_localtax($vat_rate, 1, $mysoc, $object->thirdparty);
778 $localtax2_rate = get_localtax($vat_rate, 2, $mysoc, $object->thirdparty);
779
780 if (GETPOST('price_ht') != '') {
781 $price_base_type = 'HT';
782 $ht = price2num(GETPOST('price_ht'), '', 2);
783 } else {
784 $reg = array();
785 $vatratecleaned = $vat_rate;
786 if (preg_match('/^(.*)\s*\‍((.*)\‍)$/', $vat_rate, $reg)) { // If vat is "xx (yy)"
787 $vatratecleaned = trim($reg[1]);
788 $vatratecode = $reg[2];
789 }
790
791 $ttc = price2num(GETPOST('price_ttc'), '', 2);
792 $ht = (float) $ttc / (1 + ((float) $vatratecleaned / 100));
793 $price_base_type = 'HT';
794 }
795
796 $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), 'CU', 2);
797
798 // Extrafields Lines
799 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
800 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
801 // Unset extrafield POST Data
802 if (is_array($extralabelsline)) {
803 foreach ($extralabelsline as $key => $value) {
804 unset($_POST["options_".$key]);
805 }
806 }
807
808 $result = $object->updateline(
809 $lineid,
810 GETPOST('product_desc', 'restricthtml'),
811 $ht,
812 (float) price2num(GETPOST('qty'), 'MS'),
813 (float) price2num(GETPOST('remise_percent'), '', 2),
814 $vat_rate,
815 $localtax1_rate,
816 $localtax2_rate,
817 $price_base_type,
818 0,
819 GETPOSTISSET("type") ? GETPOST("type") : $line->product_type,
820 0,
821 $date_start,
822 $date_end,
823 $array_options,
824 ((string) GETPOST('units') === '') ? null : GETPOSTINT('units'),
825 (float) $pu_ht_devise,
826 GETPOST('fourn_ref', 'alpha')
827 );
828 unset($_POST['qty']);
829 unset($_POST['type']);
830 unset($_POST['idprodfournprice']);
831 unset($_POST['remmise_percent']);
832 unset($_POST['dp_desc']);
833 unset($_POST['np_desc']);
834 unset($_POST['pu']);
835 unset($_POST['fourn_ref']);
836 unset($_POST['tva_tx']);
837 unset($_POST['date_start']);
838 unset($_POST['date_end']);
839 unset($_POST['units']);
840 unset($localtax1_tx);
841 unset($localtax2_tx);
842
843 unset($_POST['date_starthour']);
844 unset($_POST['date_startmin']);
845 unset($_POST['date_startsec']);
846 unset($_POST['date_startday']);
847 unset($_POST['date_startmonth']);
848 unset($_POST['date_startyear']);
849 unset($_POST['date_endhour']);
850 unset($_POST['date_endmin']);
851 unset($_POST['date_endsec']);
852 unset($_POST['date_endday']);
853 unset($_POST['date_endmonth']);
854 unset($_POST['date_endyear']);
855
856 if ($result >= 0) {
857 // Define output language
858 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
859 $outputlangs = $langs;
860 $newlang = '';
861 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
862 $newlang = GETPOST('lang_id', 'aZ09');
863 }
864 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
865 $newlang = $object->thirdparty->default_lang;
866 }
867 if (!empty($newlang)) {
868 $outputlangs = new Translate("", $conf);
869 $outputlangs->setDefaultLang($newlang);
870 }
871 $model = $object->model_pdf;
872 $ret = $object->fetch($id); // Reload to get new records
873
874 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
875 if ($result < 0) {
876 dol_print_error($db, $object->error, $object->errors);
877 }
878 }
879
880 $db->commit();
881 } else {
882 $db->rollback();
883
884 setEventMessages($object->error, $object->errors, 'errors');
885 }
886 }
887
888 // Remove a product line
889 if ($action == 'confirm_deleteline' && $confirm == 'yes' && $usercancreate) {
890 $db->begin();
891
892 $result = $object->deleteLine($lineid);
893 if ($result > 0) {
894 // reorder lines
895 $object->line_order(true);
896 // Define output language
897 $outputlangs = $langs;
898 $newlang = '';
899 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
900 $newlang = GETPOST('lang_id', 'aZ09');
901 }
902 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
903 $newlang = $object->thirdparty->default_lang;
904 }
905 if (!empty($newlang)) {
906 $outputlangs = new Translate("", $conf);
907 $outputlangs->setDefaultLang($newlang);
908 }
909 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
910 $ret = $object->fetch($object->id); // Reload to get new records
911 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
912 }
913 } else {
914 $error++;
915 setEventMessages($object->error, $object->errors, 'errors');
916 // Reset action to avoid asking again confirmation on failure
917 $action = '';
918 }
919
920 if (!$error) {
921 // reopen order if necessary
923 if ($object->setStatus($user, CommandeFournisseur::STATUS_RECEIVED_PARTIALLY) < 0) {
924 setEventMessages($object->error, $object->errors, 'errors');
925 $error++;
926 $action = '';
927 }
928 }
929 }
930
931 if (!$error) {
932 $db->commit();
933 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
934 exit;
935 } else {
936 $db->rollback();
937 }
938 }
939
940 // Validate
941 if ($action == 'confirm_valid' && $confirm == 'yes' && $usercanvalidate) {
942 $db->begin();
943
944 $object->date_commande = dol_now();
945 $result = $object->valid($user);
946 if ($result >= 0) {
947 // Define output language
948 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
949 $outputlangs = $langs;
950 $newlang = '';
951 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
952 $newlang = GETPOST('lang_id', 'aZ09');
953 }
954 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
955 $newlang = $object->thirdparty->default_lang;
956 }
957 if (!empty($newlang)) {
958 $outputlangs = new Translate("", $conf);
959 $outputlangs->setDefaultLang($newlang);
960 }
961 $model = $object->model_pdf;
962 $ret = $object->fetch($id); // Reload to get new records
963
964 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
965 if ($result < 0) {
966 $error++;
967 dol_print_error($db, $object->error, $object->errors);
968 }
969 }
970 } else {
971 $error++;
972 setEventMessages($object->error, $object->errors, 'errors');
973 }
974
975 // If we have permission, and if we don't need to provide the idwarehouse, we go directly on approved step
976 if (!$error && !getDolGlobalString('SUPPLIER_ORDER_NO_DIRECT_APPROVE') && $usercanapprove && !(getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER') && $object->hasProductsOrServices(1))) {
977 $action = 'confirm_approve'; // can make standard or first level approval also if permission is set
978 }
979
980 if (!$error) {
981 $db->commit();
982 } else {
983 $db->rollback();
984 }
985 }
986
987 if (($action == 'confirm_approve' || $action == 'confirm_approve2') && $confirm == 'yes' && $usercanapprove) {
988 $db->begin();
989
990 $idwarehouse = GETPOSTINT('idwarehouse');
991
992 $qualified_for_stock_change = 0;
993 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
994 $qualified_for_stock_change = $object->hasProductsOrServices(2);
995 } else {
996 $qualified_for_stock_change = $object->hasProductsOrServices(1);
997 }
998
999 // Check parameters
1000 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER') && $qualified_for_stock_change) { // warning name of option should be STOCK_CALCULATE_ON_SUPPLIER_APPROVE_ORDER
1001 if (!$idwarehouse || $idwarehouse == -1) {
1002 $error++;
1003 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1004 $action = '';
1005 }
1006 }
1007
1008 if (!$error) {
1009 $result = $object->approve($user, $idwarehouse, ($action == 'confirm_approve2' ? 1 : 0));
1010 if ($result > 0) {
1011 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1012 $outputlangs = $langs;
1013 $newlang = '';
1014 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
1015 $newlang = GETPOST('lang_id', 'aZ09');
1016 }
1017 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1018 $newlang = $object->thirdparty->default_lang;
1019 }
1020 if (!empty($newlang)) {
1021 $outputlangs = new Translate("", $conf);
1022 $outputlangs->setDefaultLang($newlang);
1023 }
1024 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1025 }
1026 } else {
1027 $error++;
1028 setEventMessages($object->error, $object->errors, 'errors');
1029 }
1030 }
1031
1032 if (!$error) {
1033 $db->commit();
1034
1035 header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id);
1036 exit;
1037 } else {
1038 $db->rollback();
1039 }
1040 }
1041
1042 if ($action == 'confirm_refuse' && $confirm == 'yes' && $usercanapprove) {
1043 if (GETPOST('refuse_note')) {
1044 $object->refuse_note = GETPOST('refuse_note');
1045 }
1046 $result = $object->refuse($user);
1047 if ($result > 0) {
1048 header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id);
1049 exit;
1050 } else {
1051 setEventMessages($object->error, $object->errors, 'errors');
1052 }
1053 }
1054
1055 // Force mandatory order method
1056 if ($action == 'commande') { // Test on permission not required here
1057 $methodecommande = GETPOSTINT('methodecommande');
1058
1059 if ($cancel) {
1060 $action = '';
1061 } elseif ($methodecommande <= 0 && !getDolGlobalInt('SUPPLIER_ORDER_MODE_OPTIONAL')) {
1062 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("OrderMode")), null, 'errors');
1063 $action = 'createorder';
1064 }
1065 }
1066
1067 if ($action == 'confirm_commande' && $confirm == 'yes' && $usercanorder) {
1068 $db->begin();
1069 $object->context["sendmanualtriggers"] = GETPOST("manual_trigger_send");
1070 $result = $object->commande($user, GETPOSTINT("datecommande"), GETPOSTINT("methode"), GETPOST('comment'));
1071 if ($result > 0) {
1072 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1073 $outputlangs = $langs;
1074 $newlang = '';
1075 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
1076 $newlang = GETPOST('lang_id', 'aZ09');
1077 }
1078 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1079 $newlang = $object->thirdparty->default_lang;
1080 }
1081 if (!empty($newlang)) {
1082 $outputlangs = new Translate("", $conf);
1083 $outputlangs->setDefaultLang($newlang);
1084 }
1085 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1086 }
1087 $action = '';
1088 } else {
1089 $error++;
1090 setEventMessages($object->error, $object->errors, 'errors');
1091 }
1092
1093 if (!$error) {
1094 $db->commit();
1095
1096 header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id);
1097 exit;
1098 } else {
1099 $db->rollback();
1100 }
1101 }
1102
1103
1104 if ($action == 'confirm_delete' && $confirm == 'yes' && $usercandelete) {
1105 // Delete existing dispatched lines
1106 $errOnDelete = 0;
1107 $errorsOnDelete = array();
1108
1109 $db->begin();
1110
1111 if ($stockDelete) {
1112 // TODO We must find line already recorded in stock, not lines dispatched (stock recording may not have been done
1113 // even if dispatched in llx_receptiondet_batch)
1114 // For example to know if stock movement were already record, we may look at stock movements in llx_stock_movement linked to a reception
1115 // that is linked to the purchase order.
1116
1117 /*
1118 $dispatchedLines = $object->getDispachedLines();
1119
1120 if (!empty($dispatchedLines)) {
1121 foreach ($dispatchedLines as $dispatchedLine) {
1122 $supplierorderdispatch = new CommandeFournisseurDispatch($db);
1123 $result = $supplierorderdispatch->fetch($dispatchedLine['id']);
1124 if ($result > 0) {
1125 $result = $supplierorderdispatch->delete($user);
1126 }
1127 if ($result < 0) {
1128 $errorsOnDelete = $object->errors;
1129 $errOnDelete++;
1130 }
1131 }
1132 }
1133
1134 if ($entrepot > 0 && $product > 0 && isModEnabled('enabled')) {
1135 $stockMovementLines = $object->getstockMovementLines()
1136
1137 if (!empty($stockMovementLines)) {
1138 foreach($stockMovementLines as $stockmovementline) {
1139 $qty = $stockmovementline->qty;
1140 $entrepot = $stockmovementline->fk_entrepot;
1141 $product = $stockmovementline->fk_product;
1142 $price = $stockmovementline->price;
1143 $comment = $langs->trans('SupplierOrderDeletion', $object->ref);
1144 $eatby = $stockmovementline->eatby;
1145 $sellby = $stockmovementline->sellby;
1146 $batch = $stockmovementline->batch;
1147
1148 $mouv = new MouvementStock($db);
1149 $mouv->setOrigin($object->element, $object->id);
1150 $result = $mouv->livraison($user, $product, $entrepot, $qty, $price, $comment, '', $eatby, $sellby, $batch);
1151 if ($result < 0) {
1152 $errorsOnDelete = $mouv->errors;
1153 $errOnDelete++;
1154 }
1155 }
1156 }
1157 }
1158 */
1159 }
1160
1161 // @phpstan-ignore-next-line
1162 if (empty($errOnDelete)) {
1163 $result = $object->delete($user);
1164 if ($result > 0) {
1165 $db->commit();
1166 header("Location: " . DOL_URL_ROOT . '/fourn/commande/list.php?restore_lastsearch_values=1');
1167 exit;
1168 } else {
1169 $db->rollback();
1170 setEventMessages($object->error, $object->errors, 'errors');
1171 }
1172 } else {
1173 $db->rollback();
1174 setEventMessages('', $errorsOnDelete, 'errors');
1175 }
1176 }
1177
1178 // Action clone object
1179 if ($action == 'confirm_clone' && $confirm == 'yes' && $usercancreate) {
1180 // @phan-suppress-next-line PhanPluginBothLiteralsBinaryOp
1181 if (1 == 0 && !GETPOST('clone_content') && !GETPOST('clone_receivers')) {
1182 setEventMessages($langs->trans("NoCloneOptionsSpecified"), null, 'errors');
1183 } else {
1184 if ($object->id > 0) {
1185 $orig = clone $object;
1186
1187 $result = $object->createFromClone($user, $socid);
1188 if ($result > 0) {
1189 header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result);
1190 exit;
1191 } else {
1192 setEventMessages($object->error, $object->errors, 'errors');
1193 $object = $orig;
1194 $action = '';
1195 }
1196 }
1197 }
1198 }
1199
1200 // Set status of reception (complete, partial, ...)
1201 if ($action == 'livraison' && $usercanreceive) {
1202 if ($cancel) {
1203 $action = '';
1204 } else {
1205 $db->begin();
1206
1207 if (GETPOST("type") != '') {
1208 $date_liv = dol_mktime(GETPOSTINT('rehour'), GETPOSTINT('remin'), GETPOSTINT('resec'), GETPOSTINT("remonth"), GETPOSTINT("reday"), GETPOSTINT("reyear"));
1209
1210 $result = $object->Livraison($user, $date_liv, GETPOST("type"), GETPOST("comment")); // GETPOST("type") is 'tot', 'par', 'nev', 'can'
1211 if ($result > 0) {
1212 $langs->load("sendings");
1213 setEventMessages($langs->trans("DeliveryStateSaved"), null);
1214 $action = '';
1215 } else {
1216 //if ($result == -3) {}
1217 $error++;
1218 setEventMessages($object->error, $object->errors, 'errors');
1219 }
1220 } else {
1221 $error++;
1222 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Delivery")), null, 'errors');
1223 }
1224
1225 if (!$error) {
1226 $db->commit();
1227 } else {
1228 $db->rollback();
1229 }
1230 }
1231 }
1232
1233 if ($action == 'confirm_cancel' && $confirm == 'yes' && $usercanorder) {
1234 if (GETPOST('cancel_note')) {
1235 $object->cancel_note = GETPOST('cancel_note');
1236 }
1237 $result = $object->cancel($user);
1238 if ($result > 0) {
1239 header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id);
1240 exit;
1241 } else {
1242 setEventMessages($object->error, $object->errors, 'errors');
1243 }
1244 }
1245
1246 // Actions when printing a doc from card
1247 include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
1248
1249 // Actions to send emails
1250 $triggersendname = 'ORDER_SUPPLIER_SENTBYMAIL';
1251 $autocopy = 'MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO';
1252 $trackid = 'sord'.$object->id;
1253 include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
1254
1255 // Actions to build doc
1256 $upload_dir = $conf->fournisseur->commande->dir_output;
1257 include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
1258
1259
1260 if ($action == 'update_extras' && $permissiontoeditextra) {
1261 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
1262
1263 $attribute_name = GETPOST('attribute', 'aZ09');
1264
1265 // Fill array 'array_options' with data from update form
1266 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
1267 if ($ret < 0) {
1268 $error++;
1269 }
1270
1271 if (!$error) {
1272 $result = $object->updateExtraField($attribute_name, 'ORDER_SUPPLIER_MODIFY');
1273 if ($result < 0) {
1274 setEventMessages($object->error, $object->errors, 'errors');
1275 $error++;
1276 }
1277 }
1278
1279 if ($error) {
1280 $action = 'edit_extras';
1281 }
1282 }
1283
1284 /*
1285 * Create an order
1286 */
1287 if ($action == 'add' && $permissiontoadd) {
1288 $error = 0;
1289 $selectedLines = GETPOST('toselect', 'array:int');
1290 if ($socid < 1) {
1291 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Supplier')), null, 'errors');
1292 $action = 'create';
1293 $error++;
1294 }
1295
1296 if (!$error) {
1297 $db->begin();
1298
1299 // Creation commande
1300 $object->ref_supplier = GETPOST('refsupplier');
1301 $object->socid = $socid;
1302 $object->cond_reglement_id = GETPOSTINT('cond_reglement_id');
1303 $object->deposit_percent = GETPOSTFLOAT('cond_reglement_id_deposit_percent');
1304 $object->mode_reglement_id = GETPOSTINT('mode_reglement_id');
1305 $object->fk_account = GETPOSTINT('fk_account');
1306 $object->note_private = GETPOST('note_private', 'restricthtml');
1307 $object->note_public = GETPOST('note_public', 'restricthtml');
1308 $object->delivery_date = $datelivraison;
1309 $object->fk_incoterms = GETPOSTINT('incoterm_id');
1310 $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
1311 $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
1312 $object->multicurrency_tx = GETPOSTFLOAT('originmulticurrency_tx');
1313 $object->fk_project = GETPOSTINT('projectid');
1314
1315 // Fill array 'array_options' with data from add form
1316 if (!$error) {
1317 $ret = $extrafields->setOptionalsFromPost(null, $object);
1318 if ($ret < 0) {
1319 $error++;
1320 }
1321 }
1322
1323 if (!$error) {
1324 // If creation from another object of another module (Example: origin=propal, originid=1)
1325 if (!empty($origin) && !empty($originid)) {
1326 $element = $subelement = $origin;
1327 $classname = ucfirst($subelement);
1328 if ($origin == 'propal' || $origin == 'proposal') {
1329 $element = 'comm/propal';
1330 $subelement = 'propal';
1331 $classname = 'Propal';
1332 }
1333 if ($origin == 'order' || $origin == 'commande') {
1334 $element = $subelement = 'commande';
1335 $classname = 'Commande';
1336 }
1337 if ($origin == 'supplier_proposal') {
1338 $classname = 'SupplierProposal';
1339 $element = 'supplier_proposal';
1340 $subelement = 'supplier_proposal';
1341 }
1342
1343 $object->origin = $origin;
1344 $object->origin_type = $origin;
1345 $object->origin_id = $originid;
1346
1347 // Possibility to add external linked objects with hooks
1348 $object->linked_objects[$object->origin_type] = $object->origin_id;
1349 $other_linked_objects = GETPOST('other_linked_objects', 'array');
1350 if (!empty($other_linked_objects)) {
1351 $object->linked_objects = array_merge($object->linked_objects, $other_linked_objects);
1352 }
1353
1354 $id = $object->create($user);
1355 if ($id > 0) {
1356 dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
1357
1358 $srcobject = new $classname($db);
1359
1360 dol_syslog("Try to find source object origin=".$object->origin_type." originid=".$object->origin_id." to add lines");
1361 $result = $srcobject->fetch($object->origin_id);
1362 if ($result > 0) {
1363 if (empty($object->delivery_date)) {
1364 $tmpdate = $srcobject->delivery_date;
1365 $object->setDeliveryDate($user, $tmpdate);
1366 }
1367 $object->set_id_projet($user, $srcobject->fk_project);
1368
1369 $lines = $srcobject->lines;
1370 if (empty($lines) && method_exists($srcobject, 'fetch_lines')) {
1371 $srcobject->fetch_lines();
1372 $lines = $srcobject->lines;
1373 }
1374
1375 $fk_parent_line = 0;
1376 $num = count($lines);
1377
1378 for ($i = 0; $i < $num; $i++) {
1379 if (
1380 empty($lines[$i]->subprice)
1381 || $lines[$i]->qty < 0
1382 || !in_array($lines[$i]->id, $selectedLines)
1383 || $lines[$i]->special_code == SUBTOTALS_SPECIAL_CODE
1384 ) {
1385 continue;
1386 }
1387
1388 $label = (!empty($lines[$i]->label) ? $lines[$i]->label : '');
1389 $desc = (!empty($lines[$i]->desc) ? $lines[$i]->desc : '');
1390 $product_type = (!empty($lines[$i]->product_type) ? $lines[$i]->product_type : 0);
1391 // Reset fk_parent_line for no child products and special product
1392 if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) {
1393 $fk_parent_line = 0;
1394 }
1395
1396 // Extrafields
1397 if (method_exists($lines[$i], 'fetch_optionals')) { // For avoid conflicts if
1398 $lines[$i]->fetch_optionals();
1399 $array_option = $lines[$i]->array_options;
1400 } else {
1401 $array_option = array();
1402 }
1403
1404 $ref_supplier = '';
1405 $product_fourn_price_id = 0;
1406 if ($origin == "commande") {
1407 $productsupplier = new ProductFournisseur($db);
1408 $result = $productsupplier->find_min_price_product_fournisseur($lines[$i]->fk_product, $lines[$i]->qty, $object->socid);
1409 $lines[$i]->subprice = 0;
1410 if ($result > 0) {
1411 $ref_supplier = $productsupplier->ref_supplier;
1412 $product_fourn_price_id = $productsupplier->product_fourn_price_id;
1413 // we need supplier subprice
1414 foreach ($srcobject->lines as $li) {
1415 $sql = 'SELECT price, unitprice, tva_tx, remise_percent, entity, ref_fourn';
1416 $sql .= ' FROM '.MAIN_DB_PREFIX.'product_fournisseur_price';
1417 $sql .= ' WHERE fk_product = '.((int) $li->fk_product);
1418 $sql .= ' AND entity IN ('.getEntity('product_fournisseur_price').')';
1419 $sql .= ' AND fk_soc = '.((int) $object->socid);
1420 $sql .= ' ORDER BY unitprice ASC';
1421
1422 $resql = $db->query($sql);
1423 if ($resql) {
1424 $num_row = $db->num_rows($resql);
1425 if (empty($num_row)) {
1426 $li->remise_percent = 0;
1427 } else {
1428 $obj = $db->fetch_object($resql);
1429 $li->subprice = $obj->unitprice;
1430 $li->remise_percent = $obj->remise_percent;
1431 }
1432 } else {
1433 dol_print_error($db);
1434 }
1435 $db->free($resql);
1436 }
1437 }
1438 } else {
1439 $ref_supplier = $lines[$i]->ref_fourn;
1440 $product_fourn_price_id = 0;
1441 }
1442
1443 $tva_tx = $lines[$i]->tva_tx;
1444
1445 if ($origin == "commande") {
1446 $soc = new Societe($db);
1447 $soc->fetch($socid);
1448 $tva_tx = get_default_tva($soc, $mysoc, $lines[$i]->fk_product, $product_fourn_price_id);
1449 }
1450
1451 $result = $object->addline(
1452 $desc,
1453 $lines[$i]->subprice,
1454 $lines[$i]->qty,
1455 $tva_tx,
1456 $lines[$i]->localtax1_tx,
1457 $lines[$i]->localtax2_tx,
1458 $lines[$i]->fk_product > 0 ? $lines[$i]->fk_product : 0,
1459 $product_fourn_price_id,
1460 $ref_supplier,
1461 $lines[$i]->remise_percent,
1462 'HT',
1463 0,
1464 $lines[$i]->product_type,
1465 0,
1466 0,
1467 null,
1468 null,
1469 $array_option,
1470 $lines[$i]->fk_unit,
1471 0,
1472 $element,
1473 !empty($lines[$i]->id) ? $lines[$i]->id : $lines[$i]->rowid,
1474 -1,
1475 $lines[$i]->special_code
1476 );
1477
1478 if ($result < 0) {
1479 setEventMessages($object->error, $object->errors, 'errors');
1480 $error++;
1481 break;
1482 }
1483
1484 // Defined the new fk_parent_line
1485 if ($result > 0 && $lines[$i]->product_type == 9) {
1486 $fk_parent_line = $result;
1487 }
1488 }
1489
1490 // Add link between elements
1491
1492
1493 // Hooks
1494 $parameters = array('objFrom' => $srcobject);
1495 $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been
1496
1497 if ($reshook < 0) {
1498 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1499 $error++;
1500 }
1501 } else {
1502 setEventMessages($srcobject->error, $srcobject->errors, 'errors');
1503 $error++;
1504 }
1505 } else {
1506 setEventMessages($object->error, $object->errors, 'errors');
1507 $error++;
1508 }
1509 } else {
1510 $id = $object->create($user);
1511 if ($id < 0) {
1512 $error++;
1513 setEventMessages($object->error, $object->errors, 'errors');
1514 }
1515 }
1516 }
1517
1518 if (isModEnabled('category')) {
1519 $categories = GETPOST('categories', 'array:int');
1520 if (method_exists($object, 'setCategories')) {
1521 $object->setCategories($categories);
1522 }
1523 }
1524
1525 if ($error) {
1526 $langs->load("errors");
1527 $db->rollback();
1528 $action = 'create';
1529 } else {
1530 $db->commit();
1531 header("Location: ".$_SERVER['PHP_SELF']."?id=".urlencode((string) ($id)));
1532 exit;
1533 }
1534 }
1535 }
1536
1537 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
1538 if ($action == 'addcontact' && $permissiontoadd) {
1539 if ($object->id > 0) {
1540 $contactid = (GETPOST('userid') ? GETPOSTINT('userid') : GETPOSTINT('contactid'));
1541 $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
1542 $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09'));
1543 }
1544
1545 if ($result >= 0) {
1546 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1547 exit;
1548 } else {
1549 if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
1550 $langs->load("errors");
1551 setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
1552 } else {
1553 setEventMessages($object->error, $object->errors, 'errors');
1554 }
1555 }
1556 } elseif ($action == 'swapstatut' && $object->id > 0 && $permissiontoadd) {
1557 // bascule du statut d'un contact
1558 $result = $object->swapContactStatus(GETPOSTINT('ligne'));
1559 } elseif ($action == 'deletecontact' && $object->id > 0 && $permissiontoadd) {
1560 // Efface un contact
1561 $result = $object->delete_contact(GETPOSTINT("lineid"));
1562
1563 if ($result >= 0) {
1564 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1565 exit;
1566 } else {
1567 dol_print_error($db);
1568 }
1569 }
1570 }
1571}
1572
1573
1574/*
1575 * View
1576 */
1577
1578$form = new Form($db);
1579$formfile = new FormFile($db);
1580$formorder = new FormOrder($db);
1581$productstatic = new Product($db);
1582if (isModEnabled('project')) {
1583 $formproject = new FormProjets($db);
1584}
1585
1586$title = $object->ref." - ".$langs->trans('Card');
1587if ($action == 'create') {
1588 $title = $langs->trans("NewOrderSupplier");
1589}
1590$help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores';
1591llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-supplier-order page-card');
1592
1593$now = dol_now();
1594
1595if ($action == 'create') {
1596 print load_fiche_titre($langs->trans('NewOrderSupplier'), '', 'supplier_order');
1597
1599
1600 $currency_code = $conf->currency;
1601
1602 $societe = '';
1603 $objectsrc = null;
1604
1605 if ($socid > 0) {
1606 $societe = new Societe($db);
1607 $societe->fetch($socid);
1608 }
1609
1610 if (!empty($origin) && !empty($originid)) {
1611 // Parse element/subelement (ex: project_task)
1612 $element = $subelement = $origin;
1613 $classname = ucfirst($subelement);
1614 $regs = array();
1615 if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
1616 $element = $regs[1];
1617 $subelement = $regs[2];
1618 }
1619
1620 if ($origin == 'propal' || $origin == 'proposal') {
1621 $classname = 'Propal';
1622 $element = 'comm/propal';
1623 $subelement = 'propal';
1624 }
1625 if ($origin == 'order' || $origin == 'commande') {
1626 $classname = 'Commande';
1627 $element = $subelement = 'commande';
1628 }
1629 if ($origin == 'supplier_proposal') {
1630 $classname = 'SupplierProposal';
1631 $element = 'supplier_proposal';
1632 $subelement = 'supplier_proposal';
1633 }
1634
1635
1636 dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
1637
1638 $objectsrc = new $classname($db);
1639 $objectsrc->fetch($originid);
1640 if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
1641 $objectsrc->fetch_lines();
1642 }
1643 $objectsrc->fetch_thirdparty();
1644
1645 // Replicate extrafields
1646 $objectsrc->fetch_optionals();
1647 $object->array_options = $objectsrc->array_options;
1648
1649 $projectid = (int) $objectsrc->fk_project;
1650 $ref_client = (!empty($objectsrc->ref_client) ? $objectsrc->ref_client : '');
1651 $fk_account = 0;
1652 if ($origin == "commande") {
1653 $cond_reglement_id = 0;
1654 $deposit_percent = 0;
1655 $mode_reglement_id = 0;
1656 $datelivraison = '';
1657 $objectsrc->note_private = '';
1658 $objectsrc->note_public = '';
1659 if ($societe = $object->thirdparty) {
1660 $cond_reglement_id = $societe->cond_reglement_supplier_id;
1661 $deposit_percent = $societe->deposit_percent;
1662 $mode_reglement_id = $societe->mode_reglement_supplier_id;
1663 if (isModEnabled("multicurrency")) {
1664 $currency_code = $societe->multicurrency_code;
1665 if (getDolGlobalString('MULTICURRENCY_USE_ORIGIN_TX')) {
1666 $currency_tx = $societe->multicurrency_tx;
1667 }
1668 }
1669 }
1670 } else {
1671 $soc = $objectsrc->thirdparty;
1672
1673 $cond_reglement_id = (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_id) ? $soc->cond_reglement_id : 0));
1674 $deposit_percent = (!empty($objectsrc->deposit_percent) ? $objectsrc->deposit_percent : (!empty($soc->deposit_percent) ? $soc->deposit_percent : 0));
1675 $mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_id) ? $soc->mode_reglement_id : 0));
1676 $fk_account = (!empty($objectsrc->fk_account) ? $objectsrc->fk_account : (!empty($soc->fk_account) ? $soc->fk_account : 0));
1677 $availability_id = (!empty($objectsrc->availability_id) ? $objectsrc->availability_id : (!empty($soc->availability_id) ? $soc->availability_id : 0));
1678 $shipping_method_id = (!empty($objectsrc->shipping_method_id) ? $objectsrc->shipping_method_id : (!empty($soc->shipping_method_id) ? $soc->shipping_method_id : 0));
1679 $demand_reason_id = (!empty($objectsrc->demand_reason_id) ? $objectsrc->demand_reason_id : (!empty($soc->demand_reason_id) ? $soc->demand_reason_id : 0));
1680 //$remise_percent = (!empty($objectsrc->remise_percent) ? $objectsrc->remise_percent : (!empty($soc->remise_supplier_percent) ? $soc->remise_supplier_percent : 0));
1681 //$remise_absolue = (!empty($objectsrc->remise_absolue) ? $objectsrc->remise_absolue : (!empty($soc->remise_absolue) ? $soc->remise_absolue : 0));
1682 $dateinvoice = getDolGlobalString('MAIN_AUTOFILL_DATE') ? '' : -1;
1683
1684 $datelivraison = (!empty($objectsrc->delivery_date) ? $objectsrc->delivery_date : '');
1685
1686 if (isModEnabled("multicurrency")) {
1687 if (!empty($objectsrc->multicurrency_code)) {
1688 $currency_code = $objectsrc->multicurrency_code;
1689 }
1690 if (getDolGlobalString('MULTICURRENCY_USE_ORIGIN_TX') && !empty($objectsrc->multicurrency_tx)) {
1691 $currency_tx = $objectsrc->multicurrency_tx;
1692 }
1693 }
1694
1695 $note_private = $object->getDefaultCreateValueFor('note_private', (!empty($objectsrc->note_private) ? $objectsrc->note_private : null));
1696 $note_public = $object->getDefaultCreateValueFor('note_public', (!empty($objectsrc->note_public) ? $objectsrc->note_public : null));
1697
1698 // Object source contacts list
1699 $srccontactslist = $objectsrc->liste_contact(-1, 'external', 1);
1700 }
1701 } else {
1702 $cond_reglement_id = !empty($societe->cond_reglement_supplier_id) ? $societe->cond_reglement_supplier_id : 0;
1703 $deposit_percent = !empty($societe->deposit_percent) ? $societe->deposit_percent : 0;
1704 $mode_reglement_id = !empty($societe->mode_reglement_supplier_id) ? $societe->mode_reglement_supplier_id : 0;
1705
1706 if (isModEnabled("multicurrency") && !empty($societe->multicurrency_code)) {
1707 $currency_code = $societe->multicurrency_code;
1708 }
1709
1710 $note_private = $object->getDefaultCreateValueFor('note_private');
1711 $note_public = $object->getDefaultCreateValueFor('note_public');
1712 }
1713
1714 // If not defined, set default value from constant
1715 if (empty($cond_reglement_id) && getDolGlobalString('SUPPLIER_ORDER_DEFAULT_PAYMENT_TERM_ID')) {
1716 $cond_reglement_id = getDolGlobalString('SUPPLIER_ORDER_DEFAULT_PAYMENT_TERM_ID');
1717 }
1718 if (empty($mode_reglement_id) && getDolGlobalString('SUPPLIER_ORDER_DEFAULT_PAYMENT_MODE_ID')) {
1719 $mode_reglement_id = getDolGlobalString('SUPPLIER_ORDER_DEFAULT_PAYMENT_MODE_ID');
1720 }
1721 if (GETPOSTISSET('cond_reglement_id_deposit_percent')) {
1722 $deposit_percent = GETPOSTFLOAT('cond_reglement_id_deposit_percent');
1723 }
1724
1725 print '<form name="add" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1726 print '<input type="hidden" name="token" value="'.newToken().'">';
1727 print '<input type="hidden" name="action" value="add">';
1728 print '<input type="hidden" name="remise_percent" value="'.(empty($soc->remise_supplier_percent) ? '' : $soc->remise_supplier_percent).'">';
1729 print '<input type="hidden" name="origin" value="'.$origin.'">';
1730 print '<input type="hidden" name="originid" value="'.$originid.'">';
1731 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
1732 if ($backtopage) {
1733 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1734 }
1735 if ($backtopageforcancel) {
1736 print '<input type="hidden" name="backtopageforcancel" value="'.$backtopageforcancel.'">';
1737 }
1738
1739 if (!empty($currency_tx)) {
1740 print '<input type="hidden" name="originmulticurrency_tx" value="'.$currency_tx.'">';
1741 }
1742
1743 print dol_get_fiche_head(array());
1744
1745 // Call Hook tabContentCreateSupplierOrder
1746 $parameters = array();
1747 // Note that $action and $object may be modified by hook
1748 $reshook = $hookmanager->executeHooks('tabContentCreateSupplierOrder', $parameters, $object, $action);
1749 if (empty($reshook)) {
1750 print '<table class="border centpercent">';
1751
1752 // Ref
1753 print '<tr><td class="titlefieldcreate">'.$langs->trans('Ref').'</td><td>'.$langs->trans('Draft').'</td></tr>';
1754
1755 // Third party
1756 print '<tr><td class="fieldrequired">'.$langs->trans('Supplier').'</td>';
1757 print '<td>';
1758
1759 if (!empty($societe->id) && $societe->id > 0) {
1760 print $societe->getNomUrl(1, 'supplier');
1761 print '<input type="hidden" name="socid" value="'.$societe->id.'">';
1762 } else {
1763 $filter = '((s.fournisseur:=:1) AND (s.status:=:1))';
1764 print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company((empty($socid) ? '' : $socid), 'socid', $filter, 'SelectThirdParty', 1, 0, array(), 0, 'minwidth175 maxwidth500 widthcentpercentminusxx');
1765 // reload page to retrieve customer information
1766 if (!getDolGlobalString('RELOAD_PAGE_ON_SUPPLIER_CHANGE_DISABLED')) {
1767 print '<script>
1768 $(document).ready(function() {
1769 $("#socid").change(function() {
1770 console.log("We have changed the company - Reload page");
1771 // reload page
1772 $("input[name=action]").val("create");
1773 $("input[name=changecompany]").val("1");
1774 $("form[name=add]").submit();
1775 });
1776 });
1777 </script>';
1778 }
1779 print ' <a href="'.DOL_URL_ROOT.'/societe/card.php?action=create&client=0&fournisseur=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create').'"><span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("AddThirdParty").'"></span></a>';
1780 }
1781 print '</td>';
1782
1783 if (!empty($societe->id) && $societe->id > 0) {
1784 // Discounts for third party
1785 print '<tr><td>'.$langs->trans('Discounts').'</td><td>';
1786
1787 $absolute_discount = $societe->getAvailableDiscounts(null, '', 0, 1);
1788
1789 $thirdparty = $societe;
1790 $discount_type = 1;
1791 $backtopage = urlencode($_SERVER["PHP_SELF"].'?socid='.$thirdparty->id.'&action='.$action.'&origin='.GETPOST('origin').'&originid='.GETPOST('originid'));
1792 include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
1793
1794 print '</td></tr>';
1795 }
1796
1797 // Ref supplier
1798 print '<tr><td>'.$langs->trans('RefSupplier').'</td><td><input name="refsupplier" type="text"></td>';
1799 print '</tr>';
1800
1801 // Payment term
1802 print '<tr><td class="nowrap">'.$langs->trans('PaymentConditionsShort').'</td><td>';
1803 print img_picto('', 'payment', 'class="pictofixedwidth"');
1804 print $form->getSelectConditionsPaiements((GETPOSTISSET('cond_reglement_id') && GETPOST('cond_reglement_id') != 0) ? GETPOSTINT('cond_reglement_id') : $cond_reglement_id, 'cond_reglement_id', 1, 1, 0, 'maxwidth200 widthcentpercentminusx', $deposit_percent);
1805 print '</td></tr>';
1806
1807 // Payment mode
1808 print '<tr><td>'.$langs->trans('PaymentMode').'</td><td>';
1809 print img_picto('', 'bank', 'class="pictofixedwidth"');
1810 $form->select_types_paiements((GETPOSTISSET('mode_reglement_id') && GETPOSTINT('mode_reglement_id') != 0) ? GETPOST('mode_reglement_id') : $mode_reglement_id, 'mode_reglement_id');
1811 print '</td></tr>';
1812
1813 // Planned delivery date
1814 print '<tr><td>';
1815 print $langs->trans('DateDeliveryPlanned');
1816 print '</td>';
1817 print '<td>';
1818 $usehourmin = 0;
1819 if (getDolGlobalString('SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE')) {
1820 $usehourmin = 1;
1821 }
1822 print img_picto('', 'action', 'class="pictofixedwidth"');
1823 print $form->selectDate($datelivraison ? $datelivraison : -1, 'liv_', $usehourmin, $usehourmin, 0, "set", 1, 1);
1824 print '</td></tr>';
1825
1826 // Bank Account
1827 if (getDolGlobalString('BANK_ASK_PAYMENT_BANK_DURING_SUPPLIER_ORDER') && isModEnabled("bank")) {
1828 $langs->load("bank");
1829 print '<tr><td>'.$langs->trans('BankAccount').'</td><td>';
1830 print img_picto('', 'bank_account', 'class="pictofixedwidth"');
1831 $form->select_comptes($fk_account ?? '', 'fk_account', 0, '', 1);
1832 print '</td></tr>';
1833 }
1834
1835 // Project
1836 if (isModEnabled('project')) {
1837 $formproject = new FormProjets($db);
1838
1839 $langs->load('projects');
1840 print '<tr><td>'.$langs->trans('Project').'</td><td>';
1841 if ($socid > 0) { // external user
1842 $projSocFilter = $socid;
1843 } elseif ((int) $societe->id == 0 || getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS')) {
1844 $projSocFilter = -1;
1845 } else {
1846 $projSocFilter = $societe->id;
1847 }
1848 print img_picto('', 'project', 'class="pictofixedwidth"').$formproject->select_projects($projSocFilter, $projectid, 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500');
1849 print ' &nbsp; <a href="'.DOL_URL_ROOT.'/projet/card.php?action=create&status=1'.(!empty($societe->id) ? '&socid='.$societe->id : "").'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create'.(!empty($societe->id) ? '&socid='.$societe->id : "")).'"><span class="fa fa-plus-circle valignmiddle" title="'.$langs->trans("AddProject").'"></span></a>';
1850 print '</td></tr>';
1851 }
1852
1853 // Incoterms
1854 if (isModEnabled('incoterm')) {
1855 $fkincoterms = (!empty($object->fk_incoterms) ? $object->fk_incoterms : ($socid > 0 ? $societe->fk_incoterms : ''));
1856 $locincoterms = (!empty($object->location_incoterms) ? $object->location_incoterms : ($socid > 0 ? $societe->location_incoterms : ''));
1857 print '<tr>';
1858 print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $object->label_incoterms, 1).'</label></td>';
1859 print '<td class="maxwidthonsmartphone">';
1860 print img_picto('', 'incoterm', 'class="pictofixedwidth"');
1861 print $form->select_incoterms($fkincoterms, $locincoterms);
1862 print '</td></tr>';
1863 }
1864
1865 // Multicurrency
1866 if (isModEnabled("multicurrency")) {
1867 print '<tr>';
1868 print '<td>'.$form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0).'</td>';
1869 print '<td class="maxwidthonsmartphone">';
1870 print img_picto('', 'currency', 'class="pictofixedwidth"');
1871 print $form->selectMultiCurrency($currency_code, 'multicurrency_code');
1872 print '</td></tr>';
1873 }
1874
1875 // Categories
1876 if (isModEnabled("category")) {
1877 print '<tr><td>'.$langs->trans("Categories").'</td><td colspan="3">';
1878 print $form->selectCategories(Categorie::TYPE_SUPPLIER_ORDER, 'categories', $object);
1879 print "</td></tr>";
1880 }
1881
1882 print '<tr><td>'.$langs->trans('NotePublic').'</td>';
1883 print '<td>';
1884 $doleditor = new DolEditor('note_public', isset($note_public) ? $note_public : GETPOST('note_public', 'restricthtml'), '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
1885 print $doleditor->Create(1);
1886 print '</td>';
1887 //print '<textarea name="note_public" wrap="soft" cols="60" rows="'.ROWS_5.'"></textarea>';
1888 print '</tr>';
1889
1890 print '<tr><td>'.$langs->trans('NotePrivate').'</td>';
1891 print '<td>';
1892 $doleditor = new DolEditor('note_private', isset($note_private) ? $note_private : GETPOST('note_private', 'restricthtml'), '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
1893 print $doleditor->Create(1);
1894 print '</td>';
1895 //print '<td><textarea name="note_private" wrap="soft" cols="60" rows="'.ROWS_5.'"></textarea></td>';
1896 print '</tr>';
1897
1898 if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
1899 print "\n<!-- ".$classname." info -->";
1900 print "\n";
1901 print '<input type="hidden" name="amount" value="'.$objectsrc->total_ht.'">'."\n";
1902 print '<input type="hidden" name="total" value="'.$objectsrc->total_ttc.'">'."\n";
1903 print '<input type="hidden" name="tva" value="'.$objectsrc->total_tva.'">'."\n";
1904 print '<input type="hidden" name="origin" value="'.$objectsrc->element.'">';
1905 print '<input type="hidden" name="originid" value="'.$objectsrc->id.'">';
1906
1907 $newclassname = $classname;
1908 print '<tr><td>'.$langs->trans($newclassname).'</td><td>'.$objectsrc->getNomUrl(1, 'supplier').'</td></tr>';
1909 print '<tr><td>'.$langs->trans('AmountHT').'</td><td>'.price($objectsrc->total_ht).'</td></tr>';
1910 print '<tr><td>'.$langs->trans('AmountVAT').'</td><td>'.price($objectsrc->total_tva)."</td></tr>";
1911 if ($mysoc->localtax1_assuj == "1" || $objectsrc->total_localtax1 != 0) { // Localtax1 RE
1912 print '<tr><td>'.$langs->transcountry("AmountLT1", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax1)."</td></tr>";
1913 }
1914
1915 if ($mysoc->localtax2_assuj == "1" || $objectsrc->total_localtax2 != 0) { // Localtax2 IRPF
1916 print '<tr><td>'.$langs->transcountry("AmountLT2", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax2)."</td></tr>";
1917 }
1918
1919 print '<tr><td>'.$langs->trans('AmountTTC').'</td><td>'.price($objectsrc->total_ttc)."</td></tr>";
1920
1921 if (isModEnabled("multicurrency")) {
1922 print '<tr><td>'.$langs->trans('MulticurrencyAmountHT').'</td><td>'.price($objectsrc->multicurrency_total_ht).'</td></tr>';
1923 print '<tr><td>'.$langs->trans('MulticurrencyAmountVAT').'</td><td>'.price($objectsrc->multicurrency_total_tva).'</td></tr>';
1924 print '<tr><td>'.$langs->trans('MulticurrencyAmountTTC').'</td><td>'.price($objectsrc->multicurrency_total_ttc).'</td></tr>';
1925 }
1926 }
1927
1928 // Other options
1929 $parameters = array();
1930 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1931 print $hookmanager->resPrint;
1932
1933 if (empty($reshook)) {
1934 if (getDolGlobalString('THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_SUPPLIER_ORDER') && !empty($societe->id)) {
1935 // copy from thirdparty
1936 $tpExtrafields = new ExtraFields($db);
1937 $tpExtrafieldLabels = $tpExtrafields->fetch_name_optionals_label($societe->table_element);
1938 if ($societe->fetch_optionals() > 0) {
1939 $object->array_options = array_merge($object->array_options, $societe->array_options);
1940 }
1941 }
1942
1943 print $object->showOptionals($extrafields, 'create');
1944 }
1945
1946 // Bouton "Create Draft"
1947 print "</table>\n";
1948 }
1949 print dol_get_fiche_end();
1950
1951 print $form->buttonsSaveCancel("CreateDraft");
1952
1953 // Show origin lines
1954 if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
1955 $title = $langs->trans('ProductsAndServices');
1956 print load_fiche_titre($title);
1957
1958 print '<div class="div-table-responsive-no-min">';
1959 print '<table class="noborder centpercent">';
1960
1961 $selectedLines = array();
1962
1963 $objectsrc->printOriginLinesList('', $selectedLines);
1964
1965 print '</table>';
1966 print '</div>';
1967 }
1968 print "</form>\n";
1969} elseif (!empty($object->id)) {
1970 // view
1971 $result = $object->fetch($id, $ref);
1972 $object->fetch_thirdparty();
1973
1974 $societe = $object->thirdparty;
1975
1976 $author = new User($db);
1977 $author->fetch($object->user_author_id);
1978
1979 $head = ordersupplier_prepare_head($object);
1980
1981 $title = $langs->trans("SupplierOrder");
1982 print dol_get_fiche_head($head, 'card', $title, -1, 'order');
1983
1984
1985 $formconfirm = '';
1986
1987 // Confirmation de la suppression de la commande
1988 if ($action == 'delete') {
1989 $arrayAjouts = array();
1990 $heightModal = 0;
1991 $widthModal = 500;
1992
1993 // TODO We must find line already recorded in stock, not lines dispatched (stock recording may not have been done
1994 // even if dispatched in llx_receptiondet_batch).
1995 // For example to know if stock movement were already record, we may look at stock movements in llx_stock_movement linked to a reception
1996 // that is linked to the purchase order.
1997 /* $dispatchedLines = $object->getStockMovementLines();
1998
1999 if (!empty($dispatchedLines)) {
2000 $arrayAjouts = array(
2001 array(
2002 'type' => 'other',
2003 'value' => img_warning() . " " . $langs->trans('ExistingDipatchLines')
2004 ),
2005 array('type' => 'separator'),
2006 array(
2007 'type' => 'select',
2008 'id' => 'stockDeleteSelect',
2009 'name' => 'stockDelete',
2010 'label' => $langs->trans('ConfirmDeleteDispatchedLines'),
2011 'values' => array(1 => $langs->trans('Yes'), 0 => $langs->trans('No')),
2012 'select_show_empty' => false
2013 )
2014 );
2015 $heightModal = 300;
2016 $widthModal = "70%";
2017 }
2018 */
2019
2020 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.((int) $object->id), $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', $arrayAjouts, 0, 2, $heightModal, $widthModal);
2021 }
2022
2023 // Clone confirmation
2024 if ($action == 'clone') {
2025 $filter = '(s.fournisseur:=:1)';
2026 // Create an array for form
2027 $formquestion = array(
2028 array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOSTINT('socid'), 'socid', $filter))
2029 );
2030 // Paiement incomplet. On demande si motif = escompte ou autre
2031 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneOrder', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
2032 }
2033
2034 // Confirmation de la validation
2035 if ($action == 'valid') {
2036 $object->date_commande = dol_now();
2037
2038 // We check if number is temporary number
2039 if (preg_match('/^[\‍(]?PROV/i', (string) $object->ref) || empty($object->ref)) { // empty should not happened, but when it occurs, the test save life
2040 $newref = $object->getNextNumRef($object->thirdparty);
2041 } else {
2042 $newref = (string) $object->ref;
2043 }
2044
2045 if ($newref < 0) {
2046 setEventMessages($object->error, $object->errors, 'errors');
2047 $action = '';
2048 } else {
2049 $text = $langs->trans('ConfirmValidateOrder', $newref);
2050 if (isModEnabled('notification')) {
2051 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2052 $notify = new Notify($db);
2053 $text .= '<br>';
2054 $text .= $notify->confirmMessage('ORDER_SUPPLIER_VALIDATE', $object->socid, $object);
2055 }
2056
2057 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateOrder'), $text, 'confirm_valid', '', 0, 1);
2058 }
2059 }
2060
2061 // Confirm approval
2062 if ($action == 'approve' || $action == 'approve2') {
2063 $qualified_for_stock_change = 0;
2064 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
2065 $qualified_for_stock_change = $object->hasProductsOrServices(2);
2066 } else {
2067 $qualified_for_stock_change = $object->hasProductsOrServices(1);
2068 }
2069
2070 $formquestion = array();
2071 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER') && $qualified_for_stock_change) {
2072 $langs->load("stocks");
2073 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2074 $formproduct = new FormProduct($db);
2075 $forcecombo = 0;
2076 if ($conf->browser->name == 'ie') {
2077 $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2078 }
2079 $formquestion = array(
2080 //'text' => $langs->trans("ConfirmClone"),
2081 //array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2082 //array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2083 array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockIncrease"), 'value' => $formproduct->selectWarehouses(GETPOSTINT('idwarehouse'), 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
2084 );
2085 }
2086 $text = $langs->trans("ConfirmApproveThisOrder", $object->ref);
2087 if (isModEnabled('notification')) {
2088 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2089 $notify = new Notify($db);
2090 $text .= '<br>';
2091 $text .= $notify->confirmMessage('ORDER_SUPPLIER_APPROVE', $object->socid, $object);
2092 }
2093
2094 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("ApproveThisOrder"), $text, "confirm_".$action, $formquestion, 1, 1, 240);
2095 }
2096
2097 // Confirmation of disapproval
2098 if ($action == 'refuse') {
2099 $formquestion = array(
2100 array(
2101 'type' => 'text',
2102 'name' => 'refuse_note',
2103 'label' => $langs->trans("Reason"),
2104 'value' => '',
2105 'morecss' => 'minwidth300'
2106 )
2107 );
2108 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=$object->id", $langs->trans("DenyingThisOrder"), $langs->trans("ConfirmDenyingThisOrder", $object->ref), "confirm_refuse", $formquestion, 0, 1);
2109 }
2110
2111 // Confirmation of cancellation
2112 if ($action == 'cancel') {
2113 $formquestion = array(
2114 array(
2115 'type' => 'text',
2116 'name' => 'cancel_note',
2117 'label' => $langs->trans("Reason"),
2118 'value' => '',
2119 'morecss' => 'minwidth300'
2120 )
2121 );
2122 if (isModEnabled('notification')) {
2123 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2124 $notify = new Notify($db);
2125 $text = '';
2126 $text .= '<br>';
2127 $text .= $notify->confirmMessage('ORDER_SUPPLIER_CANCEL', $object->socid, $object);
2128 }
2129 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=$object->id", $langs->trans("Cancel"), $langs->trans("ConfirmCancelThisOrder", $object->ref), "confirm_cancel", $formquestion, 0, 1);
2130 }
2131
2132 // Confirmation de l'envoi de la commande
2133 if ($action == 'commande') {
2134 $formquestion = array();
2135 $date_com = dol_mktime(GETPOSTINT('rehour'), GETPOSTINT('remin'), GETPOSTINT('resec'), GETPOSTINT("remonth"), GETPOSTINT("reday"), GETPOSTINT("reyear"));
2136 if (isModEnabled('notification')) {
2137 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2138 $notify = new Notify($db);
2139 $text = '';
2140 $text .= '<br>';
2141 $text .= $notify->confirmMessage('ORDER_SUPPLIER_SUBMIT', $object->socid, $object);
2142 }
2143 if (isModEnabled('webhook')) {
2144 require_once DOL_DOCUMENT_ROOT.'/webhook/class/target.class.php';
2145 $targetstatic = new Target($db);
2146 if ($targetstatic->isTriggerCodeManualTarget('ORDER_SUPPLIER_SUBMIT') > 0) {
2147 $formquestion[] = array('type' => 'checkbox', 'name' => 'manual_trigger_send', 'label' => $langs->trans("QuestionSendManualTrigger"));
2148 }
2149 }
2150 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id."&datecommande=".$date_com."&methode=".GETPOST("methodecommande")."&comment=".urlencode(GETPOST("comment")), $langs->trans("MakeOrder"), $langs->trans("ConfirmMakeOrder", dol_print_date($date_com, 'day')), "confirm_commande", $formquestion, 0, 2);
2151 }
2152
2153 // Confirmation to delete line
2154 if ($action == 'ask_deleteline') {
2155 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 0, 1);
2156 }
2157
2158 $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
2159 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2160 if (empty($reshook)) {
2161 $formconfirm .= $hookmanager->resPrint;
2162 } elseif ($reshook > 0) {
2163 $formconfirm = $hookmanager->resPrint;
2164 }
2165
2166 // Print form confirm
2167 print $formconfirm;
2168
2169
2170 // Supplier order card
2171
2172 $linkback = '<a href="'.DOL_URL_ROOT.'/fourn/commande/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
2173
2174 $morehtmlref = '<div class="refidno">';
2175 // Ref supplier
2176 $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, (int) $usercancreate, 'string', '', 0, 1);
2177 $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $usercancreate, 'string'.(isset($conf->global->THIRDPARTY_REF_INPUT_SIZE) ? ':' . getDolGlobalString('THIRDPARTY_REF_INPUT_SIZE') : ''), '', null, null, '', 1);
2178 // Thirdparty
2179 $morehtmlref .= '<br>';
2180 if (getDolGlobalString('MAIN_CAN_EDIT_SUPPLIER_ON_SUPPLIER_ORDER') && !empty($usercancreate) && $action == 'edit_thirdparty') {
2181 $morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
2182 $morehtmlref .= '<input type="hidden" name="action" value="set_thirdparty">';
2183 $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
2184 $filter = '(s.fournisseur:=:1)';
2185 $morehtmlref .= $form->select_company($object->thirdparty->id, 'new_socid', $filter, '', 0, 0, array(), 0, 'minwidth300');
2186 $morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
2187 $morehtmlref .= '</form>';
2188 }
2189 if (!getDolGlobalString('MAIN_CAN_EDIT_SUPPLIER_ON_SUPPLIER_ORDER') || $action != 'edit_thirdparty') {
2190 if (getDolGlobalString('MAIN_CAN_EDIT_SUPPLIER_ON_SUPPLIER_ORDER') && $object->status == CommandeFournisseur::STATUS_DRAFT) {
2191 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=edit_thirdparty&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetThirdParty')).'</a>';
2192 }
2193 $morehtmlref .= $object->thirdparty->getNomUrl(1, 'supplier');
2194 if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
2195 $morehtmlref .= ' (<a href="'.DOL_URL_ROOT.'/fourn/commande/list.php?socid='.$object->thirdparty->id.'&search_company='.urlencode($object->thirdparty->name).'">'.$langs->trans("OtherOrders").'</a>)';
2196 }
2197 }
2198
2199 // Project
2200 if (isModEnabled('project')) {
2201 $langs->load("projects");
2202 $morehtmlref .= '<br>';
2203 if ($permissiontoadd) {
2204 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
2205 if ($action != 'classify' && $caneditproject) {
2206 $morehtmlref .= '<a class="editfielda" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'classify', 'id' => $object->id], true).'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
2207 }
2208 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (!getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') ? $object->socid : -1), (string) $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 1, 0, 0, 1, '', 'maxwidth300');
2209 } else {
2210 if (!empty($object->fk_project)) {
2211 $proj = new Project($db);
2212 $proj->fetch($object->fk_project);
2213 $morehtmlref .= $proj->getNomUrl(1);
2214 if ($proj->title) {
2215 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
2216 }
2217 }
2218 }
2219 }
2220 $morehtmlref .= '</div>';
2221
2222
2223 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
2224
2225 // Call Hook tabContentViewSupplierOrder
2226 $parameters = array();
2227 // Note that $action and $object may be modified by hook
2228 $reshook = $hookmanager->executeHooks('tabContentViewSupplierOrder', $parameters, $object, $action);
2229 if (empty($reshook)) {
2230 print '<div class="fichecenter">';
2231 print '<div class="fichehalfleft">';
2232 print '<div class="underbanner clearboth"></div>';
2233
2234 print '<table class="border tableforfield centpercent">';
2235
2236 // Date
2237 if ($object->methode_commande_id > 0) {
2238 $usehourmin = 0;
2239 if (getDolGlobalString('SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE')) {
2240 $usehourmin = 1;
2241 }
2242 print '<tr><td class="titlefield">'.$langs->trans("Date").'</td><td>';
2243 print $object->date_commande ? dol_print_date($object->date_commande, $usehourmin ? 'dayhour' : 'day') : '';
2244 if ($object->hasDelay() && !empty($object->delivery_date) && !empty($object->date_commande)) {
2245 print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
2246 }
2247 print "</td></tr>";
2248
2249 if ($object->methode_commande) {
2250 print '<tr><td>'.$langs->trans("Method").'</td><td>'.$object->getInputMethod().'</td></tr>';
2251 }
2252 }
2253
2254 // Author
2255 print '<tr><td class="titlefield">'.$langs->trans("AuthorRequest").'</td>';
2256 print '<td>'.$author->getNomUrl(-1, '', 0, 0, 0).'</td>';
2257 print '</tr>';
2258
2259 // Relative and absolute discounts
2260 if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) {
2261 $filterabsolutediscount = "fk_invoice_supplier_source IS NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
2262 $filtercreditnote = "fk_invoice_supplier_source IS NOT NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
2263 } else {
2264 $filterabsolutediscount = "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')";
2265 $filtercreditnote = "fk_invoice_supplier_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS PAID)%')";
2266 }
2267
2268 $absolute_discount = $societe->getAvailableDiscounts(null, $filterabsolutediscount, 0, 1);
2269 $absolute_creditnote = $societe->getAvailableDiscounts(null, $filtercreditnote, 0, 1);
2270 $absolute_discount = price2num($absolute_discount, 'MT');
2271 $absolute_creditnote = price2num($absolute_creditnote, 'MT');
2272
2273 print '<tr><td class="titlefield">'.$langs->trans('Discounts').'</td><td>';
2274
2275 $thirdparty = $societe;
2276 $discount_type = 1;
2277 $backtopage = urlencode($_SERVER["PHP_SELF"].'?id='.$object->id);
2278 include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
2279
2280 print '</td></tr>';
2281
2282 // Default terms of the settlement
2283 $langs->load('bills');
2284 print '<tr><td class="nowrap">';
2285 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
2286 print $langs->trans('PaymentConditions');
2287 print '<td>';
2288 if ($action != 'editconditions' && $permissiontoadd) {
2289 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editconditions&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetConditions'), 1).'</a></td>';
2290 }
2291 print '</tr></table>';
2292 print '</td><td>';
2293 if ($action == 'editconditions') {
2294 $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->cond_reglement_id, 'cond_reglement_id', 1, '', 1, $object->deposit_percent);
2295 } else {
2296 $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->cond_reglement_id, 'none', 1, '', 1, $object->deposit_percent);
2297 }
2298 print "</td>";
2299 print '</tr>';
2300
2301 // Mode of payment
2302 $langs->load('bills');
2303 print '<tr><td class="nowrap">';
2304 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
2305 print $langs->trans('PaymentMode');
2306 print '</td>';
2307 if ($action != 'editmode' && $permissiontoadd) {
2308 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editmode&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetMode'), 1).'</a></td>';
2309 }
2310 print '</tr></table>';
2311 print '</td><td>';
2312 if ($action == 'editmode') {
2313 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->mode_reglement_id, 'mode_reglement_id', 'DBIT', 1, 1);
2314 } else {
2315 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->mode_reglement_id, 'none');
2316 }
2317 print '</td></tr>';
2318
2319 // Bank Account
2320 if (getDolGlobalString('BANK_ASK_PAYMENT_BANK_DURING_SUPPLIER_ORDER') && isModEnabled("bank")) {
2321 print '<tr><td class="nowrap">';
2322 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
2323 print $langs->trans('BankAccount');
2324 print '<td>';
2325 if ($action != 'editbankaccount' && $permissiontoadd) {
2326 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>';
2327 }
2328 print '</tr></table>';
2329 print '</td><td>';
2330 if ($action == 'editbankaccount') {
2331 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'fk_account', 1);
2332 } else {
2333 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'none');
2334 }
2335 print '</td>';
2336 print '</tr>';
2337 }
2338
2339 // Delivery delay (in days)
2340 print '<tr>';
2341 print '<td>'.$langs->trans('NbDaysToDelivery').'&nbsp;'.img_picto($langs->trans('DescNbDaysToDelivery'), 'info', 'style="cursor:help"').'</td>';
2342 print '<td>'.$object->getMaxDeliveryTimeDay($langs).'</td>';
2343 print '</tr>';
2344
2345 // Delivery date planned
2346 print '<tr><td>';
2347 print '<table class="nobordernopadding centpercent"><tr><td>';
2348 print $langs->trans('DateDeliveryPlanned');
2349 print '</td>';
2350 if ($action != 'editdate_livraison') {
2351 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editdate_livraison&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetDeliveryDate'), 1).'</a></td>';
2352 }
2353 print '</tr></table>';
2354 print '</td><td>';
2355 if ($action == 'editdate_livraison') {
2356 print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2357 print '<input type="hidden" name="token" value="'.newToken().'">';
2358 print '<input type="hidden" name="action" value="setdate_livraison">';
2359 $usehourmin = 0;
2360 if (getDolGlobalString('SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE')) {
2361 $usehourmin = 1;
2362 }
2363 print $form->selectDate($object->delivery_date ? $object->delivery_date : -1, 'liv_', $usehourmin, $usehourmin, 0, "setdate_livraison");
2364 print '<input type="submit" class="button button-edit smallpaddingimp valign middle" value="'.$langs->trans('Modify').'">';
2365 print '</form>';
2366 } else {
2367 $usehourmin = 'day';
2368 if (getDolGlobalString('SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE')) {
2369 $usehourmin = 'dayhour';
2370 }
2371 print $object->delivery_date ? dol_print_date($object->delivery_date, $usehourmin) : '&nbsp;';
2372 if ($object->hasDelay() && !empty($object->delivery_date) && ($object->status == $object::STATUS_ORDERSENT || $object->status == $object::STATUS_RECEIVED_PARTIALLY)) {
2373 print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
2374 }
2375 }
2376 print '</td></tr>';
2377
2378 // Incoterms
2379 if (isModEnabled('incoterm')) {
2380 print '<tr><td>';
2381 print '<table class="nobordernopadding centpercent"><tr><td>';
2382 print $langs->trans('IncotermLabel');
2383 print '<td><td class="right">';
2384 if ($usercancreate) {
2385 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/fourn/commande/card.php?id='.$object->id.'&action=editincoterm&token='.newToken().'">'.img_edit().'</a>';
2386 } else {
2387 print '&nbsp;';
2388 }
2389 print '</td></tr></table>';
2390 print '</td>';
2391 print '<td>';
2392 if ($action != 'editincoterm') {
2393 print $form->textwithpicto(dol_escape_htmltag($object->display_incoterms()), $object->label_incoterms, 1);
2394 } else {
2395 print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
2396 }
2397 print '</td></tr>';
2398 }
2399
2400 // Tags-Categories
2401 if (isModEnabled('category')) {
2402 print '<tr><td>';
2403 print '<table class="nobordernopadding centpercent"><tr><td>';
2404 print $langs->trans("Categories");
2405 print '<td><td class="right">';
2406 if ($usercancreate) {
2407 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/fourn/commande/card.php?id='.$object->id.'&action=edittags&token='.newToken().'">'.img_edit().'</a>';
2408 } else {
2409 print '&nbsp;';
2410 }
2411 print '</td></tr></table>';
2412 print '</td>';
2413 print '<td>';
2414 if ($action == 'edittags') {
2415 print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
2416 print '<input type="hidden" name="action" value="settags">';
2417 print '<input type="hidden" name="token" value="'.newToken().'">';
2418 print $form->selectCategories(Categorie::TYPE_SUPPLIER_ORDER, 'categories', $object);
2419 print '<input type="submit" class="button valignmiddle smallpaddingimp" value="'.$langs->trans("Modify").'">';
2420 print '</form>';
2421 } else {
2422 print $form->showCategories($object->id, Categorie::TYPE_SUPPLIER_ORDER, 1);
2423 }
2424 print "</td></tr>";
2425 }
2426
2427 // Other attributes
2428 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
2429
2430 print '</table>';
2431
2432 print '</div>';
2433 print '<div class="fichehalfright">';
2434 print '<div class="underbanner clearboth"></div>';
2435
2436 print '<table class="border tableforfield centpercent">';
2437
2438 include DOL_DOCUMENT_ROOT.'/core/tpl/object_currency_amount.tpl.php';
2439
2440 print '<tr>';
2441 // Amount HT
2442 print '<td class="titlefieldmiddle">' . $langs->trans('AmountHT') . '</td>';
2443 print '<td class="nowrap amountcard right">' . price($object->total_ht, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
2444 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2445 // Multicurrency Amount HT
2446 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ht, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2447 }
2448 print '</tr>';
2449
2450 print '<tr>';
2451 // Amount VAT
2452 print '<td class="titlefieldmiddle">' . $langs->trans('AmountVAT') . '</td>';
2453 print '<td class="nowrap amountcard right">' . price($object->total_tva, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
2454 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2455 // Multicurrency Amount VAT
2456 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_tva, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2457 }
2458 print '</tr>';
2459
2460 // Amount Local Taxes
2461 if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) {
2462 print '<tr>';
2463 print '<td class="titlefieldmiddle">' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
2464 print '<td class="nowrap amountcard right">' . price($object->total_localtax1, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
2465 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2466 print '<td class="nowrap amountcard right">' . price($object->total_localtax1, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2467 }
2468 print '</tr>';
2469
2470 if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) {
2471 print '<tr>';
2472 print '<td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
2473 print '<td class="nowrap amountcard right">' . price($object->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
2474 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2475 print '<td class="nowrap amountcard right">' . price($object->total_localtax2, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2476 }
2477 print '</tr>';
2478 }
2479 }
2480
2481 $alert = '';
2482 if (getDolGlobalString('ORDER_MANAGE_MIN_AMOUNT') && $object->total_ht < $object->thirdparty->supplier_order_min_amount) {
2483 $alert = ' ' . img_warning($langs->trans('OrderMinAmount') . ': ' . price($object->thirdparty->supplier_order_min_amount));
2484 }
2485
2486 print '<tr>';
2487 // Amount TTC
2488 print '<td>' . $langs->trans('AmountTTC') . '</td>';
2489 print '<td class="nowrap amountcard right">' . price($object->total_ttc, 0, $langs, 0, -1, -1, $conf->currency) . $alert . '</td>';
2490 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2491 // Multicurrency Amount TTC
2492 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ttc, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2493 }
2494 print '</tr>';
2495
2496 print '</table>';
2497
2498 // Margin Infos
2499 /*if (isModEnabled('margin')) {
2500 $formmargin->displayMarginInfos($object);
2501 }*/
2502
2503
2504 print '</div>';
2505 print '</div>';
2506
2507 print '<div class="clearboth"></div><br>';
2508
2509 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
2510 $blocname = 'contacts';
2511 $title = $langs->trans('ContactsAddresses');
2512 include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
2513 }
2514
2515 if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
2516 $blocname = 'notes';
2517 $title = $langs->trans('Notes');
2518 include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
2519 }
2520
2521 /*
2522 * Lines
2523 */
2524 //$result = $object->getLinesArray();
2525
2526
2527 print ' <form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline') ? '' : '#line_'.GETPOSTINT('lineid')).'" method="POST">
2528 <input type="hidden" name="token" value="'.newToken().'">
2529 <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">
2530 <input type="hidden" name="mode" value="">
2531 <input type="hidden" name="page_y" value="">
2532 <input type="hidden" name="id" value="'.$object->id.'">
2533 <input type="hidden" name="socid" value="'.$societe->id.'">
2534 ';
2535
2536 if (!empty($conf->use_javascript_ajax) && $object->status == 0) {
2537 include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
2538 }
2539
2540 print '<div class="div-table-responsive-no-min">';
2541 print '<table id="tablelines" class="noborder noshadow centpercent">';
2542
2543 // Add free products/services form
2544 global $forceall, $senderissupplier, $dateSelector, $inputalsopricewithtax;
2545 $forceall = 1;
2546 $dateSelector = 0;
2547 $inputalsopricewithtax = 1;
2548 $senderissupplier = 2; // $senderissupplier=2 is same than 1 but disable test on minimum qty and disable autofill qty with minimum.
2549 if (getDolGlobalInt('SUPPLIER_ORDER_WITH_PREDEFINED_PRICES_ONLY')) {
2550 $senderissupplier = getDolGlobalInt('SUPPLIER_ORDER_WITH_PREDEFINED_PRICES_ONLY');
2551 }
2552
2553 // Show object lines
2554 if (!empty($object->lines)) {
2555 $object->printObjectLines($action, $object->thirdparty, $mysoc, $lineid, 1);
2556 }
2557
2558 $num = count($object->lines);
2559
2560 // Form to add new line
2561 if ($object->status == CommandeFournisseur::STATUS_DRAFT && $usercancreate) {
2562 if ($action != 'editline') {
2563 // Add free products/services
2564
2565 $parameters = array();
2566 $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2567 if ($reshook < 0) {
2568 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2569 }
2570 if (empty($reshook)) {
2571 $object->formAddObjectLine(1, $societe, $mysoc);
2572 }
2573 }
2574 }
2575 print '</table>';
2576 print '</div>';
2577 print '</form>';
2578 }
2579
2580 print dol_get_fiche_end();
2581
2586 if ($user->socid == 0 && $action != 'delete') {
2587 if ($action != 'createorder' && $action != 'presend' && $action != 'editline') {
2588 print '<div class="tabsAction">';
2589
2590 $parameters = array();
2591 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
2592 // modified by hook
2593 if (empty($reshook)) {
2594 $object->fetchObjectLinked(); // Links are used to show or not button, so we load them now.
2595
2596 // Validate
2597 if ($object->status == 0 && $num > 0) {
2598 if ($usercanvalidate) {
2599 $tmpbuttonlabel = $langs->trans('Validate');
2600 if ($usercanapprove && !getDolGlobalString('SUPPLIER_ORDER_NO_DIRECT_APPROVE')) {
2601 $tmpbuttonlabel = $langs->trans("ValidateAndApprove");
2602 }
2603
2604 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=valid&token='.newToken().'">';
2605 print $tmpbuttonlabel;
2606 print '</a>';
2607 }
2608 }
2609 // Create event
2610 /*if (isModEnabled('agenda') && getDolGlobalString('MAIN_ADD_EVENT_ON_ELEMENT_CARD')) // Add hidden condition because this is not a "workflow" action so should appears somewhere else on page.
2611 {
2612 print '<div class="inline-block divButAction"><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>';
2613 }*/
2614
2615 // Modify
2617 if ($usercanorder) {
2618 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("Modify").'</a>';
2619 }
2620 }
2621
2622 // Approve
2624 if ($usercanapprove) {
2625 if (getDolGlobalString('SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED') && $object->total_ht >= $conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED && !empty($object->user_approve_id)) {
2626 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("FirstApprovalAlreadyDone")).'">'.$langs->trans("ApproveOrder").'</a>';
2627 } else {
2628 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=approve">'.$langs->trans("ApproveOrder").'</a>';
2629 }
2630 } else {
2631 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$langs->trans("ApproveOrder").'</a>';
2632 }
2633 }
2634
2635 // Second approval (if option SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED is set)
2636 if (getDolGlobalString('SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED') && $object->total_ht >= $conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED) {
2638 if ($usercanapprovesecond) {
2639 if (!empty($object->user_approve_id2)) {
2640 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("SecondApprovalAlreadyDone")).'">'.$langs->trans("Approve2Order").'</a>';
2641 } else {
2642 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=approve2">'.$langs->trans("Approve2Order").'</a>';
2643 }
2644 } else {
2645 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$langs->trans("Approve2Order").'</a>';
2646 }
2647 }
2648 }
2649
2650 // Refuse
2652 if ($usercanapprove || $usercanapprovesecond) {
2653 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=refuse">'.$langs->trans("RefuseOrder").'</a>';
2654 } else {
2655 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$langs->trans("RefuseOrder").'</a>';
2656 }
2657 }
2658
2659 // Send
2660 if (empty($user->socid)) {
2661 if (in_array($object->status, array(CommandeFournisseur::STATUS_ACCEPTED, 3, 4, 5)) || getDolGlobalString('SUPPLIER_ORDER_SENDBYEMAIL_FOR_ALL_STATUS')) {
2662 if ($usercanorder) {
2663 print dolGetButtonAction('', $langs->trans('SendMail'), 'email', dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id, 'action' => 'presend', 'mode' => 'init'], true).'#formmailbeforetitle', '');
2664 }
2665 }
2666 }
2667
2668 // Reopen
2669 if (in_array($object->status, array(CommandeFournisseur::STATUS_ACCEPTED))) {
2670 $buttonshown = 0;
2671 if (!$buttonshown && $usercanapprove) {
2672 if (!getDolGlobalString('SUPPLIER_ORDER_REOPEN_BY_APPROVER_ONLY')
2673 || (getDolGlobalString('SUPPLIER_ORDER_REOPEN_BY_APPROVER_ONLY') && $user->id == $object->user_approve_id)) {
2674 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("Disapprove").'</a>';
2675 $buttonshown++;
2676 }
2677 }
2678 if (!$buttonshown && $usercanapprovesecond && getDolGlobalString('SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED')) {
2679 if (!getDolGlobalString('SUPPLIER_ORDER_REOPEN_BY_APPROVER2_ONLY')
2680 || (getDolGlobalString('SUPPLIER_ORDER_REOPEN_BY_APPROVER2_ONLY') && $user->id == $object->user_approve_id2)) {
2681 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("Disapprove").'</a>';
2682 }
2683 }
2684 }
2685 if (in_array($object->status, array(3, 4, 5, 6, 7, 9))) {
2686 if ($usercanorder) {
2687 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ReOpen").'</a>';
2688 }
2689 }
2690
2691 // Ship
2692 $hasreception = 0;
2693 if (isModEnabled('stock') && (getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER') || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE'))) {
2694 $labelofbutton = $langs->trans('ReceiveProducts');
2695 if (isModEnabled('reception')) {
2696 $labelofbutton = $langs->trans("CreateReception");
2697 if (!empty($object->linkedObjects['reception'])) {
2698 foreach ($object->linkedObjects['reception'] as $element) {
2699 if ($element->statut >= 0) {
2700 $hasreception = 1;
2701 break;
2702 }
2703 }
2704 }
2705 }
2706
2707 // To avoid delete order with dispatched lines
2708 if (getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER')) {
2709 if (empty($object->lines)) {
2710 $object->fetch_lines();
2711 }
2712 $dispachedLines = $object->getDispachedLines(1);
2713 $nbDispachedLines = count($dispachedLines);
2714 if ($nbDispachedLines > 0) {
2715 $hasreception = 1;
2716 }
2717 }
2718
2719 if (in_array($object->status, array(3, 4, 5))) {
2720 if (isModEnabled("supplier_order") && $usercanreceive) {
2721 print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/fourn/commande/dispatch.php?id='.$object->id.'">'.$labelofbutton.'</a></div>';
2722 } else {
2723 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$labelofbutton.'</a></div>';
2724 }
2725 }
2726 }
2727
2729 if ($usercanorder) {
2730 print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=createorder&token='.newToken().'#makeorder">'.$langs->trans("MakeOrder").'</a></div>';
2731 } else {
2732 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#">'.$langs->trans("MakeOrder").'</a></div>';
2733 }
2734 }
2735
2736 // Classify received (this does not record reception)
2738 if ($usercanreceive) {
2739 print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&token='.newToken().'&action=classifyreception#classifyreception">'.$langs->trans("ClassifyReception").'</a></div>';
2740 }
2741 }
2742
2743 // Create bill
2744 //if (isModEnabled('facture'))
2745 //{
2746 if (isModEnabled("supplier_invoice") && ($object->status >= 2 && $object->status != 7 && $object->billed != 1)) { // statut 2 means approved, 7 means canceled
2747 if ($user->hasRight('fournisseur', 'facture', 'creer') || $user->hasRight("supplier_invoice", "creer")) {
2748 print '<a class="butAction" href="'.DOL_URL_ROOT.'/fourn/facture/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid.'">'.$langs->trans("SupplierOrderCreateBill").'</a>';
2749 }
2750 }
2751 //}
2752
2753 // Classify billed manually (need one invoice if module invoice is on, no condition on invoice if not)
2754 if ($usercancreate && $object->status >= 2 && $object->status != 7 && $object->billed != 1) { // statut 2 means approved
2755 if (!isModEnabled('invoice')) {
2756 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifybilled&token='.newToken().'">'.$langs->trans("ClassifyBilled").'</a>';
2757 } else {
2758 if (!empty($object->linkedObjectsIds['invoice_supplier']) || (empty($object->linkedObjectsIds['invoice_supplier']) && !getDolGlobalInt('SUPPLIER_ORDER_DISABLE_CLASSIFY_BILLED_FROM_SUPPLIER_ORDER'))) {
2759 if ($user->hasRight('fournisseur', 'facture', 'creer') || $user->hasRight("supplier_invoice", "creer")) {
2760 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifybilled&token='.newToken().'">'.$langs->trans("ClassifyBilled").'</a>';
2761 }
2762 } else {
2763 print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NeedAtLeastOneInvoice")).'">'.$langs->trans("ClassifyBilled").'</a>';
2764 }
2765 }
2766 }
2767
2768 // Classify unbilled manually
2769 if ($usercancreate && $object->billed > 0 && $object->status > $object::STATUS_DRAFT) {
2770 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifyunbilled&token='.newToken().'">'.$langs->trans("ClassifyUnbilled").'</a>';
2771 }
2772
2773 // Clone
2774 if ($usercancreate) {
2775 print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&amp;socid='.$object->socid.'&amp;action=clone&amp;token='.newToken().'&amp;object=order">'.$langs->trans("ToClone").'</a>';
2776 }
2777
2778 // Cancel
2780 if ($usercanorder) {
2781 print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=cancel&amp;token='.newToken().'">'.$langs->trans("CancelOrder").'</a>';
2782 }
2783 }
2784
2785 // Delete
2786 if (!empty($usercandelete)) {
2787 if ($hasreception) {
2788 print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("ReceptionExist").'">'.$langs->trans("Delete").'</a>';
2789 } else {
2790 print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'">'.$langs->trans("Delete").'</a>';
2791 }
2792 }
2793 }
2794
2795 print "</div>";
2796 }
2797
2798 if ($usercanorder && $object->status == CommandeFournisseur::STATUS_ACCEPTED && $action == 'createorder') {
2799 // Set status to ordered (action=commande)
2800 print '<!-- form to record supplier order -->'."\n";
2801 print '<form name="commande" id="makeorder" action="card.php?id='.$object->id.'&amp;action=commande" method="POST">';
2802
2803 print '<input type="hidden" name="token" value="'.newToken().'">';
2804 print '<input type="hidden" name="action" value="commande">';
2805 print load_fiche_titre($langs->trans("ToOrder"), '', '');
2806 print '<table class="noborder centpercent">';
2807 //print '<tr class="liste_titre"><td colspan="2">'.$langs->trans("ToOrder").'</td></tr>';
2808 print '<tr><td class="fieldrequired">'.$langs->trans("OrderDate").'</td><td>';
2809 $date_com = dol_mktime(GETPOSTINT('rehour'), GETPOSTINT('remin'), GETPOSTINT('resec'), GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
2810 print $form->selectDate($date_com ?: '', '', 0, 0, 0, "commande", 1, 1);
2811 print '</td></tr>';
2812
2813 // Force mandatory order method
2814 print '<tr><td class="fieldrequired">'.$langs->trans("OrderMode").'</td><td>';
2815 $formorder->selectInputMethod(GETPOST('methodecommande'), "methodecommande", 1);
2816 print '</td></tr>';
2817
2818 print '<tr><td>'.$langs->trans("Comment").'</td><td><input class="quatrevingtpercent" type="text" name="comment" value="'.GETPOST('comment').'"></td></tr>';
2819
2820 print '<tr><td class="center" colspan="2">';
2821 print '<input type="submit" name="makeorder" class="button" value="'.$langs->trans("ToOrder").'">';
2822 print ' &nbsp; &nbsp; ';
2823 print '<input type="submit" name="cancel" class="button button-cancel" value="'.$langs->trans("Cancel").'">';
2824 print '</td></tr>';
2825 print '</table>';
2826
2827 print '</form>';
2828 print "<br>";
2829 }
2830
2831 // Select mail models is same action as presend
2832 if (GETPOST('modelselected')) {
2833 $action = 'presend';
2834 }
2835
2836 if ($action != 'createorder' && $action != 'presend') {
2837 print '<div class="fichecenter"><div class="fichehalfleft">';
2838
2839 // Generated documents
2840 $objref = dol_sanitizeFileName($object->ref);
2841 $file = $conf->fournisseur->dir_output.'/commande/'.$objref.'/'.$objref.'.pdf';
2842 $relativepath = $objref.'/'.$objref.'.pdf';
2843 $filedir = $conf->fournisseur->dir_output.'/commande/'.$objref;
2844 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
2845 $genallowed = $usercanread;
2846 $delallowed = $usercancreate;
2847 $modelpdf = (!empty($object->model_pdf) ? $object->model_pdf : (!getDolGlobalString('COMMANDE_SUPPLIER_ADDON_PDF') ? '' : $conf->global->COMMANDE_SUPPLIER_ADDON_PDF));
2848
2849 print $formfile->showdocuments('commande_fournisseur', $objref, $filedir, $urlsource, (int) $genallowed, (int) $delallowed, $modelpdf, 1, 0, 0, 0, 0, '', '', '', $object->thirdparty->default_lang, '', $object);
2850 $somethingshown = $formfile->numoffiles;
2851
2852 // Show links to link elements
2853 $tmparray = $form->showLinkToObjectBlock($object, array(), array('supplier_order', 'order_supplier'), 1);
2854 $linktoelem = $tmparray['linktoelem'];
2855 $htmltoenteralink = $tmparray['htmltoenteralink'];
2856 print $htmltoenteralink;
2857
2858 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
2859
2860 print '</div><div class="fichehalfright">';
2861
2862 if ($action == 'classifyreception') {
2864 // Set status to received (action=livraison)
2865 print '<!-- form to record purchase order received -->'."\n";
2866 print '<form id="classifyreception" action="card.php?id='.$object->id.'" method="post">';
2867 print '<input type="hidden" name="token" value="'.newToken().'">';
2868 print '<input type="hidden" name="action" value="livraison">';
2869 print load_fiche_titre($langs->trans("Receive"), '', '');
2870
2871 print '<table class="noborder centpercent">';
2872 //print '<tr class="liste_titre"><td colspan="2">'.$langs->trans("Receive").'</td></tr>';
2873 print '<tr><td>'.$langs->trans("DeliveryDate").'</td><td>';
2874 $datepreselected = dol_now();
2875 print $form->selectDate($datepreselected, '', 1, 1, 0, "commande", 1, 1);
2876 print "</td></tr>\n";
2877
2878 print '<tr><td class="fieldrequired">'.$langs->trans("Delivery")."</td><td>\n";
2879 $liv = array();
2880 $liv[''] = '&nbsp;';
2881 $liv['tot'] = $langs->trans("CompleteOrNoMoreReceptionExpected");
2882 $liv['par'] = $langs->trans("PartialWoman");
2883 $liv['nev'] = $langs->trans("NeverReceived");
2884 $liv['can'] = $langs->trans("Canceled");
2885
2886 print $form->selectarray("type", $liv);
2887
2888 print '</td></tr>';
2889 print '<tr><td>'.$langs->trans("Comment").'</td><td><input class="quatrevingtpercent" type="text" name="comment"></td></tr>';
2890 print '<tr><td class="center" colspan="2">';
2891 print '<input type="submit" name="receive" class="button" value="'.$langs->trans("Receive").'">';
2892 print ' &nbsp; &nbsp; ';
2893 print '<input type="submit" name="cancel" class="button button-cancel" value="'.$langs->trans("Cancel").'">';
2894 print '</td></tr>';
2895 print "</table>\n";
2896 print "</form>\n";
2897 print "<br>";
2898 }
2899 }
2900
2901 // List of actions on element
2902 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
2903 $formactions = new FormActions($db);
2904 $somethingshown = $formactions->showactions($object, 'order_supplier', $socid, 1, 'listaction'.($genallowed ? 'largetitle' : ''));
2905
2906 print '</div></div>';
2907 }
2908
2909 /*
2910 * Action webservice
2911 */
2912 if ($action == 'webservice' && GETPOST('mode', 'alpha') != "send" && !GETPOST('cancel', 'alpha')) {
2913 $mode = GETPOST('mode', 'alpha');
2914 $ws_url = $object->thirdparty->webservices_url;
2915 $ws_key = $object->thirdparty->webservices_key;
2916 $ws_user = GETPOST('ws_user', 'alpha');
2917 $ws_password = GETPOST('ws_password', 'alpha');
2918 $error_occurred = false;
2919
2920 // NS and Authentication parameters
2921 $ws_ns = 'http://www.dolibarr.org/ns/';
2922 $ws_authentication = array(
2923 'dolibarrkey' => $ws_key,
2924 'sourceapplication' => 'DolibarrWebServiceClient',
2925 'login' => $ws_user,
2926 'password' => $ws_password,
2927 'entity' => ''
2928 );
2929
2930 print load_fiche_titre($langs->trans('CreateRemoteOrder'), '');
2931
2932 //Is everything filled?
2933 if (empty($ws_url) || empty($ws_key)) {
2934 setEventMessages($langs->trans("ErrorWebServicesFieldsRequired"), null, 'errors');
2935 $mode = "init";
2936 $error_occurred = true; //Don't allow to set the user/pass if thirdparty fields are not filled
2937 } elseif ($mode != "init" && (empty($ws_user) || empty($ws_password))) {
2938 setEventMessages($langs->trans("ErrorFieldsRequired"), null, 'errors');
2939 $mode = "init";
2940 }
2941
2942 if ($mode == "init") {
2943 //Table/form header
2944 print '<table class="border centpercent">';
2945 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2946 print '<input type="hidden" name="token" value="'.newToken().'">';
2947 print '<input type="hidden" name="action" value="webservice">';
2948 print '<input type="hidden" name="mode" value="check">';
2949
2950 if ($error_occurred) {
2951 print "<br>".$langs->trans("ErrorOccurredReviseAndRetry")."<br>";
2952 print '<input class="button button-cancel" type="submit" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
2953 } else {
2954 // Webservice url
2955 print '<tr><td>'.$langs->trans("WebServiceURL").'</td><td colspan="3">'.dol_print_url($ws_url).'</td></tr>';
2956 //Remote User
2957 print '<tr><td>'.$langs->trans("User").'</td><td><input class="width100" type="text" name="ws_user"></td></tr>';
2958 //Remote Password
2959 print '<tr><td>'.$langs->trans("Password").'</td><td><input class="width100" type="text" name="ws_password"></td></tr>';
2960 //Submit button
2961 print '<tr><td class="center" colspan="2">';
2962 print '<input type="submit" class="button" id="ws_submit" name="ws_submit" value="'.$langs->trans("CreateRemoteOrder").'">';
2963 print ' &nbsp; &nbsp; ';
2964 //Cancel button
2965 print '<input class="button button-cancel" type="submit" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
2966 print '</td></tr>';
2967 }
2968
2969 //End table/form
2970 print '</form>';
2971 print '</table>';
2972 } elseif ($mode == "check") {
2973 $ws_entity = '';
2974 $ws_thirdparty = '';
2975 $error_occurred = false;
2976
2977 //Create SOAP client and connect it to user
2978 $soapclient_user = new nusoap_client($ws_url."/webservices/server_user.php");
2979 $soapclient_user->soap_defencoding = 'UTF-8';
2980 $soapclient_user->decodeUTF8(false);
2981
2982 //Get the thirdparty associated to user
2983 $ws_parameters = array('authentication' => $ws_authentication, 'id' => '', 'ref' => $ws_user);
2984 $result_user = $soapclient_user->call("getUser", $ws_parameters, $ws_ns, '');
2985 $user_status_code = $result_user["result"]["result_code"];
2986
2987 if ($user_status_code == "OK") {
2988 //Fill the variables
2989 $ws_entity = $result_user["user"]["entity"];
2990 $ws_authentication['entity'] = $ws_entity;
2991 $ws_thirdparty = $result_user["user"]["fk_thirdparty"];
2992 if (empty($ws_thirdparty)) {
2993 setEventMessages($langs->trans("RemoteUserMissingAssociatedSoc"), null, 'errors');
2994 $error_occurred = true;
2995 } else {
2996 //Create SOAP client and connect it to product/service
2997 $soapclient_product = new nusoap_client($ws_url."/webservices/server_productorservice.php");
2998 $soapclient_product->soap_defencoding = 'UTF-8';
2999 $soapclient_product->decodeUTF8(false);
3000
3001 // Iterate each line and get the reference that uses the supplier of that product/service
3002 $i = 0;
3003 foreach ($object->lines as $line) {
3004 $i += 1;
3005 $ref_supplier = $line->ref_supplier;
3006 $line_id = $i."º) ".$line->product_ref.": ";
3007 if (empty($ref_supplier)) {
3008 continue;
3009 }
3010 $ws_parameters = array('authentication' => $ws_authentication, 'id' => '', 'ref' => $ref_supplier);
3011 $result_product = $soapclient_product->call("getProductOrService", $ws_parameters, $ws_ns, '');
3012 if (!$result_product) {
3013 setEventMessages($line_id.$langs->trans("Error")." SOAP ".$soapclient_product->error_str." - ".$soapclient_product->response, null, 'errors');
3014 $error_occurred = true;
3015 break;
3016 }
3017
3018 // Check the result code
3019 $status_code = $result_product["result"]["result_code"];
3020 if (empty($status_code)) { //No result, check error str
3021 setEventMessages($langs->trans("Error")." SOAP '".$soapclient_product->error_str."'", null, 'errors');
3022 } elseif ($status_code != "OK") { //Something went wrong
3023 if ($status_code == "NOT_FOUND") {
3024 setEventMessages($line_id.$langs->trans("SupplierMissingRef")." '".$ref_supplier."'", null, 'warnings');
3025 } else {
3026 setEventMessages($line_id.$langs->trans("ResponseNonOK")." '".$status_code."' - '".$result_product["result"]["result_label"]."'", null, 'errors');
3027 $error_occurred = true;
3028 break;
3029 }
3030 }
3031
3032
3033 // Ensure that price is equal and warn user if it's not
3034 $supplier_price = price($result_product["product"]["price_net"]); //Price of client tab in supplier dolibarr
3035 $local_price = null; //Price of supplier as stated in product suppliers tab on this dolibarr, NULL if not found
3036
3037 $product_fourn = new ProductFournisseur($db);
3038 $product_fourn_list = $product_fourn->list_product_fournisseur_price($line->fk_product);
3039 if (count($product_fourn_list) > 0) {
3040 foreach ($product_fourn_list as $product_fourn_line) {
3041 //Only accept the line where the supplier is the same at this order and has the same ref
3042 if ($product_fourn_line->fourn_id == $object->socid && $product_fourn_line->fourn_ref == $ref_supplier) {
3043 $local_price = price($product_fourn_line->fourn_price);
3044 }
3045 }
3046 }
3047
3048 if ($local_price != null && $local_price != $supplier_price) {
3049 setEventMessages($line_id.$langs->trans("RemotePriceMismatch")." ".$supplier_price." - ".$local_price, null, 'warnings');
3050 }
3051
3052 // Check if is in sale
3053 if (empty($result_product["product"]["status_tosell"])) {
3054 setEventMessages($line_id.$langs->trans("ProductStatusNotOnSellShort")." '".$ref_supplier."'", null, 'warnings');
3055 }
3056 }
3057 }
3058 } elseif ($user_status_code == "PERMISSION_DENIED") {
3059 setEventMessages($langs->trans("RemoteUserNotPermission"), null, 'errors');
3060 $error_occurred = true;
3061 } elseif ($user_status_code == "BAD_CREDENTIALS") {
3062 setEventMessages($langs->trans("RemoteUserBadCredentials"), null, 'errors');
3063 $error_occurred = true;
3064 } else {
3065 setEventMessages($langs->trans("ResponseNonOK")." '".$user_status_code."'", null, 'errors');
3066 $error_occurred = true;
3067 }
3068
3069 //Form
3070 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
3071 print '<input type="hidden" name="token" value="'.newToken().'">';
3072 print '<input type="hidden" name="action" value="webservice">';
3073 print '<input type="hidden" name="mode" value="send">';
3074 print '<input type="hidden" name="ws_user" value="'.$ws_user.'">';
3075 print '<input type="hidden" name="ws_password" value="'.$ws_password.'">';
3076 print '<input type="hidden" name="ws_entity" value="'.$ws_entity.'">';
3077 print '<input type="hidden" name="ws_thirdparty" value="'.$ws_thirdparty.'">';
3078 if ($error_occurred) {
3079 print "<br>".$langs->trans("ErrorOccurredReviseAndRetry")."<br>";
3080 } else {
3081 print '<input type="submit" class="button" id="ws_submit" name="ws_submit" value="'.$langs->trans("Confirm").'">';
3082 print ' &nbsp; &nbsp; ';
3083 }
3084 print '<input class="button button-cancel" type="submit" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
3085 print '</form>';
3086 }
3087 }
3088
3089 // Presend form
3090 $modelmail = 'order_supplier_send';
3091 $defaulttopic = 'SendOrderRef';
3092 $diroutput = $conf->fournisseur->commande->dir_output;
3093 $autocopy = 'MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO';
3094 $trackid = 'sord'.$object->id;
3095
3096 include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
3097 }
3098}
3099
3100// End of page
3101llxFooter();
3102$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
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:73
Class to manage predefined suppliers products.
const STATUS_RECEIVED_PARTIALLY
Received partially.
const STATUS_VALIDATED
Validated status.
const STATUS_RECEIVED_COMPLETELY
Received completely.
const STATUS_ORDERSENT
Order sent, shipment on process.
Class to manage line orders.
Class to manage a WYSIWYG editor.
Class to manage standard extra fields.
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 to manage HTML output components for orders Before adding component here, check they are not in...
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 the table of subscription to notifications.
Class ProductCombination Used to represent the relation between a product and one of its variants.
Class to manage predefined suppliers products.
Class to manage products or services.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class for Target.
Class to manage translations.
Class to manage Dolibarr users.
global $mysoc
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.
ordersupplier_prepare_head(CommandeFournisseur $object)
Prepare array with list of tabs.
dol_now($mode='gmt')
Return date for now.
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...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dolBuildUrl($url, $params=[], $addtoken=false)
Return path of url.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
dol_print_url($url, $target='_blank', $max=32, $withpicto=0, $morecss='')
Show Url link.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
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.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOSTFLOAT($paramname, $rounding='', $option=2)
Return the value of a $_GET or $_POST supervariable, converted into float.
dolGetButtonAction($label, $text='', $actionType='default', $url='', $id='', $userRight=1, $params=array())
Function dolGetButtonAction.
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that returns whether VAT must be recoverable collected VAT (e.g.: VAT NPR in France)
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...
dol_htmloutput_events($disabledoutputofmessages=0)
Print formatted messages to output (Used to show messages on html output).
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_clone($srcobject, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) VAT...
get_localtax($vatrate, $local, $thirdparty_buyer=null, $thirdparty_seller=null, $vatnpr=0)
Return localtax rate for a particular VAT rate, when selling a product with vat $vatrate,...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
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.