dolibarr 23.0.4
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 $object->fetch_thirdparty(); // fetch() reset thirdparty to null, reload it before reading default_lang
680
681 // Define output language
682 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
683 $outputlangs = $langs;
684 $newlang = '';
685 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */) {
686 $newlang = $object->thirdparty->default_lang;
687 if (GETPOST('lang_id', 'aZ09')) {
688 $newlang = GETPOST('lang_id', 'aZ09');
689 }
690 }
691 if (!empty($newlang)) {
692 $outputlangs = new Translate("", $conf);
693 $outputlangs->setDefaultLang($newlang);
694 }
695 $model = $object->model_pdf;
696 $ret = $object->fetch($id); // Reload to get new records
697
698 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
699 if ($result < 0) {
700 setEventMessages($object->error, $object->errors, 'errors');
701 }
702 }
703
704 unset($_POST ['prod_entry_mode']);
705
706 unset($_POST['qty']);
707 unset($_POST['type']);
708 unset($_POST['remise_percent']);
709 unset($_POST['pu']);
710 unset($_POST['price_ht']);
711 unset($_POST['multicurrency_price_ht']);
712 unset($_POST['price_ttc']);
713 unset($_POST['fourn_ref']);
714 unset($_POST['tva_tx']);
715 unset($_POST['label']);
716 unset($localtax1_tx);
717 unset($localtax2_tx);
718 unset($_POST['np_marginRate']);
719 unset($_POST['np_markRate']);
720 unset($_POST['dp_desc']);
721 unset($_POST['idprodfournprice']);
722 unset($_POST['units']);
723
724 unset($_POST['date_starthour']);
725 unset($_POST['date_startmin']);
726 unset($_POST['date_startsec']);
727 unset($_POST['date_startday']);
728 unset($_POST['date_startmonth']);
729 unset($_POST['date_startyear']);
730 unset($_POST['date_endhour']);
731 unset($_POST['date_endmin']);
732 unset($_POST['date_endsec']);
733 unset($_POST['date_endday']);
734 unset($_POST['date_endmonth']);
735 unset($_POST['date_endyear']);
736 } else {
737 $db->rollback();
738 setEventMessages($object->error, $object->errors, 'errors');
739 }
740
741 $action = '';
742 }
743
744 /*
745 * Updating a line in the order
746 */
747 if ($action == 'updateline' && $usercancreate && !GETPOST('cancel', 'alpha')) {
748 $db->begin();
749
750 $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
751
752 if ($lineid) {
753 $line = new CommandeFournisseurLigne($db);
754 $res = $line->fetch($lineid);
755 if (!$res) {
756 dol_print_error($db);
757 }
758 }
759
760 $productsupplier = new ProductFournisseur($db);
761 if (getDolGlobalInt('SUPPLIER_ORDER_WITH_PREDEFINED_PRICES_ONLY') == 1) { // Not the common case
762 if ($line->fk_product > 0 && $productsupplier->get_buyprice(0, (float) price2num(GETPOSTFLOAT('qty')), $line->fk_product, 'none', GETPOSTINT('socid')) < 0) {
763 setEventMessages($langs->trans("ErrorQtyTooLowForThisSupplier"), null, 'warnings');
764 }
765 }
766
767 $date_start = dol_mktime(GETPOSTINT('date_starthour'), GETPOSTINT('date_startmin'), GETPOSTINT('date_startsec'), GETPOSTINT('date_startmonth'), GETPOSTINT('date_startday'), GETPOSTINT('date_startyear'));
768 $date_end = dol_mktime(GETPOSTINT('date_endhour'), GETPOSTINT('date_endmin'), GETPOSTINT('date_endsec'), GETPOSTINT('date_endmonth'), GETPOSTINT('date_endday'), GETPOSTINT('date_endyear'));
769
770 // Define info_bits
771 $info_bits = 0;
772 if (preg_match('/\*/', $vat_rate)) {
773 $info_bits |= 0x01;
774 }
775
776 // Define vat_rate
777 $vat_rate = str_replace('*', '', $vat_rate);
778 $localtax1_rate = get_localtax($vat_rate, 1, $mysoc, $object->thirdparty);
779 $localtax2_rate = get_localtax($vat_rate, 2, $mysoc, $object->thirdparty);
780
781 if (GETPOST('price_ht') != '') {
782 $price_base_type = 'HT';
783 $ht = price2num(GETPOST('price_ht'), '', 2);
784 } else {
785 $reg = array();
786 $vatratecleaned = $vat_rate;
787 if (preg_match('/^(.*)\s*\‍((.*)\‍)$/', $vat_rate, $reg)) { // If vat is "xx (yy)"
788 $vatratecleaned = trim($reg[1]);
789 $vatratecode = $reg[2];
790 }
791
792 $ttc = price2num(GETPOST('price_ttc'), '', 2);
793 $ht = (float) $ttc / (1 + ((float) $vatratecleaned / 100));
794 $price_base_type = 'HT';
795 }
796
797 $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), 'CU', 2);
798
799 // Extrafields Lines
800 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
801 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
802 // Unset extrafield POST Data
803 if (is_array($extralabelsline)) {
804 foreach ($extralabelsline as $key => $value) {
805 unset($_POST["options_".$key]);
806 }
807 }
808
809 $result = $object->updateline(
810 $lineid,
811 GETPOST('product_desc', 'restricthtml'),
812 $ht,
813 (float) price2num(GETPOST('qty'), 'MS'),
814 (float) price2num(GETPOST('remise_percent'), '', 2),
815 $vat_rate,
816 $localtax1_rate,
817 $localtax2_rate,
818 $price_base_type,
819 0,
820 GETPOSTISSET("type") ? GETPOST("type") : $line->product_type,
821 0,
822 $date_start,
823 $date_end,
824 $array_options,
825 ((string) GETPOST('units') === '') ? null : GETPOSTINT('units'),
826 (float) $pu_ht_devise,
827 GETPOST('fourn_ref', 'alpha')
828 );
829 unset($_POST['qty']);
830 unset($_POST['type']);
831 unset($_POST['idprodfournprice']);
832 unset($_POST['remmise_percent']);
833 unset($_POST['dp_desc']);
834 unset($_POST['np_desc']);
835 unset($_POST['pu']);
836 unset($_POST['fourn_ref']);
837 unset($_POST['tva_tx']);
838 unset($_POST['date_start']);
839 unset($_POST['date_end']);
840 unset($_POST['units']);
841 unset($localtax1_tx);
842 unset($localtax2_tx);
843
844 unset($_POST['date_starthour']);
845 unset($_POST['date_startmin']);
846 unset($_POST['date_startsec']);
847 unset($_POST['date_startday']);
848 unset($_POST['date_startmonth']);
849 unset($_POST['date_startyear']);
850 unset($_POST['date_endhour']);
851 unset($_POST['date_endmin']);
852 unset($_POST['date_endsec']);
853 unset($_POST['date_endday']);
854 unset($_POST['date_endmonth']);
855 unset($_POST['date_endyear']);
856
857 if ($result >= 0) {
858 // Define output language
859 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
860 $outputlangs = $langs;
861 $newlang = '';
862 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
863 $newlang = GETPOST('lang_id', 'aZ09');
864 }
865 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
866 $newlang = $object->thirdparty->default_lang;
867 }
868 if (!empty($newlang)) {
869 $outputlangs = new Translate("", $conf);
870 $outputlangs->setDefaultLang($newlang);
871 }
872 $model = $object->model_pdf;
873 $ret = $object->fetch($id); // Reload to get new records
874
875 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
876 if ($result < 0) {
877 dol_print_error($db, $object->error, $object->errors);
878 }
879 }
880
881 $db->commit();
882 } else {
883 $db->rollback();
884
885 setEventMessages($object->error, $object->errors, 'errors');
886 }
887 }
888
889 // Remove a product line
890 if ($action == 'confirm_deleteline' && $confirm == 'yes' && $usercancreate) {
891 $db->begin();
892
893 $result = $object->deleteLine($lineid);
894 if ($result > 0) {
895 // reorder lines
896 $object->line_order(true);
897 // Define output language
898 $outputlangs = $langs;
899 $newlang = '';
900 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
901 $newlang = GETPOST('lang_id', 'aZ09');
902 }
903 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
904 $newlang = $object->thirdparty->default_lang;
905 }
906 if (!empty($newlang)) {
907 $outputlangs = new Translate("", $conf);
908 $outputlangs->setDefaultLang($newlang);
909 }
910 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
911 $ret = $object->fetch($object->id); // Reload to get new records
912 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
913 }
914 } else {
915 $error++;
916 setEventMessages($object->error, $object->errors, 'errors');
917 // Reset action to avoid asking again confirmation on failure
918 $action = '';
919 }
920
921 if (!$error) {
922 // reopen order if necessary
924 if ($object->setStatus($user, CommandeFournisseur::STATUS_RECEIVED_PARTIALLY) < 0) {
925 setEventMessages($object->error, $object->errors, 'errors');
926 $error++;
927 $action = '';
928 }
929 }
930 }
931
932 if (!$error) {
933 $db->commit();
934 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
935 exit;
936 } else {
937 $db->rollback();
938 }
939 }
940
941 // Validate
942 if ($action == 'confirm_valid' && $confirm == 'yes' && $usercanvalidate) {
943 $db->begin();
944
945 $object->date_commande = dol_now();
946 $result = $object->valid($user);
947 if ($result >= 0) {
948 // Define output language
949 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
950 $outputlangs = $langs;
951 $newlang = '';
952 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
953 $newlang = GETPOST('lang_id', 'aZ09');
954 }
955 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
956 $newlang = $object->thirdparty->default_lang;
957 }
958 if (!empty($newlang)) {
959 $outputlangs = new Translate("", $conf);
960 $outputlangs->setDefaultLang($newlang);
961 }
962 $model = $object->model_pdf;
963 $ret = $object->fetch($id); // Reload to get new records
964
965 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
966 if ($result < 0) {
967 $error++;
968 dol_print_error($db, $object->error, $object->errors);
969 }
970 }
971 } else {
972 $error++;
973 setEventMessages($object->error, $object->errors, 'errors');
974 }
975
976 // If we have permission, and if we don't need to provide the idwarehouse, we go directly on approved step
977 if (!$error && !getDolGlobalString('SUPPLIER_ORDER_NO_DIRECT_APPROVE') && $usercanapprove && !(getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER') && $object->hasProductsOrServices(1))) {
978 $action = 'confirm_approve'; // can make standard or first level approval also if permission is set
979 }
980
981 if (!$error) {
982 $db->commit();
983 } else {
984 $db->rollback();
985 }
986 }
987
988 if (($action == 'confirm_approve' || $action == 'confirm_approve2') && $confirm == 'yes' && $usercanapprove) {
989 $db->begin();
990
991 $idwarehouse = GETPOSTINT('idwarehouse');
992
993 $qualified_for_stock_change = 0;
994 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
995 $qualified_for_stock_change = $object->hasProductsOrServices(2);
996 } else {
997 $qualified_for_stock_change = $object->hasProductsOrServices(1);
998 }
999
1000 // Check parameters
1001 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
1002 if (!$idwarehouse || $idwarehouse == -1) {
1003 $error++;
1004 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1005 $action = '';
1006 }
1007 }
1008
1009 if (!$error) {
1010 $result = $object->approve($user, $idwarehouse, ($action == 'confirm_approve2' ? 1 : 0));
1011 if ($result > 0) {
1012 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1013 $outputlangs = $langs;
1014 $newlang = '';
1015 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
1016 $newlang = GETPOST('lang_id', 'aZ09');
1017 }
1018 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1019 $newlang = $object->thirdparty->default_lang;
1020 }
1021 if (!empty($newlang)) {
1022 $outputlangs = new Translate("", $conf);
1023 $outputlangs->setDefaultLang($newlang);
1024 }
1025 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1026 }
1027 } else {
1028 $error++;
1029 setEventMessages($object->error, $object->errors, 'errors');
1030 }
1031 }
1032
1033 if (!$error) {
1034 $db->commit();
1035
1036 header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id);
1037 exit;
1038 } else {
1039 $db->rollback();
1040 }
1041 }
1042
1043 if ($action == 'confirm_refuse' && $confirm == 'yes' && $usercanapprove) {
1044 if (GETPOST('refuse_note')) {
1045 $object->refuse_note = GETPOST('refuse_note');
1046 }
1047 $result = $object->refuse($user);
1048 if ($result > 0) {
1049 header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id);
1050 exit;
1051 } else {
1052 setEventMessages($object->error, $object->errors, 'errors');
1053 }
1054 }
1055
1056 // Force mandatory order method
1057 if ($action == 'commande') { // Test on permission not required here
1058 $methodecommande = GETPOSTINT('methodecommande');
1059
1060 if ($cancel) {
1061 $action = '';
1062 } elseif ($methodecommande <= 0 && !getDolGlobalInt('SUPPLIER_ORDER_MODE_OPTIONAL')) {
1063 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("OrderMode")), null, 'errors');
1064 $action = 'createorder';
1065 }
1066 }
1067
1068 if ($action == 'confirm_commande' && $confirm == 'yes' && $usercanorder) {
1069 $db->begin();
1070 $object->context["sendmanualtriggers"] = GETPOST("manual_trigger_send");
1071 $result = $object->commande($user, GETPOSTINT("datecommande"), GETPOSTINT("methode"), GETPOST('comment'));
1072 if ($result > 0) {
1073 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1074 $outputlangs = $langs;
1075 $newlang = '';
1076 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
1077 $newlang = GETPOST('lang_id', 'aZ09');
1078 }
1079 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1080 $newlang = $object->thirdparty->default_lang;
1081 }
1082 if (!empty($newlang)) {
1083 $outputlangs = new Translate("", $conf);
1084 $outputlangs->setDefaultLang($newlang);
1085 }
1086 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1087 }
1088 $action = '';
1089 } else {
1090 $error++;
1091 setEventMessages($object->error, $object->errors, 'errors');
1092 }
1093
1094 if (!$error) {
1095 $db->commit();
1096
1097 header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id);
1098 exit;
1099 } else {
1100 $db->rollback();
1101 }
1102 }
1103
1104
1105 if ($action == 'confirm_delete' && $confirm == 'yes' && $usercandelete) {
1106 // Delete existing dispatched lines
1107 $errOnDelete = 0;
1108 $errorsOnDelete = array();
1109
1110 $db->begin();
1111
1112 if ($stockDelete) {
1113 // TODO We must find line already recorded in stock, not lines dispatched (stock recording may not have been done
1114 // even if dispatched in llx_receptiondet_batch)
1115 // For example to know if stock movement were already record, we may look at stock movements in llx_stock_movement linked to a reception
1116 // that is linked to the purchase order.
1117
1118 /*
1119 $dispatchedLines = $object->getDispachedLines();
1120
1121 if (!empty($dispatchedLines)) {
1122 foreach ($dispatchedLines as $dispatchedLine) {
1123 $supplierorderdispatch = new CommandeFournisseurDispatch($db);
1124 $result = $supplierorderdispatch->fetch($dispatchedLine['id']);
1125 if ($result > 0) {
1126 $result = $supplierorderdispatch->delete($user);
1127 }
1128 if ($result < 0) {
1129 $errorsOnDelete = $object->errors;
1130 $errOnDelete++;
1131 }
1132 }
1133 }
1134
1135 if ($entrepot > 0 && $product > 0 && isModEnabled('enabled')) {
1136 $stockMovementLines = $object->getstockMovementLines()
1137
1138 if (!empty($stockMovementLines)) {
1139 foreach($stockMovementLines as $stockmovementline) {
1140 $qty = $stockmovementline->qty;
1141 $entrepot = $stockmovementline->fk_entrepot;
1142 $product = $stockmovementline->fk_product;
1143 $price = $stockmovementline->price;
1144 $comment = $langs->trans('SupplierOrderDeletion', $object->ref);
1145 $eatby = $stockmovementline->eatby;
1146 $sellby = $stockmovementline->sellby;
1147 $batch = $stockmovementline->batch;
1148
1149 $mouv = new MouvementStock($db);
1150 $mouv->setOrigin($object->element, $object->id);
1151 $result = $mouv->livraison($user, $product, $entrepot, $qty, $price, $comment, '', $eatby, $sellby, $batch);
1152 if ($result < 0) {
1153 $errorsOnDelete = $mouv->errors;
1154 $errOnDelete++;
1155 }
1156 }
1157 }
1158 }
1159 */
1160 }
1161
1162 // @phpstan-ignore-next-line
1163 if (empty($errOnDelete)) {
1164 $result = $object->delete($user);
1165 if ($result > 0) {
1166 $db->commit();
1167 header("Location: " . DOL_URL_ROOT . '/fourn/commande/list.php?restore_lastsearch_values=1');
1168 exit;
1169 } else {
1170 $db->rollback();
1171 setEventMessages($object->error, $object->errors, 'errors');
1172 }
1173 } else {
1174 $db->rollback();
1175 setEventMessages('', $errorsOnDelete, 'errors');
1176 }
1177 }
1178
1179 // Action clone object
1180 if ($action == 'confirm_clone' && $confirm == 'yes' && $usercancreate) {
1181 // @phan-suppress-next-line PhanPluginBothLiteralsBinaryOp
1182 if (1 == 0 && !GETPOST('clone_content') && !GETPOST('clone_receivers')) {
1183 setEventMessages($langs->trans("NoCloneOptionsSpecified"), null, 'errors');
1184 } else {
1185 if ($object->id > 0) {
1186 $orig = clone $object;
1187
1188 $result = $object->createFromClone($user, $socid);
1189 if ($result > 0) {
1190 header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result);
1191 exit;
1192 } else {
1193 setEventMessages($object->error, $object->errors, 'errors');
1194 $object = $orig;
1195 $action = '';
1196 }
1197 }
1198 }
1199 }
1200
1201 // Set status of reception (complete, partial, ...)
1202 if ($action == 'livraison' && $usercanreceive) {
1203 if ($cancel) {
1204 $action = '';
1205 } else {
1206 $db->begin();
1207
1208 if (GETPOST("type") != '') {
1209 $date_liv = dol_mktime(GETPOSTINT('rehour'), GETPOSTINT('remin'), GETPOSTINT('resec'), GETPOSTINT("remonth"), GETPOSTINT("reday"), GETPOSTINT("reyear"));
1210
1211 $result = $object->Livraison($user, $date_liv, GETPOST("type"), GETPOST("comment")); // GETPOST("type") is 'tot', 'par', 'nev', 'can'
1212 if ($result > 0) {
1213 $langs->load("sendings");
1214 setEventMessages($langs->trans("DeliveryStateSaved"), null);
1215 $action = '';
1216 } else {
1217 //if ($result == -3) {}
1218 $error++;
1219 setEventMessages($object->error, $object->errors, 'errors');
1220 }
1221 } else {
1222 $error++;
1223 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Delivery")), null, 'errors');
1224 }
1225
1226 if (!$error) {
1227 $db->commit();
1228 } else {
1229 $db->rollback();
1230 }
1231 }
1232 }
1233
1234 if ($action == 'confirm_cancel' && $confirm == 'yes' && $usercanorder) {
1235 if (GETPOST('cancel_note')) {
1236 $object->cancel_note = GETPOST('cancel_note');
1237 }
1238 $result = $object->cancel($user);
1239 if ($result > 0) {
1240 header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id);
1241 exit;
1242 } else {
1243 setEventMessages($object->error, $object->errors, 'errors');
1244 }
1245 }
1246
1247 // Actions when printing a doc from card
1248 include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
1249
1250 // Actions to send emails
1251 $triggersendname = 'ORDER_SUPPLIER_SENTBYMAIL';
1252 $autocopy = 'MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO';
1253 $trackid = 'sord'.$object->id;
1254 include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
1255
1256 // Actions to build doc
1257 $upload_dir = $conf->fournisseur->commande->dir_output;
1258 include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
1259
1260
1261 if ($action == 'update_extras' && $permissiontoeditextra) {
1262 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
1263
1264 $attribute_name = GETPOST('attribute', 'aZ09');
1265
1266 // Fill array 'array_options' with data from update form
1267 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
1268 if ($ret < 0) {
1269 $error++;
1270 }
1271
1272 if (!$error) {
1273 $result = $object->updateExtraField($attribute_name, 'ORDER_SUPPLIER_MODIFY');
1274 if ($result < 0) {
1275 setEventMessages($object->error, $object->errors, 'errors');
1276 $error++;
1277 }
1278 }
1279
1280 if ($error) {
1281 $action = 'edit_extras';
1282 }
1283 }
1284
1285 /*
1286 * Create an order
1287 */
1288 if ($action == 'add' && $permissiontoadd) {
1289 $error = 0;
1290 $selectedLines = GETPOST('toselect', 'array:int');
1291 if ($socid < 1) {
1292 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Supplier')), null, 'errors');
1293 $action = 'create';
1294 $error++;
1295 }
1296
1297 if (!$error) {
1298 $db->begin();
1299
1300 // Creation commande
1301 $object->ref_supplier = GETPOST('refsupplier');
1302 $object->socid = $socid;
1303 $object->cond_reglement_id = GETPOSTINT('cond_reglement_id');
1304 $object->deposit_percent = GETPOSTFLOAT('cond_reglement_id_deposit_percent');
1305 $object->mode_reglement_id = GETPOSTINT('mode_reglement_id');
1306 $object->fk_account = GETPOSTINT('fk_account');
1307 $object->note_private = GETPOST('note_private', 'restricthtml');
1308 $object->note_public = GETPOST('note_public', 'restricthtml');
1309 $object->delivery_date = $datelivraison;
1310 $object->fk_incoterms = GETPOSTINT('incoterm_id');
1311 $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
1312 $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
1313 $object->multicurrency_tx = GETPOSTFLOAT('originmulticurrency_tx');
1314 $object->fk_project = GETPOSTINT('projectid');
1315
1316 // Fill array 'array_options' with data from add form
1317 if (!$error) {
1318 $ret = $extrafields->setOptionalsFromPost(null, $object);
1319 if ($ret < 0) {
1320 $error++;
1321 }
1322 }
1323
1324 if (!$error) {
1325 // If creation from another object of another module (Example: origin=propal, originid=1)
1326 if (!empty($origin) && !empty($originid)) {
1327 $element = $subelement = $origin;
1328 $classname = ucfirst($subelement);
1329 if ($origin == 'propal' || $origin == 'proposal') {
1330 $element = 'comm/propal';
1331 $subelement = 'propal';
1332 $classname = 'Propal';
1333 }
1334 if ($origin == 'order' || $origin == 'commande') {
1335 $element = $subelement = 'commande';
1336 $classname = 'Commande';
1337 }
1338 if ($origin == 'supplier_proposal') {
1339 $classname = 'SupplierProposal';
1340 $element = 'supplier_proposal';
1341 $subelement = 'supplier_proposal';
1342 }
1343
1344 $object->origin = $origin;
1345 $object->origin_type = $origin;
1346 $object->origin_id = $originid;
1347
1348 // Possibility to add external linked objects with hooks
1349 $object->linked_objects[$object->origin_type] = $object->origin_id;
1350 $other_linked_objects = GETPOST('other_linked_objects', 'array');
1351 if (!empty($other_linked_objects)) {
1352 $object->linked_objects = array_merge($object->linked_objects, $other_linked_objects);
1353 }
1354
1355 $id = $object->create($user);
1356 if ($id > 0) {
1357 dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
1358
1359 $srcobject = new $classname($db);
1360
1361 dol_syslog("Try to find source object origin=".$object->origin_type." originid=".$object->origin_id." to add lines");
1362 $result = $srcobject->fetch($object->origin_id);
1363 if ($result > 0) {
1364 if (empty($object->delivery_date)) {
1365 $tmpdate = $srcobject->delivery_date;
1366 $object->setDeliveryDate($user, $tmpdate);
1367 }
1368 $object->set_id_projet($user, $srcobject->fk_project);
1369
1370 $lines = $srcobject->lines;
1371 if (empty($lines) && method_exists($srcobject, 'fetch_lines')) {
1372 $srcobject->fetch_lines();
1373 $lines = $srcobject->lines;
1374 }
1375
1376 $fk_parent_line = 0;
1377 $num = count($lines);
1378
1379 for ($i = 0; $i < $num; $i++) {
1380 if (
1381 empty($lines[$i]->subprice)
1382 || $lines[$i]->qty < 0
1383 || !in_array($lines[$i]->id, $selectedLines)
1384 || $lines[$i]->special_code == SUBTOTALS_SPECIAL_CODE
1385 ) {
1386 continue;
1387 }
1388
1389 $label = (!empty($lines[$i]->label) ? $lines[$i]->label : '');
1390 $desc = (!empty($lines[$i]->desc) ? $lines[$i]->desc : '');
1391 $product_type = (!empty($lines[$i]->product_type) ? $lines[$i]->product_type : 0);
1392 // Reset fk_parent_line for no child products and special product
1393 if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) {
1394 $fk_parent_line = 0;
1395 }
1396
1397 // Extrafields
1398 if (method_exists($lines[$i], 'fetch_optionals')) { // For avoid conflicts if
1399 $lines[$i]->fetch_optionals();
1400 $array_option = $lines[$i]->array_options;
1401 } else {
1402 $array_option = array();
1403 }
1404
1405 $ref_supplier = '';
1406 $product_fourn_price_id = 0;
1407 if ($origin == "commande") {
1408 $productsupplier = new ProductFournisseur($db);
1409 $result = $productsupplier->find_min_price_product_fournisseur($lines[$i]->fk_product, $lines[$i]->qty, $object->socid);
1410 $lines[$i]->subprice = 0;
1411 if ($result > 0) {
1412 $ref_supplier = $productsupplier->ref_supplier;
1413 $product_fourn_price_id = $productsupplier->product_fourn_price_id;
1414 // we need supplier subprice
1415 foreach ($srcobject->lines as $li) {
1416 $sql = 'SELECT price, unitprice, tva_tx, remise_percent, entity, ref_fourn';
1417 $sql .= ' FROM '.MAIN_DB_PREFIX.'product_fournisseur_price';
1418 $sql .= ' WHERE fk_product = '.((int) $li->fk_product);
1419 $sql .= ' AND entity IN ('.getEntity('product_fournisseur_price').')';
1420 $sql .= ' AND fk_soc = '.((int) $object->socid);
1421 $sql .= ' ORDER BY unitprice ASC';
1422
1423 $resql = $db->query($sql);
1424 if ($resql) {
1425 $num_row = $db->num_rows($resql);
1426 if (empty($num_row)) {
1427 $li->remise_percent = 0;
1428 } else {
1429 $obj = $db->fetch_object($resql);
1430 $li->subprice = $obj->unitprice;
1431 $li->remise_percent = $obj->remise_percent;
1432 }
1433 } else {
1434 dol_print_error($db);
1435 }
1436 $db->free($resql);
1437 }
1438 }
1439 } else {
1440 $ref_supplier = $lines[$i]->ref_fourn;
1441 $product_fourn_price_id = 0;
1442 }
1443
1444 $tva_tx = $lines[$i]->tva_tx;
1445
1446 if ($origin == "commande") {
1447 $soc = new Societe($db);
1448 $soc->fetch($socid);
1449 $tva_tx = get_default_tva($soc, $mysoc, $lines[$i]->fk_product, $product_fourn_price_id);
1450 }
1451
1452 $result = $object->addline(
1453 $desc,
1454 $lines[$i]->subprice,
1455 $lines[$i]->qty,
1456 $tva_tx,
1457 $lines[$i]->localtax1_tx,
1458 $lines[$i]->localtax2_tx,
1459 $lines[$i]->fk_product > 0 ? $lines[$i]->fk_product : 0,
1460 $product_fourn_price_id,
1461 $ref_supplier,
1462 $lines[$i]->remise_percent,
1463 'HT',
1464 0,
1465 $lines[$i]->product_type,
1466 0,
1467 0,
1468 null,
1469 null,
1470 $array_option,
1471 $lines[$i]->fk_unit,
1472 0,
1473 $element,
1474 !empty($lines[$i]->id) ? $lines[$i]->id : $lines[$i]->rowid,
1475 -1,
1476 $lines[$i]->special_code
1477 );
1478
1479 if ($result < 0) {
1480 setEventMessages($object->error, $object->errors, 'errors');
1481 $error++;
1482 break;
1483 }
1484
1485 // Defined the new fk_parent_line
1486 if ($result > 0 && $lines[$i]->product_type == 9) {
1487 $fk_parent_line = $result;
1488 }
1489 }
1490
1491 // Add link between elements
1492
1493
1494 // Hooks
1495 $parameters = array('objFrom' => $srcobject);
1496 $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been
1497
1498 if ($reshook < 0) {
1499 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1500 $error++;
1501 }
1502 } else {
1503 setEventMessages($srcobject->error, $srcobject->errors, 'errors');
1504 $error++;
1505 }
1506 } else {
1507 setEventMessages($object->error, $object->errors, 'errors');
1508 $error++;
1509 }
1510 } else {
1511 $id = $object->create($user);
1512 if ($id < 0) {
1513 $error++;
1514 setEventMessages($object->error, $object->errors, 'errors');
1515 }
1516 }
1517 }
1518
1519 if (isModEnabled('category')) {
1520 $categories = GETPOST('categories', 'array:int');
1521 if (method_exists($object, 'setCategories')) {
1522 $object->setCategories($categories);
1523 }
1524 }
1525
1526 if ($error) {
1527 $langs->load("errors");
1528 $db->rollback();
1529 $action = 'create';
1530 } else {
1531 $db->commit();
1532 header("Location: ".$_SERVER['PHP_SELF']."?id=".urlencode((string) ($id)));
1533 exit;
1534 }
1535 }
1536 }
1537
1538 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
1539 if ($action == 'addcontact' && $permissiontoadd) {
1540 if ($object->id > 0) {
1541 $contactid = (GETPOST('userid') ? GETPOSTINT('userid') : GETPOSTINT('contactid'));
1542 $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
1543 $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09'));
1544 }
1545
1546 if ($result >= 0) {
1547 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1548 exit;
1549 } else {
1550 if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
1551 $langs->load("errors");
1552 setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
1553 } else {
1554 setEventMessages($object->error, $object->errors, 'errors');
1555 }
1556 }
1557 } elseif ($action == 'swapstatut' && $object->id > 0 && $permissiontoadd) {
1558 // bascule du statut d'un contact
1559 $result = $object->swapContactStatus(GETPOSTINT('ligne'));
1560 } elseif ($action == 'deletecontact' && $object->id > 0 && $permissiontoadd) {
1561 // Efface un contact
1562 $result = $object->delete_contact(GETPOSTINT("lineid"));
1563
1564 if ($result >= 0) {
1565 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1566 exit;
1567 } else {
1568 dol_print_error($db);
1569 }
1570 }
1571 }
1572}
1573
1574
1575/*
1576 * View
1577 */
1578
1579$form = new Form($db);
1580$formfile = new FormFile($db);
1581$formorder = new FormOrder($db);
1582$productstatic = new Product($db);
1583if (isModEnabled('project')) {
1584 $formproject = new FormProjets($db);
1585}
1586
1587$title = $object->ref." - ".$langs->trans('Card');
1588if ($action == 'create') {
1589 $title = $langs->trans("NewOrderSupplier");
1590}
1591$help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores';
1592llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-supplier-order page-card');
1593
1594$now = dol_now();
1595
1596if ($action == 'create') {
1597 print load_fiche_titre($langs->trans('NewOrderSupplier'), '', 'supplier_order');
1598
1600
1601 $currency_code = $conf->currency;
1602
1603 $societe = '';
1604 $objectsrc = null;
1605
1606 if ($socid > 0) {
1607 $societe = new Societe($db);
1608 $societe->fetch($socid);
1609 }
1610
1611 if (!empty($origin) && !empty($originid)) {
1612 // Parse element/subelement (ex: project_task)
1613 $element = $subelement = $origin;
1614 $classname = ucfirst($subelement);
1615 $regs = array();
1616 if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
1617 $element = $regs[1];
1618 $subelement = $regs[2];
1619 }
1620
1621 if ($origin == 'propal' || $origin == 'proposal') {
1622 $classname = 'Propal';
1623 $element = 'comm/propal';
1624 $subelement = 'propal';
1625 }
1626 if ($origin == 'order' || $origin == 'commande') {
1627 $classname = 'Commande';
1628 $element = $subelement = 'commande';
1629 }
1630 if ($origin == 'supplier_proposal') {
1631 $classname = 'SupplierProposal';
1632 $element = 'supplier_proposal';
1633 $subelement = 'supplier_proposal';
1634 }
1635
1636
1637 dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
1638
1639 $objectsrc = new $classname($db);
1640 $objectsrc->fetch($originid);
1641 if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
1642 $objectsrc->fetch_lines();
1643 }
1644 $objectsrc->fetch_thirdparty();
1645
1646 // Replicate extrafields
1647 $objectsrc->fetch_optionals();
1648 $object->array_options = $objectsrc->array_options;
1649
1650 $projectid = (int) $objectsrc->fk_project;
1651 $ref_client = (!empty($objectsrc->ref_client) ? $objectsrc->ref_client : '');
1652 $fk_account = 0;
1653 if ($origin == "commande") {
1654 $cond_reglement_id = 0;
1655 $deposit_percent = 0;
1656 $mode_reglement_id = 0;
1657 $datelivraison = '';
1658 $objectsrc->note_private = '';
1659 $objectsrc->note_public = '';
1660 if ($societe = $object->thirdparty) {
1661 $cond_reglement_id = $societe->cond_reglement_supplier_id;
1662 $deposit_percent = $societe->deposit_percent;
1663 $mode_reglement_id = $societe->mode_reglement_supplier_id;
1664 if (isModEnabled("multicurrency")) {
1665 $currency_code = $societe->multicurrency_code;
1666 if (getDolGlobalString('MULTICURRENCY_USE_ORIGIN_TX')) {
1667 $currency_tx = $societe->multicurrency_tx;
1668 }
1669 }
1670 }
1671 } else {
1672 $soc = $objectsrc->thirdparty;
1673
1674 $cond_reglement_id = (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_id) ? $soc->cond_reglement_id : 0));
1675 $deposit_percent = (!empty($objectsrc->deposit_percent) ? $objectsrc->deposit_percent : (!empty($soc->deposit_percent) ? $soc->deposit_percent : 0));
1676 $mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_id) ? $soc->mode_reglement_id : 0));
1677 $fk_account = (!empty($objectsrc->fk_account) ? $objectsrc->fk_account : (!empty($soc->fk_account) ? $soc->fk_account : 0));
1678 $availability_id = (!empty($objectsrc->availability_id) ? $objectsrc->availability_id : (!empty($soc->availability_id) ? $soc->availability_id : 0));
1679 $shipping_method_id = (!empty($objectsrc->shipping_method_id) ? $objectsrc->shipping_method_id : (!empty($soc->shipping_method_id) ? $soc->shipping_method_id : 0));
1680 $demand_reason_id = (!empty($objectsrc->demand_reason_id) ? $objectsrc->demand_reason_id : (!empty($soc->demand_reason_id) ? $soc->demand_reason_id : 0));
1681 //$remise_percent = (!empty($objectsrc->remise_percent) ? $objectsrc->remise_percent : (!empty($soc->remise_supplier_percent) ? $soc->remise_supplier_percent : 0));
1682 //$remise_absolue = (!empty($objectsrc->remise_absolue) ? $objectsrc->remise_absolue : (!empty($soc->remise_absolue) ? $soc->remise_absolue : 0));
1683 $dateinvoice = getDolGlobalString('MAIN_AUTOFILL_DATE') ? '' : -1;
1684
1685 $datelivraison = (!empty($objectsrc->delivery_date) ? $objectsrc->delivery_date : '');
1686
1687 if (isModEnabled("multicurrency")) {
1688 if (!empty($objectsrc->multicurrency_code)) {
1689 $currency_code = $objectsrc->multicurrency_code;
1690 }
1691 if (getDolGlobalString('MULTICURRENCY_USE_ORIGIN_TX') && !empty($objectsrc->multicurrency_tx)) {
1692 $currency_tx = $objectsrc->multicurrency_tx;
1693 }
1694 }
1695
1696 $note_private = $object->getDefaultCreateValueFor('note_private', (!empty($objectsrc->note_private) ? $objectsrc->note_private : null));
1697 $note_public = $object->getDefaultCreateValueFor('note_public', (!empty($objectsrc->note_public) ? $objectsrc->note_public : null));
1698
1699 // Object source contacts list
1700 $srccontactslist = $objectsrc->liste_contact(-1, 'external', 1);
1701 }
1702 } else {
1703 $cond_reglement_id = !empty($societe->cond_reglement_supplier_id) ? $societe->cond_reglement_supplier_id : 0;
1704 $deposit_percent = !empty($societe->deposit_percent) ? $societe->deposit_percent : 0;
1705 $mode_reglement_id = !empty($societe->mode_reglement_supplier_id) ? $societe->mode_reglement_supplier_id : 0;
1706
1707 if (isModEnabled("multicurrency") && !empty($societe->multicurrency_code)) {
1708 $currency_code = $societe->multicurrency_code;
1709 }
1710
1711 $note_private = $object->getDefaultCreateValueFor('note_private');
1712 $note_public = $object->getDefaultCreateValueFor('note_public');
1713 }
1714
1715 // If not defined, set default value from constant
1716 if (empty($cond_reglement_id) && getDolGlobalString('SUPPLIER_ORDER_DEFAULT_PAYMENT_TERM_ID')) {
1717 $cond_reglement_id = getDolGlobalString('SUPPLIER_ORDER_DEFAULT_PAYMENT_TERM_ID');
1718 }
1719 if (empty($mode_reglement_id) && getDolGlobalString('SUPPLIER_ORDER_DEFAULT_PAYMENT_MODE_ID')) {
1720 $mode_reglement_id = getDolGlobalString('SUPPLIER_ORDER_DEFAULT_PAYMENT_MODE_ID');
1721 }
1722 if (GETPOSTISSET('cond_reglement_id_deposit_percent')) {
1723 $deposit_percent = GETPOSTFLOAT('cond_reglement_id_deposit_percent');
1724 }
1725
1726 print '<form name="add" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1727 print '<input type="hidden" name="token" value="'.newToken().'">';
1728 print '<input type="hidden" name="action" value="add">';
1729 print '<input type="hidden" name="remise_percent" value="'.(empty($soc->remise_supplier_percent) ? '' : $soc->remise_supplier_percent).'">';
1730 print '<input type="hidden" name="origin" value="'.$origin.'">';
1731 print '<input type="hidden" name="originid" value="'.$originid.'">';
1732 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
1733 if ($backtopage) {
1734 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1735 }
1736 if ($backtopageforcancel) {
1737 print '<input type="hidden" name="backtopageforcancel" value="'.$backtopageforcancel.'">';
1738 }
1739
1740 if (!empty($currency_tx)) {
1741 print '<input type="hidden" name="originmulticurrency_tx" value="'.$currency_tx.'">';
1742 }
1743
1744 print dol_get_fiche_head(array());
1745
1746 // Call Hook tabContentCreateSupplierOrder
1747 $parameters = array();
1748 // Note that $action and $object may be modified by hook
1749 $reshook = $hookmanager->executeHooks('tabContentCreateSupplierOrder', $parameters, $object, $action);
1750 if (empty($reshook)) {
1751 print '<table class="border centpercent">';
1752
1753 // Ref
1754 print '<tr><td class="titlefieldcreate">'.$langs->trans('Ref').'</td><td>'.$langs->trans('Draft').'</td></tr>';
1755
1756 // Third party
1757 print '<tr><td class="fieldrequired">'.$langs->trans('Supplier').'</td>';
1758 print '<td>';
1759
1760 if (!empty($societe->id) && $societe->id > 0) {
1761 print $societe->getNomUrl(1, 'supplier');
1762 print '<input type="hidden" name="socid" value="'.$societe->id.'">';
1763 } else {
1764 $filter = '((s.fournisseur:=:1) AND (s.status:=:1))';
1765 print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company((empty($socid) ? '' : $socid), 'socid', $filter, 'SelectThirdParty', 1, 0, array(), 0, 'minwidth175 maxwidth500 widthcentpercentminusxx');
1766 // reload page to retrieve customer information
1767 if (!getDolGlobalString('RELOAD_PAGE_ON_SUPPLIER_CHANGE_DISABLED')) {
1768 print '<script>
1769 $(document).ready(function() {
1770 $("#socid").change(function() {
1771 console.log("We have changed the company - Reload page");
1772 // reload page
1773 $("input[name=action]").val("create");
1774 $("input[name=changecompany]").val("1");
1775 $("form[name=add]").submit();
1776 });
1777 });
1778 </script>';
1779 }
1780 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>';
1781 }
1782 print '</td>';
1783
1784 if (!empty($societe->id) && $societe->id > 0) {
1785 // Discounts for third party
1786 print '<tr><td>'.$langs->trans('Discounts').'</td><td>';
1787
1788 $absolute_discount = $societe->getAvailableDiscounts(null, '', 0, 1);
1789
1790 $thirdparty = $societe;
1791 $discount_type = 1;
1792 $backtopage = urlencode($_SERVER["PHP_SELF"].'?socid='.$thirdparty->id.'&action='.$action.'&origin='.GETPOST('origin').'&originid='.GETPOST('originid'));
1793 include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
1794
1795 print '</td></tr>';
1796 }
1797
1798 // Ref supplier
1799 print '<tr><td>'.$langs->trans('RefSupplier').'</td><td><input name="refsupplier" type="text"></td>';
1800 print '</tr>';
1801
1802 // Payment term
1803 print '<tr><td class="nowrap">'.$langs->trans('PaymentConditionsShort').'</td><td>';
1804 print img_picto('', 'payment', 'class="pictofixedwidth"');
1805 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);
1806 print '</td></tr>';
1807
1808 // Payment mode
1809 print '<tr><td>'.$langs->trans('PaymentMode').'</td><td>';
1810 print img_picto('', 'bank', 'class="pictofixedwidth"');
1811 $form->select_types_paiements((GETPOSTISSET('mode_reglement_id') && GETPOSTINT('mode_reglement_id') != 0) ? GETPOST('mode_reglement_id') : $mode_reglement_id, 'mode_reglement_id');
1812 print '</td></tr>';
1813
1814 // Planned delivery date
1815 print '<tr><td>';
1816 print $langs->trans('DateDeliveryPlanned');
1817 print '</td>';
1818 print '<td>';
1819 $usehourmin = 0;
1820 if (getDolGlobalString('SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE')) {
1821 $usehourmin = 1;
1822 }
1823 print img_picto('', 'action', 'class="pictofixedwidth"');
1824 print $form->selectDate($datelivraison ? $datelivraison : -1, 'liv_', $usehourmin, $usehourmin, 0, "set", 1, 1);
1825 print '</td></tr>';
1826
1827 // Bank Account
1828 if (getDolGlobalString('BANK_ASK_PAYMENT_BANK_DURING_SUPPLIER_ORDER') && isModEnabled("bank")) {
1829 $langs->load("bank");
1830 print '<tr><td>'.$langs->trans('BankAccount').'</td><td>';
1831 print img_picto('', 'bank_account', 'class="pictofixedwidth"');
1832 $form->select_comptes($fk_account ?? '', 'fk_account', 0, '', 1);
1833 print '</td></tr>';
1834 }
1835
1836 // Project
1837 if (isModEnabled('project')) {
1838 $formproject = new FormProjets($db);
1839
1840 $langs->load('projects');
1841 print '<tr><td>'.$langs->trans('Project').'</td><td>';
1842 if (!empty($user->socid)) { // external user: restrict to their own third party
1843 $projSocFilter = $user->socid;
1844 } elseif (getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') || $socid == 0) {
1845 // Give priority to the constant (as on supplier invoice), so a supplier document created from a
1846 // customer project keeps that project selected after the supplier is chosen.
1847 $projSocFilter = -1;
1848 } else {
1849 $projSocFilter = $socid;
1850 }
1851 print img_picto('', 'project', 'class="pictofixedwidth"').$formproject->select_projects($projSocFilter, $projectid, 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500');
1852 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>';
1853 print '</td></tr>';
1854 }
1855
1856 // Incoterms
1857 if (isModEnabled('incoterm')) {
1858 $fkincoterms = (!empty($object->fk_incoterms) ? $object->fk_incoterms : ($socid > 0 ? $societe->fk_incoterms : ''));
1859 $locincoterms = (!empty($object->location_incoterms) ? $object->location_incoterms : ($socid > 0 ? $societe->location_incoterms : ''));
1860 print '<tr>';
1861 print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $object->label_incoterms, 1).'</label></td>';
1862 print '<td class="maxwidthonsmartphone">';
1863 print img_picto('', 'incoterm', 'class="pictofixedwidth"');
1864 print $form->select_incoterms($fkincoterms, $locincoterms);
1865 print '</td></tr>';
1866 }
1867
1868 // Multicurrency
1869 if (isModEnabled("multicurrency")) {
1870 print '<tr>';
1871 print '<td>'.$form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0).'</td>';
1872 print '<td class="maxwidthonsmartphone">';
1873 print img_picto('', 'currency', 'class="pictofixedwidth"');
1874 print $form->selectMultiCurrency($currency_code, 'multicurrency_code');
1875 print '</td></tr>';
1876 }
1877
1878 // Categories
1879 if (isModEnabled("category")) {
1880 print '<tr><td>'.$langs->trans("Categories").'</td><td colspan="3">';
1881 print $form->selectCategories(Categorie::TYPE_SUPPLIER_ORDER, 'categories', $object);
1882 print "</td></tr>";
1883 }
1884
1885 print '<tr><td>'.$langs->trans('NotePublic').'</td>';
1886 print '<td>';
1887 $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%');
1888 print $doleditor->Create(1);
1889 print '</td>';
1890 //print '<textarea name="note_public" wrap="soft" cols="60" rows="'.ROWS_5.'"></textarea>';
1891 print '</tr>';
1892
1893 print '<tr><td>'.$langs->trans('NotePrivate').'</td>';
1894 print '<td>';
1895 $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%');
1896 print $doleditor->Create(1);
1897 print '</td>';
1898 //print '<td><textarea name="note_private" wrap="soft" cols="60" rows="'.ROWS_5.'"></textarea></td>';
1899 print '</tr>';
1900
1901 if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
1902 print "\n<!-- ".$classname." info -->";
1903 print "\n";
1904 print '<input type="hidden" name="amount" value="'.$objectsrc->total_ht.'">'."\n";
1905 print '<input type="hidden" name="total" value="'.$objectsrc->total_ttc.'">'."\n";
1906 print '<input type="hidden" name="tva" value="'.$objectsrc->total_tva.'">'."\n";
1907 print '<input type="hidden" name="origin" value="'.$objectsrc->element.'">';
1908 print '<input type="hidden" name="originid" value="'.$objectsrc->id.'">';
1909
1910 $newclassname = $classname;
1911 print '<tr><td>'.$langs->trans($newclassname).'</td><td>'.$objectsrc->getNomUrl(1, 'supplier').'</td></tr>';
1912 print '<tr><td>'.$langs->trans('AmountHT').'</td><td>'.price($objectsrc->total_ht).'</td></tr>';
1913 print '<tr><td>'.$langs->trans('AmountVAT').'</td><td>'.price($objectsrc->total_tva)."</td></tr>";
1914 if ($mysoc->localtax1_assuj == "1" || $objectsrc->total_localtax1 != 0) { // Localtax1 RE
1915 print '<tr><td>'.$langs->transcountry("AmountLT1", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax1)."</td></tr>";
1916 }
1917
1918 if ($mysoc->localtax2_assuj == "1" || $objectsrc->total_localtax2 != 0) { // Localtax2 IRPF
1919 print '<tr><td>'.$langs->transcountry("AmountLT2", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax2)."</td></tr>";
1920 }
1921
1922 print '<tr><td>'.$langs->trans('AmountTTC').'</td><td>'.price($objectsrc->total_ttc)."</td></tr>";
1923
1924 if (isModEnabled("multicurrency")) {
1925 print '<tr><td>'.$langs->trans('MulticurrencyAmountHT').'</td><td>'.price($objectsrc->multicurrency_total_ht).'</td></tr>';
1926 print '<tr><td>'.$langs->trans('MulticurrencyAmountVAT').'</td><td>'.price($objectsrc->multicurrency_total_tva).'</td></tr>';
1927 print '<tr><td>'.$langs->trans('MulticurrencyAmountTTC').'</td><td>'.price($objectsrc->multicurrency_total_ttc).'</td></tr>';
1928 }
1929 }
1930
1931 // Other options
1932 $parameters = array();
1933 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1934 print $hookmanager->resPrint;
1935
1936 if (empty($reshook)) {
1937 if (getDolGlobalString('THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_SUPPLIER_ORDER') && !empty($societe->id)) {
1938 // copy from thirdparty
1939 $tpExtrafields = new ExtraFields($db);
1940 $tpExtrafieldLabels = $tpExtrafields->fetch_name_optionals_label($societe->table_element);
1941 if ($societe->fetch_optionals() > 0) {
1942 $object->array_options = array_merge($object->array_options, $societe->array_options);
1943 }
1944 }
1945
1946 print $object->showOptionals($extrafields, 'create');
1947 }
1948
1949 // Bouton "Create Draft"
1950 print "</table>\n";
1951 }
1952 print dol_get_fiche_end();
1953
1954 print $form->buttonsSaveCancel("CreateDraft");
1955
1956 // Show origin lines
1957 if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
1958 $title = $langs->trans('ProductsAndServices');
1959 print load_fiche_titre($title);
1960
1961 print '<div class="div-table-responsive-no-min">';
1962 print '<table class="noborder centpercent">';
1963
1964 $selectedLines = array();
1965
1966 $objectsrc->printOriginLinesList('', $selectedLines);
1967
1968 print '</table>';
1969 print '</div>';
1970 }
1971 print "</form>\n";
1972} elseif (!empty($object->id)) {
1973 // view
1974 $result = $object->fetch($id, $ref);
1975 $object->fetch_thirdparty();
1976
1977 $societe = $object->thirdparty;
1978
1979 $author = new User($db);
1980 $author->fetch($object->user_author_id);
1981
1982 $head = ordersupplier_prepare_head($object);
1983
1984 $title = $langs->trans("SupplierOrder");
1985 print dol_get_fiche_head($head, 'card', $title, -1, 'order');
1986
1987
1988 $formconfirm = '';
1989
1990 // Confirmation de la suppression de la commande
1991 if ($action == 'delete') {
1992 $arrayAjouts = array();
1993 $heightModal = 0;
1994 $widthModal = 500;
1995
1996 // TODO We must find line already recorded in stock, not lines dispatched (stock recording may not have been done
1997 // even if dispatched in llx_receptiondet_batch).
1998 // For example to know if stock movement were already record, we may look at stock movements in llx_stock_movement linked to a reception
1999 // that is linked to the purchase order.
2000 /* $dispatchedLines = $object->getStockMovementLines();
2001
2002 if (!empty($dispatchedLines)) {
2003 $arrayAjouts = array(
2004 array(
2005 'type' => 'other',
2006 'value' => img_warning() . " " . $langs->trans('ExistingDipatchLines')
2007 ),
2008 array('type' => 'separator'),
2009 array(
2010 'type' => 'select',
2011 'id' => 'stockDeleteSelect',
2012 'name' => 'stockDelete',
2013 'label' => $langs->trans('ConfirmDeleteDispatchedLines'),
2014 'values' => array(1 => $langs->trans('Yes'), 0 => $langs->trans('No')),
2015 'select_show_empty' => false
2016 )
2017 );
2018 $heightModal = 300;
2019 $widthModal = "70%";
2020 }
2021 */
2022
2023 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.((int) $object->id), $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', $arrayAjouts, 0, 2, $heightModal, $widthModal);
2024 }
2025
2026 // Clone confirmation
2027 if ($action == 'clone') {
2028 $filter = '(s.fournisseur:=:1)';
2029 // Create an array for form
2030 $formquestion = array(
2031 array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOSTINT('socid'), 'socid', $filter))
2032 );
2033 // Paiement incomplet. On demande si motif = escompte ou autre
2034 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneOrder', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
2035 }
2036
2037 // Confirmation de la validation
2038 if ($action == 'valid') {
2039 $object->date_commande = dol_now();
2040
2041 // We check if number is temporary number
2042 if (preg_match('/^[\‍(]?PROV/i', (string) $object->ref) || empty($object->ref)) { // empty should not happened, but when it occurs, the test save life
2043 $newref = $object->getNextNumRef($object->thirdparty);
2044 } else {
2045 $newref = (string) $object->ref;
2046 }
2047
2048 if ($newref < 0) {
2049 setEventMessages($object->error, $object->errors, 'errors');
2050 $action = '';
2051 } else {
2052 $text = $langs->trans('ConfirmValidateOrder', $newref);
2053 if (isModEnabled('notification')) {
2054 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2055 $notify = new Notify($db);
2056 $text .= '<br>';
2057 $text .= $notify->confirmMessage('ORDER_SUPPLIER_VALIDATE', $object->socid, $object);
2058 }
2059
2060 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateOrder'), $text, 'confirm_valid', '', 0, 1);
2061 }
2062 }
2063
2064 // Confirm approval
2065 if ($action == 'approve' || $action == 'approve2') {
2066 $qualified_for_stock_change = 0;
2067 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
2068 $qualified_for_stock_change = $object->hasProductsOrServices(2);
2069 } else {
2070 $qualified_for_stock_change = $object->hasProductsOrServices(1);
2071 }
2072
2073 $formquestion = array();
2074 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER') && $qualified_for_stock_change) {
2075 $langs->load("stocks");
2076 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2077 $formproduct = new FormProduct($db);
2078 $forcecombo = 0;
2079 if ($conf->browser->name == 'ie') {
2080 $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2081 }
2082 $formquestion = array(
2083 //'text' => $langs->trans("ConfirmClone"),
2084 //array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2085 //array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2086 array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockIncrease"), 'value' => $formproduct->selectWarehouses(GETPOSTINT('idwarehouse'), 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
2087 );
2088 }
2089 $text = $langs->trans("ConfirmApproveThisOrder", $object->ref);
2090 if (isModEnabled('notification')) {
2091 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2092 $notify = new Notify($db);
2093 $text .= '<br>';
2094 $text .= $notify->confirmMessage('ORDER_SUPPLIER_APPROVE', $object->socid, $object);
2095 }
2096
2097 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("ApproveThisOrder"), $text, "confirm_".$action, $formquestion, 1, 1, 240);
2098 }
2099
2100 // Confirmation of disapproval
2101 if ($action == 'refuse') {
2102 $formquestion = array(
2103 array(
2104 'type' => 'text',
2105 'name' => 'refuse_note',
2106 'label' => $langs->trans("Reason"),
2107 'value' => '',
2108 'morecss' => 'minwidth300'
2109 )
2110 );
2111 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=$object->id", $langs->trans("DenyingThisOrder"), $langs->trans("ConfirmDenyingThisOrder", $object->ref), "confirm_refuse", $formquestion, 0, 1);
2112 }
2113
2114 // Confirmation of cancellation
2115 if ($action == 'cancel') {
2116 $formquestion = array(
2117 array(
2118 'type' => 'text',
2119 'name' => 'cancel_note',
2120 'label' => $langs->trans("Reason"),
2121 'value' => '',
2122 'morecss' => 'minwidth300'
2123 )
2124 );
2125 if (isModEnabled('notification')) {
2126 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2127 $notify = new Notify($db);
2128 $text = '';
2129 $text .= '<br>';
2130 $text .= $notify->confirmMessage('ORDER_SUPPLIER_CANCEL', $object->socid, $object);
2131 }
2132 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=$object->id", $langs->trans("Cancel"), $langs->trans("ConfirmCancelThisOrder", $object->ref), "confirm_cancel", $formquestion, 0, 1);
2133 }
2134
2135 // Confirmation de l'envoi de la commande
2136 if ($action == 'commande') {
2137 $formquestion = array();
2138 $date_com = dol_mktime(GETPOSTINT('rehour'), GETPOSTINT('remin'), GETPOSTINT('resec'), GETPOSTINT("remonth"), GETPOSTINT("reday"), GETPOSTINT("reyear"));
2139 if (isModEnabled('notification')) {
2140 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2141 $notify = new Notify($db);
2142 $text = '';
2143 $text .= '<br>';
2144 $text .= $notify->confirmMessage('ORDER_SUPPLIER_SUBMIT', $object->socid, $object);
2145 }
2146 if (isModEnabled('webhook')) {
2147 require_once DOL_DOCUMENT_ROOT.'/webhook/class/target.class.php';
2148 $targetstatic = new Target($db);
2149 if ($targetstatic->isTriggerCodeManualTarget('ORDER_SUPPLIER_SUBMIT') > 0) {
2150 $formquestion[] = array('type' => 'checkbox', 'name' => 'manual_trigger_send', 'label' => $langs->trans("QuestionSendManualTrigger"));
2151 }
2152 }
2153 $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);
2154 }
2155
2156 // Confirmation to delete line
2157 if ($action == 'ask_deleteline') {
2158 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 0, 1);
2159 }
2160
2161 $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
2162 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2163 if (empty($reshook)) {
2164 $formconfirm .= $hookmanager->resPrint;
2165 } elseif ($reshook > 0) {
2166 $formconfirm = $hookmanager->resPrint;
2167 }
2168
2169 // Print form confirm
2170 print $formconfirm;
2171
2172
2173 // Supplier order card
2174
2175 $linkback = '<a href="'.DOL_URL_ROOT.'/fourn/commande/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
2176
2177 $morehtmlref = '<div class="refidno">';
2178 // Ref supplier
2179 $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, (int) $usercancreate, 'string', '', 0, 1);
2180 $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);
2181 // Thirdparty
2182 $morehtmlref .= '<br>';
2183 if (getDolGlobalString('MAIN_CAN_EDIT_SUPPLIER_ON_SUPPLIER_ORDER') && !empty($usercancreate) && $action == 'edit_thirdparty') {
2184 $morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
2185 $morehtmlref .= '<input type="hidden" name="action" value="set_thirdparty">';
2186 $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
2187 $filter = '(s.fournisseur:=:1)';
2188 $morehtmlref .= $form->select_company($object->thirdparty->id, 'new_socid', $filter, '', 0, 0, array(), 0, 'minwidth300');
2189 $morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
2190 $morehtmlref .= '</form>';
2191 }
2192 if (!getDolGlobalString('MAIN_CAN_EDIT_SUPPLIER_ON_SUPPLIER_ORDER') || $action != 'edit_thirdparty') {
2193 if (getDolGlobalString('MAIN_CAN_EDIT_SUPPLIER_ON_SUPPLIER_ORDER') && $object->status == CommandeFournisseur::STATUS_DRAFT) {
2194 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=edit_thirdparty&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetThirdParty')).'</a>';
2195 }
2196 $morehtmlref .= $object->thirdparty->getNomUrl(1, 'supplier');
2197 if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
2198 $morehtmlref .= ' (<a href="'.DOL_URL_ROOT.'/fourn/commande/list.php?socid='.$object->thirdparty->id.'">'.$langs->trans("OtherOrders").'</a>)';
2199 }
2200 }
2201
2202 // Project
2203 if (isModEnabled('project')) {
2204 $langs->load("projects");
2205 $morehtmlref .= '<br>';
2206 if ($permissiontoadd) {
2207 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
2208 if ($action != 'classify' && $caneditproject) {
2209 $morehtmlref .= '<a class="editfielda" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'classify', 'id' => $object->id], true).'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
2210 }
2211 $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');
2212 } else {
2213 if (!empty($object->fk_project)) {
2214 $proj = new Project($db);
2215 $proj->fetch($object->fk_project);
2216 $morehtmlref .= $proj->getNomUrl(1);
2217 if ($proj->title) {
2218 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
2219 }
2220 }
2221 }
2222 }
2223 $morehtmlref .= '</div>';
2224
2225
2226 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
2227
2228 // Call Hook tabContentViewSupplierOrder
2229 $parameters = array();
2230 // Note that $action and $object may be modified by hook
2231 $reshook = $hookmanager->executeHooks('tabContentViewSupplierOrder', $parameters, $object, $action);
2232 if (empty($reshook)) {
2233 print '<div class="fichecenter">';
2234 print '<div class="fichehalfleft">';
2235 print '<div class="underbanner clearboth"></div>';
2236
2237 print '<table class="border tableforfield centpercent">';
2238
2239 // Date
2240 if ($object->methode_commande_id > 0) {
2241 $usehourmin = 0;
2242 if (getDolGlobalString('SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE')) {
2243 $usehourmin = 1;
2244 }
2245 print '<tr><td class="titlefield">'.$langs->trans("Date").'</td><td>';
2246 print $object->date_commande ? dol_print_date($object->date_commande, $usehourmin ? 'dayhour' : 'day') : '';
2247 if ($object->hasDelay() && !empty($object->delivery_date) && !empty($object->date_commande)) {
2248 print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
2249 }
2250 print "</td></tr>";
2251
2252 if ($object->methode_commande) {
2253 print '<tr><td>'.$langs->trans("Method").'</td><td>'.$object->getInputMethod().'</td></tr>';
2254 }
2255 }
2256
2257 // Author
2258 print '<tr><td class="titlefield">'.$langs->trans("AuthorRequest").'</td>';
2259 print '<td>'.$author->getNomUrl(-1, '', 0, 0, 0).'</td>';
2260 print '</tr>';
2261
2262 // Relative and absolute discounts
2263 if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) {
2264 $filterabsolutediscount = "fk_invoice_supplier_source IS NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
2265 $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
2266 } else {
2267 $filterabsolutediscount = "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')";
2268 $filtercreditnote = "fk_invoice_supplier_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS PAID)%')";
2269 }
2270
2271 $absolute_discount = $societe->getAvailableDiscounts(null, $filterabsolutediscount, 0, 1);
2272 $absolute_creditnote = $societe->getAvailableDiscounts(null, $filtercreditnote, 0, 1);
2273 $absolute_discount = price2num($absolute_discount, 'MT');
2274 $absolute_creditnote = price2num($absolute_creditnote, 'MT');
2275
2276 print '<tr><td class="titlefield">'.$langs->trans('Discounts').'</td><td>';
2277
2278 $thirdparty = $societe;
2279 $discount_type = 1;
2280 $backtopage = urlencode($_SERVER["PHP_SELF"].'?id='.$object->id);
2281 include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
2282
2283 print '</td></tr>';
2284
2285 // Default terms of the settlement
2286 $langs->load('bills');
2287 print '<tr><td class="nowrap">';
2288 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
2289 print $langs->trans('PaymentConditions');
2290 print '<td>';
2291 if ($action != 'editconditions' && $permissiontoadd) {
2292 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>';
2293 }
2294 print '</tr></table>';
2295 print '</td><td>';
2296 if ($action == 'editconditions') {
2297 $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->cond_reglement_id, 'cond_reglement_id', 1, '', 1, $object->deposit_percent);
2298 } else {
2299 $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->cond_reglement_id, 'none', 1, '', 1, $object->deposit_percent);
2300 }
2301 print "</td>";
2302 print '</tr>';
2303
2304 // Mode of payment
2305 $langs->load('bills');
2306 print '<tr><td class="nowrap">';
2307 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
2308 print $langs->trans('PaymentMode');
2309 print '</td>';
2310 if ($action != 'editmode' && $permissiontoadd) {
2311 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>';
2312 }
2313 print '</tr></table>';
2314 print '</td><td>';
2315 if ($action == 'editmode') {
2316 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->mode_reglement_id, 'mode_reglement_id', 'DBIT', 1, 1);
2317 } else {
2318 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->mode_reglement_id, 'none');
2319 }
2320 print '</td></tr>';
2321
2322 // Bank Account
2323 if (getDolGlobalString('BANK_ASK_PAYMENT_BANK_DURING_SUPPLIER_ORDER') && isModEnabled("bank")) {
2324 print '<tr><td class="nowrap">';
2325 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
2326 print $langs->trans('BankAccount');
2327 print '<td>';
2328 if ($action != 'editbankaccount' && $permissiontoadd) {
2329 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>';
2330 }
2331 print '</tr></table>';
2332 print '</td><td>';
2333 if ($action == 'editbankaccount') {
2334 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'fk_account', 1);
2335 } else {
2336 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'none');
2337 }
2338 print '</td>';
2339 print '</tr>';
2340 }
2341
2342 // Delivery delay (in days)
2343 print '<tr>';
2344 print '<td>'.$langs->trans('NbDaysToDelivery').'&nbsp;'.img_picto($langs->trans('DescNbDaysToDelivery'), 'info', 'style="cursor:help"').'</td>';
2345 print '<td>'.$object->getMaxDeliveryTimeDay($langs).'</td>';
2346 print '</tr>';
2347
2348 // Delivery date planned
2349 print '<tr><td>';
2350 print '<table class="nobordernopadding centpercent"><tr><td>';
2351 print $langs->trans('DateDeliveryPlanned');
2352 print '</td>';
2353 if ($action != 'editdate_livraison') {
2354 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>';
2355 }
2356 print '</tr></table>';
2357 print '</td><td>';
2358 if ($action == 'editdate_livraison') {
2359 print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2360 print '<input type="hidden" name="token" value="'.newToken().'">';
2361 print '<input type="hidden" name="action" value="setdate_livraison">';
2362 $usehourmin = 0;
2363 if (getDolGlobalString('SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE')) {
2364 $usehourmin = 1;
2365 }
2366 print $form->selectDate($object->delivery_date ? $object->delivery_date : -1, 'liv_', $usehourmin, $usehourmin, 0, "setdate_livraison");
2367 print '<input type="submit" class="button button-edit smallpaddingimp valign middle" value="'.$langs->trans('Modify').'">';
2368 print '</form>';
2369 } else {
2370 $usehourmin = 'day';
2371 if (getDolGlobalString('SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE')) {
2372 $usehourmin = 'dayhour';
2373 }
2374 print $object->delivery_date ? dol_print_date($object->delivery_date, $usehourmin) : '&nbsp;';
2375 if ($object->hasDelay() && !empty($object->delivery_date) && ($object->status == $object::STATUS_ORDERSENT || $object->status == $object::STATUS_RECEIVED_PARTIALLY)) {
2376 print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
2377 }
2378 }
2379 print '</td></tr>';
2380
2381 // Incoterms
2382 if (isModEnabled('incoterm')) {
2383 print '<tr><td>';
2384 print '<table class="nobordernopadding centpercent"><tr><td>';
2385 print $langs->trans('IncotermLabel');
2386 print '<td><td class="right">';
2387 if ($usercancreate) {
2388 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/fourn/commande/card.php?id='.$object->id.'&action=editincoterm&token='.newToken().'">'.img_edit().'</a>';
2389 } else {
2390 print '&nbsp;';
2391 }
2392 print '</td></tr></table>';
2393 print '</td>';
2394 print '<td>';
2395 if ($action != 'editincoterm') {
2396 print $form->textwithpicto(dol_escape_htmltag($object->display_incoterms()), $object->label_incoterms, 1);
2397 } else {
2398 print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
2399 }
2400 print '</td></tr>';
2401 }
2402
2403 // Tags-Categories
2404 if (isModEnabled('category')) {
2405 print '<tr><td>';
2406 print '<table class="nobordernopadding centpercent"><tr><td>';
2407 print $langs->trans("Categories");
2408 print '<td><td class="right">';
2409 if ($usercancreate) {
2410 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/fourn/commande/card.php?id='.$object->id.'&action=edittags&token='.newToken().'">'.img_edit().'</a>';
2411 } else {
2412 print '&nbsp;';
2413 }
2414 print '</td></tr></table>';
2415 print '</td>';
2416 print '<td>';
2417 if ($action == 'edittags') {
2418 print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
2419 print '<input type="hidden" name="action" value="settags">';
2420 print '<input type="hidden" name="token" value="'.newToken().'">';
2421 print $form->selectCategories(Categorie::TYPE_SUPPLIER_ORDER, 'categories', $object);
2422 print '<input type="submit" class="button valignmiddle smallpaddingimp" value="'.$langs->trans("Modify").'">';
2423 print '</form>';
2424 } else {
2425 print $form->showCategories($object->id, Categorie::TYPE_SUPPLIER_ORDER, 1);
2426 }
2427 print "</td></tr>";
2428 }
2429
2430 // Other attributes
2431 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
2432
2433 print '</table>';
2434
2435 print '</div>';
2436 print '<div class="fichehalfright">';
2437 print '<div class="underbanner clearboth"></div>';
2438
2439 print '<table class="border tableforfield centpercent">';
2440
2441 include DOL_DOCUMENT_ROOT.'/core/tpl/object_currency_amount.tpl.php';
2442
2443 print '<tr>';
2444 // Amount HT
2445 print '<td class="titlefieldmiddle">' . $langs->trans('AmountHT') . '</td>';
2446 print '<td class="nowrap amountcard right">' . price($object->total_ht, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
2447 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2448 // Multicurrency Amount HT
2449 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ht, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2450 }
2451 print '</tr>';
2452
2453 print '<tr>';
2454 // Amount VAT
2455 print '<td class="titlefieldmiddle">' . $langs->trans('AmountVAT') . '</td>';
2456 print '<td class="nowrap amountcard right">' . price($object->total_tva, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
2457 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2458 // Multicurrency Amount VAT
2459 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_tva, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2460 }
2461 print '</tr>';
2462
2463 // Amount Local Taxes
2464 if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) {
2465 print '<tr>';
2466 print '<td class="titlefieldmiddle">' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
2467 print '<td class="nowrap amountcard right">' . price($object->total_localtax1, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
2468 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2469 print '<td class="nowrap amountcard right">' . price($object->total_localtax1, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2470 }
2471 print '</tr>';
2472
2473 if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) {
2474 print '<tr>';
2475 print '<td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
2476 print '<td class="nowrap amountcard right">' . price($object->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
2477 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2478 print '<td class="nowrap amountcard right">' . price($object->total_localtax2, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2479 }
2480 print '</tr>';
2481 }
2482 }
2483
2484 $alert = '';
2485 if (getDolGlobalString('ORDER_MANAGE_MIN_AMOUNT') && $object->total_ht < $object->thirdparty->supplier_order_min_amount) {
2486 $alert = ' ' . img_warning($langs->trans('OrderMinAmount') . ': ' . price($object->thirdparty->supplier_order_min_amount));
2487 }
2488
2489 print '<tr>';
2490 // Amount TTC
2491 print '<td>' . $langs->trans('AmountTTC') . '</td>';
2492 print '<td class="nowrap amountcard right">' . price($object->total_ttc, 0, $langs, 0, -1, -1, $conf->currency) . $alert . '</td>';
2493 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2494 // Multicurrency Amount TTC
2495 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ttc, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2496 }
2497 print '</tr>';
2498
2499 print '</table>';
2500
2501 // Margin Infos
2502 /*if (isModEnabled('margin')) {
2503 $formmargin->displayMarginInfos($object);
2504 }*/
2505
2506
2507 print '</div>';
2508 print '</div>';
2509
2510 print '<div class="clearboth"></div><br>';
2511
2512 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
2513 $blocname = 'contacts';
2514 $title = $langs->trans('ContactsAddresses');
2515 include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
2516 }
2517
2518 if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
2519 $blocname = 'notes';
2520 $title = $langs->trans('Notes');
2521 include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
2522 }
2523
2524 /*
2525 * Lines
2526 */
2527 //$result = $object->getLinesArray();
2528
2529
2530 print ' <form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline') ? '' : '#line_'.GETPOSTINT('lineid')).'" method="POST">
2531 <input type="hidden" name="token" value="'.newToken().'">
2532 <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">
2533 <input type="hidden" name="mode" value="">
2534 <input type="hidden" name="page_y" value="">
2535 <input type="hidden" name="id" value="'.$object->id.'">
2536 <input type="hidden" name="socid" value="'.$societe->id.'">
2537 ';
2538
2539 if (!empty($conf->use_javascript_ajax) && $object->status == 0) {
2540 include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
2541 }
2542
2543 print '<div class="div-table-responsive-no-min">';
2544 print '<table id="tablelines" class="noborder noshadow centpercent">';
2545
2546 // Add free products/services form
2547 global $forceall, $senderissupplier, $dateSelector, $inputalsopricewithtax;
2548 $forceall = 1;
2549 $dateSelector = 0;
2550 $inputalsopricewithtax = 1;
2551 $senderissupplier = 2; // $senderissupplier=2 is same than 1 but disable test on minimum qty and disable autofill qty with minimum.
2552 if (getDolGlobalInt('SUPPLIER_ORDER_WITH_PREDEFINED_PRICES_ONLY')) {
2553 $senderissupplier = getDolGlobalInt('SUPPLIER_ORDER_WITH_PREDEFINED_PRICES_ONLY');
2554 }
2555
2556 // Show object lines
2557 if (!empty($object->lines)) {
2558 $object->printObjectLines($action, $object->thirdparty, $mysoc, $lineid, 1);
2559 }
2560
2561 $num = count($object->lines);
2562
2563 // Form to add new line
2564 if ($object->status == CommandeFournisseur::STATUS_DRAFT && $usercancreate) {
2565 if ($action != 'editline') {
2566 // Add free products/services
2567
2568 $parameters = array();
2569 $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2570 if ($reshook < 0) {
2571 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2572 }
2573 if (empty($reshook)) {
2574 $object->formAddObjectLine(1, $societe, $mysoc);
2575 }
2576 }
2577 }
2578 print '</table>';
2579 print '</div>';
2580 print '</form>';
2581 }
2582
2583 print dol_get_fiche_end();
2584
2589 if ($user->socid == 0 && $action != 'delete') {
2590 if ($action != 'createorder' && $action != 'presend' && $action != 'editline') {
2591 print '<div class="tabsAction">';
2592
2593 $parameters = array();
2594 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
2595 // modified by hook
2596 if (empty($reshook)) {
2597 $object->fetchObjectLinked(); // Links are used to show or not button, so we load them now.
2598
2599 // Validate
2600 if ($object->status == 0 && $num > 0) {
2601 if ($usercanvalidate) {
2602 $tmpbuttonlabel = $langs->trans('Validate');
2603 if ($usercanapprove && !getDolGlobalString('SUPPLIER_ORDER_NO_DIRECT_APPROVE')) {
2604 $tmpbuttonlabel = $langs->trans("ValidateAndApprove");
2605 }
2606
2607 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=valid&token='.newToken().'">';
2608 print $tmpbuttonlabel;
2609 print '</a>';
2610 }
2611 }
2612 // Create event
2613 /*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.
2614 {
2615 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>';
2616 }*/
2617
2618 // Modify
2620 if ($usercanorder) {
2621 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("Modify").'</a>';
2622 }
2623 }
2624
2625 // Approve
2627 if ($usercanapprove) {
2628 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)) {
2629 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("FirstApprovalAlreadyDone")).'">'.$langs->trans("ApproveOrder").'</a>';
2630 } else {
2631 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=approve">'.$langs->trans("ApproveOrder").'</a>';
2632 }
2633 } else {
2634 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$langs->trans("ApproveOrder").'</a>';
2635 }
2636 }
2637
2638 // Second approval (if option SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED is set)
2639 if (getDolGlobalString('SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED') && $object->total_ht >= $conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED) {
2641 if ($usercanapprovesecond) {
2642 if (!empty($object->user_approve_id2)) {
2643 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("SecondApprovalAlreadyDone")).'">'.$langs->trans("Approve2Order").'</a>';
2644 } else {
2645 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=approve2">'.$langs->trans("Approve2Order").'</a>';
2646 }
2647 } else {
2648 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$langs->trans("Approve2Order").'</a>';
2649 }
2650 }
2651 }
2652
2653 // Refuse
2655 if ($usercanapprove || $usercanapprovesecond) {
2656 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=refuse">'.$langs->trans("RefuseOrder").'</a>';
2657 } else {
2658 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$langs->trans("RefuseOrder").'</a>';
2659 }
2660 }
2661
2662 // Send
2663 if (empty($user->socid)) {
2664 if (in_array($object->status, array(CommandeFournisseur::STATUS_ACCEPTED, 3, 4, 5)) || getDolGlobalString('SUPPLIER_ORDER_SENDBYEMAIL_FOR_ALL_STATUS')) {
2665 if ($usercanorder) {
2666 print dolGetButtonAction('', $langs->trans('SendMail'), 'email', dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id, 'action' => 'presend', 'mode' => 'init'], true).'#formmailbeforetitle', '');
2667 }
2668 }
2669 }
2670
2671 // Reopen
2672 if (in_array($object->status, array(CommandeFournisseur::STATUS_ACCEPTED))) {
2673 $buttonshown = 0;
2674 if (!$buttonshown && $usercanapprove) {
2675 if (!getDolGlobalString('SUPPLIER_ORDER_REOPEN_BY_APPROVER_ONLY')
2676 || (getDolGlobalString('SUPPLIER_ORDER_REOPEN_BY_APPROVER_ONLY') && $user->id == $object->user_approve_id)) {
2677 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("Disapprove").'</a>';
2678 $buttonshown++;
2679 }
2680 }
2681 if (!$buttonshown && $usercanapprovesecond && getDolGlobalString('SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED')) {
2682 if (!getDolGlobalString('SUPPLIER_ORDER_REOPEN_BY_APPROVER2_ONLY')
2683 || (getDolGlobalString('SUPPLIER_ORDER_REOPEN_BY_APPROVER2_ONLY') && $user->id == $object->user_approve_id2)) {
2684 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("Disapprove").'</a>';
2685 }
2686 }
2687 }
2688 if (in_array($object->status, array(3, 4, 5, 6, 7, 9))) {
2689 if ($usercanorder) {
2690 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ReOpen").'</a>';
2691 }
2692 }
2693
2694 // Ship
2695 $hasreception = 0;
2696 if (isModEnabled('stock') && (getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER') || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE'))) {
2697 $labelofbutton = $langs->trans('ReceiveProducts');
2698 if (isModEnabled('reception')) {
2699 $labelofbutton = $langs->trans("CreateReception");
2700 if (!empty($object->linkedObjects['reception'])) {
2701 foreach ($object->linkedObjects['reception'] as $element) {
2702 if ($element->statut >= 0) {
2703 $hasreception = 1;
2704 break;
2705 }
2706 }
2707 }
2708 }
2709
2710 // To avoid delete order with dispatched lines
2711 if (getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER')) {
2712 if (empty($object->lines)) {
2713 $object->fetch_lines();
2714 }
2715 $dispachedLines = $object->getDispachedLines(1);
2716 $nbDispachedLines = count($dispachedLines);
2717 if ($nbDispachedLines > 0) {
2718 $hasreception = 1;
2719 }
2720 }
2721
2722 if (in_array($object->status, array(3, 4, 5))) {
2723 if (isModEnabled("supplier_order") && $usercanreceive) {
2724 print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/fourn/commande/dispatch.php?id='.$object->id.'">'.$labelofbutton.'</a></div>';
2725 } else {
2726 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$labelofbutton.'</a></div>';
2727 }
2728 }
2729 }
2730
2732 if ($usercanorder) {
2733 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>';
2734 } else {
2735 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#">'.$langs->trans("MakeOrder").'</a></div>';
2736 }
2737 }
2738
2739 // Classify received (this does not record reception)
2741 if ($usercanreceive) {
2742 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>';
2743 }
2744 }
2745
2746 // Create bill
2747 //if (isModEnabled('facture'))
2748 //{
2749 if (isModEnabled("supplier_invoice") && ($object->status >= 2 && $object->status != 7 && $object->billed != 1)) { // statut 2 means approved, 7 means canceled
2750 if ($user->hasRight('fournisseur', 'facture', 'creer') || $user->hasRight("supplier_invoice", "creer")) {
2751 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>';
2752 }
2753 }
2754 //}
2755
2756 // Classify billed manually (need one invoice if module invoice is on, no condition on invoice if not)
2757 if ($usercancreate && $object->status >= 2 && $object->status != 7 && $object->billed != 1) { // statut 2 means approved
2758 if (!isModEnabled('invoice')) {
2759 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifybilled&token='.newToken().'">'.$langs->trans("ClassifyBilled").'</a>';
2760 } else {
2761 if (!empty($object->linkedObjectsIds['invoice_supplier']) || (empty($object->linkedObjectsIds['invoice_supplier']) && !getDolGlobalInt('SUPPLIER_ORDER_DISABLE_CLASSIFY_BILLED_FROM_SUPPLIER_ORDER'))) {
2762 if ($user->hasRight('fournisseur', 'facture', 'creer') || $user->hasRight("supplier_invoice", "creer")) {
2763 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifybilled&token='.newToken().'">'.$langs->trans("ClassifyBilled").'</a>';
2764 }
2765 } else {
2766 print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NeedAtLeastOneInvoice")).'">'.$langs->trans("ClassifyBilled").'</a>';
2767 }
2768 }
2769 }
2770
2771 // Classify unbilled manually
2772 if ($usercancreate && $object->billed > 0 && $object->status > $object::STATUS_DRAFT) {
2773 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifyunbilled&token='.newToken().'">'.$langs->trans("ClassifyUnbilled").'</a>';
2774 }
2775
2776 // Clone
2777 if ($usercancreate) {
2778 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>';
2779 }
2780
2781 // Cancel
2783 if ($usercanorder) {
2784 print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=cancel&amp;token='.newToken().'">'.$langs->trans("CancelOrder").'</a>';
2785 }
2786 }
2787
2788 // Delete
2789 if (!empty($usercandelete)) {
2790 if ($hasreception) {
2791 print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("ReceptionExist").'">'.$langs->trans("Delete").'</a>';
2792 } else {
2793 print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'">'.$langs->trans("Delete").'</a>';
2794 }
2795 }
2796 }
2797
2798 print "</div>";
2799 }
2800
2801 if ($usercanorder && $object->status == CommandeFournisseur::STATUS_ACCEPTED && $action == 'createorder') {
2802 // Set status to ordered (action=commande)
2803 print '<!-- form to record supplier order -->'."\n";
2804 print '<form name="commande" id="makeorder" action="card.php?id='.$object->id.'&amp;action=commande" method="POST">';
2805
2806 print '<input type="hidden" name="token" value="'.newToken().'">';
2807 print '<input type="hidden" name="action" value="commande">';
2808 print load_fiche_titre($langs->trans("ToOrder"), '', '');
2809 print '<table class="noborder centpercent">';
2810 //print '<tr class="liste_titre"><td colspan="2">'.$langs->trans("ToOrder").'</td></tr>';
2811 print '<tr><td class="fieldrequired">'.$langs->trans("OrderDate").'</td><td>';
2812 $date_com = dol_mktime(GETPOSTINT('rehour'), GETPOSTINT('remin'), GETPOSTINT('resec'), GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
2813 print $form->selectDate($date_com ?: '', '', 0, 0, 0, "commande", 1, 1);
2814 print '</td></tr>';
2815
2816 // Force mandatory order method
2817 print '<tr><td class="fieldrequired">'.$langs->trans("OrderMode").'</td><td>';
2818 $formorder->selectInputMethod(GETPOST('methodecommande'), "methodecommande", 1);
2819 print '</td></tr>';
2820
2821 print '<tr><td>'.$langs->trans("Comment").'</td><td><input class="quatrevingtpercent" type="text" name="comment" value="'.GETPOST('comment').'"></td></tr>';
2822
2823 print '<tr><td class="center" colspan="2">';
2824 print '<input type="submit" name="makeorder" class="button" value="'.$langs->trans("ToOrder").'">';
2825 print ' &nbsp; &nbsp; ';
2826 print '<input type="submit" name="cancel" class="button button-cancel" value="'.$langs->trans("Cancel").'">';
2827 print '</td></tr>';
2828 print '</table>';
2829
2830 print '</form>';
2831 print "<br>";
2832 }
2833
2834 // Select mail models is same action as presend
2835 if (GETPOST('modelselected')) {
2836 $action = 'presend';
2837 }
2838
2839 if ($action != 'createorder' && $action != 'presend') {
2840 print '<div class="fichecenter"><div class="fichehalfleft">';
2841
2842 // Generated documents
2843 $objref = dol_sanitizeFileName($object->ref);
2844 $file = $conf->fournisseur->dir_output.'/commande/'.$objref.'/'.$objref.'.pdf';
2845 $relativepath = $objref.'/'.$objref.'.pdf';
2846 $filedir = $conf->fournisseur->dir_output.'/commande/'.$objref;
2847 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
2848 $genallowed = $usercanread;
2849 $delallowed = $usercancreate;
2850 $modelpdf = (!empty($object->model_pdf) ? $object->model_pdf : (!getDolGlobalString('COMMANDE_SUPPLIER_ADDON_PDF') ? '' : $conf->global->COMMANDE_SUPPLIER_ADDON_PDF));
2851
2852 print $formfile->showdocuments('commande_fournisseur', $objref, $filedir, $urlsource, (int) $genallowed, (int) $delallowed, $modelpdf, 1, 0, 0, 0, 0, '', '', '', $object->thirdparty->default_lang, '', $object);
2853 $somethingshown = $formfile->numoffiles;
2854
2855 // Show links to link elements
2856 $tmparray = $form->showLinkToObjectBlock($object, array(), array('supplier_order', 'order_supplier'), 1);
2857 $linktoelem = $tmparray['linktoelem'];
2858 $htmltoenteralink = $tmparray['htmltoenteralink'];
2859 print $htmltoenteralink;
2860
2861 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
2862
2863 print '</div><div class="fichehalfright">';
2864
2865 if ($action == 'classifyreception') {
2867 // Set status to received (action=livraison)
2868 print '<!-- form to record purchase order received -->'."\n";
2869 print '<form id="classifyreception" action="card.php?id='.$object->id.'" method="post">';
2870 print '<input type="hidden" name="token" value="'.newToken().'">';
2871 print '<input type="hidden" name="action" value="livraison">';
2872 print load_fiche_titre($langs->trans("Receive"), '', '');
2873
2874 print '<table class="noborder centpercent">';
2875 //print '<tr class="liste_titre"><td colspan="2">'.$langs->trans("Receive").'</td></tr>';
2876 print '<tr><td>'.$langs->trans("DeliveryDate").'</td><td>';
2877 $datepreselected = dol_now();
2878 print $form->selectDate($datepreselected, '', 1, 1, 0, "commande", 1, 1);
2879 print "</td></tr>\n";
2880
2881 print '<tr><td class="fieldrequired">'.$langs->trans("Delivery")."</td><td>\n";
2882 $liv = array();
2883 $liv[''] = '&nbsp;';
2884 $liv['tot'] = $langs->trans("CompleteOrNoMoreReceptionExpected");
2885 $liv['par'] = $langs->trans("PartialWoman");
2886 $liv['nev'] = $langs->trans("NeverReceived");
2887 $liv['can'] = $langs->trans("Canceled");
2888
2889 print $form->selectarray("type", $liv);
2890
2891 print '</td></tr>';
2892 print '<tr><td>'.$langs->trans("Comment").'</td><td><input class="quatrevingtpercent" type="text" name="comment"></td></tr>';
2893 print '<tr><td class="center" colspan="2">';
2894 print '<input type="submit" name="receive" class="button" value="'.$langs->trans("Receive").'">';
2895 print ' &nbsp; &nbsp; ';
2896 print '<input type="submit" name="cancel" class="button button-cancel" value="'.$langs->trans("Cancel").'">';
2897 print '</td></tr>';
2898 print "</table>\n";
2899 print "</form>\n";
2900 print "<br>";
2901 }
2902 }
2903
2904 // List of actions on element
2905 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
2906 $formactions = new FormActions($db);
2907 $somethingshown = $formactions->showactions($object, 'order_supplier', $socid, 1, 'listaction'.($genallowed ? 'largetitle' : ''));
2908
2909 print '</div></div>';
2910 }
2911
2912 /*
2913 * Action webservice
2914 */
2915 if ($action == 'webservice' && GETPOST('mode', 'alpha') != "send" && !GETPOST('cancel', 'alpha')) {
2916 $mode = GETPOST('mode', 'alpha');
2917 $ws_url = $object->thirdparty->webservices_url;
2918 $ws_key = $object->thirdparty->webservices_key;
2919 $ws_user = GETPOST('ws_user', 'alpha');
2920 $ws_password = GETPOST('ws_password', 'alpha');
2921 $error_occurred = false;
2922
2923 // NS and Authentication parameters
2924 $ws_ns = 'http://www.dolibarr.org/ns/';
2925 $ws_authentication = array(
2926 'dolibarrkey' => $ws_key,
2927 'sourceapplication' => 'DolibarrWebServiceClient',
2928 'login' => $ws_user,
2929 'password' => $ws_password,
2930 'entity' => ''
2931 );
2932
2933 print load_fiche_titre($langs->trans('CreateRemoteOrder'), '');
2934
2935 //Is everything filled?
2936 if (empty($ws_url) || empty($ws_key)) {
2937 setEventMessages($langs->trans("ErrorWebServicesFieldsRequired"), null, 'errors');
2938 $mode = "init";
2939 $error_occurred = true; //Don't allow to set the user/pass if thirdparty fields are not filled
2940 } elseif ($mode != "init" && (empty($ws_user) || empty($ws_password))) {
2941 setEventMessages($langs->trans("ErrorFieldsRequired"), null, 'errors');
2942 $mode = "init";
2943 }
2944
2945 if ($mode == "init") {
2946 //Table/form header
2947 print '<table class="border centpercent">';
2948 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2949 print '<input type="hidden" name="token" value="'.newToken().'">';
2950 print '<input type="hidden" name="action" value="webservice">';
2951 print '<input type="hidden" name="mode" value="check">';
2952
2953 if ($error_occurred) {
2954 print "<br>".$langs->trans("ErrorOccurredReviseAndRetry")."<br>";
2955 print '<input class="button button-cancel" type="submit" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
2956 } else {
2957 // Webservice url
2958 print '<tr><td>'.$langs->trans("WebServiceURL").'</td><td colspan="3">'.dol_print_url($ws_url).'</td></tr>';
2959 //Remote User
2960 print '<tr><td>'.$langs->trans("User").'</td><td><input class="width100" type="text" name="ws_user"></td></tr>';
2961 //Remote Password
2962 print '<tr><td>'.$langs->trans("Password").'</td><td><input class="width100" type="text" name="ws_password"></td></tr>';
2963 //Submit button
2964 print '<tr><td class="center" colspan="2">';
2965 print '<input type="submit" class="button" id="ws_submit" name="ws_submit" value="'.$langs->trans("CreateRemoteOrder").'">';
2966 print ' &nbsp; &nbsp; ';
2967 //Cancel button
2968 print '<input class="button button-cancel" type="submit" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
2969 print '</td></tr>';
2970 }
2971
2972 //End table/form
2973 print '</form>';
2974 print '</table>';
2975 } elseif ($mode == "check") {
2976 $ws_entity = '';
2977 $ws_thirdparty = '';
2978 $error_occurred = false;
2979
2980 //Create SOAP client and connect it to user
2981 $soapclient_user = new nusoap_client($ws_url."/webservices/server_user.php");
2982 $soapclient_user->soap_defencoding = 'UTF-8';
2983 $soapclient_user->decodeUTF8(false);
2984
2985 //Get the thirdparty associated to user
2986 $ws_parameters = array('authentication' => $ws_authentication, 'id' => '', 'ref' => $ws_user);
2987 $result_user = $soapclient_user->call("getUser", $ws_parameters, $ws_ns, '');
2988 $user_status_code = $result_user["result"]["result_code"];
2989
2990 if ($user_status_code == "OK") {
2991 //Fill the variables
2992 $ws_entity = $result_user["user"]["entity"];
2993 $ws_authentication['entity'] = $ws_entity;
2994 $ws_thirdparty = $result_user["user"]["fk_thirdparty"];
2995 if (empty($ws_thirdparty)) {
2996 setEventMessages($langs->trans("RemoteUserMissingAssociatedSoc"), null, 'errors');
2997 $error_occurred = true;
2998 } else {
2999 //Create SOAP client and connect it to product/service
3000 $soapclient_product = new nusoap_client($ws_url."/webservices/server_productorservice.php");
3001 $soapclient_product->soap_defencoding = 'UTF-8';
3002 $soapclient_product->decodeUTF8(false);
3003
3004 // Iterate each line and get the reference that uses the supplier of that product/service
3005 $i = 0;
3006 foreach ($object->lines as $line) {
3007 $i += 1;
3008 $ref_supplier = $line->ref_supplier;
3009 $line_id = $i."º) ".$line->product_ref.": ";
3010 if (empty($ref_supplier)) {
3011 continue;
3012 }
3013 $ws_parameters = array('authentication' => $ws_authentication, 'id' => '', 'ref' => $ref_supplier);
3014 $result_product = $soapclient_product->call("getProductOrService", $ws_parameters, $ws_ns, '');
3015 if (!$result_product) {
3016 setEventMessages($line_id.$langs->trans("Error")." SOAP ".$soapclient_product->error_str." - ".$soapclient_product->response, null, 'errors');
3017 $error_occurred = true;
3018 break;
3019 }
3020
3021 // Check the result code
3022 $status_code = $result_product["result"]["result_code"];
3023 if (empty($status_code)) { //No result, check error str
3024 setEventMessages($langs->trans("Error")." SOAP '".$soapclient_product->error_str."'", null, 'errors');
3025 } elseif ($status_code != "OK") { //Something went wrong
3026 if ($status_code == "NOT_FOUND") {
3027 setEventMessages($line_id.$langs->trans("SupplierMissingRef")." '".$ref_supplier."'", null, 'warnings');
3028 } else {
3029 setEventMessages($line_id.$langs->trans("ResponseNonOK")." '".$status_code."' - '".$result_product["result"]["result_label"]."'", null, 'errors');
3030 $error_occurred = true;
3031 break;
3032 }
3033 }
3034
3035
3036 // Ensure that price is equal and warn user if it's not
3037 $supplier_price = price($result_product["product"]["price_net"]); //Price of client tab in supplier dolibarr
3038 $local_price = null; //Price of supplier as stated in product suppliers tab on this dolibarr, NULL if not found
3039
3040 $product_fourn = new ProductFournisseur($db);
3041 $product_fourn_list = $product_fourn->list_product_fournisseur_price($line->fk_product);
3042 if (count($product_fourn_list) > 0) {
3043 foreach ($product_fourn_list as $product_fourn_line) {
3044 //Only accept the line where the supplier is the same at this order and has the same ref
3045 if ($product_fourn_line->fourn_id == $object->socid && $product_fourn_line->fourn_ref == $ref_supplier) {
3046 $local_price = price($product_fourn_line->fourn_price);
3047 }
3048 }
3049 }
3050
3051 if ($local_price != null && $local_price != $supplier_price) {
3052 setEventMessages($line_id.$langs->trans("RemotePriceMismatch")." ".$supplier_price." - ".$local_price, null, 'warnings');
3053 }
3054
3055 // Check if is in sale
3056 if (empty($result_product["product"]["status_tosell"])) {
3057 setEventMessages($line_id.$langs->trans("ProductStatusNotOnSellShort")." '".$ref_supplier."'", null, 'warnings');
3058 }
3059 }
3060 }
3061 } elseif ($user_status_code == "PERMISSION_DENIED") {
3062 setEventMessages($langs->trans("RemoteUserNotPermission"), null, 'errors');
3063 $error_occurred = true;
3064 } elseif ($user_status_code == "BAD_CREDENTIALS") {
3065 setEventMessages($langs->trans("RemoteUserBadCredentials"), null, 'errors');
3066 $error_occurred = true;
3067 } else {
3068 setEventMessages($langs->trans("ResponseNonOK")." '".$user_status_code."'", null, 'errors');
3069 $error_occurred = true;
3070 }
3071
3072 //Form
3073 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
3074 print '<input type="hidden" name="token" value="'.newToken().'">';
3075 print '<input type="hidden" name="action" value="webservice">';
3076 print '<input type="hidden" name="mode" value="send">';
3077 print '<input type="hidden" name="ws_user" value="'.$ws_user.'">';
3078 print '<input type="hidden" name="ws_password" value="'.$ws_password.'">';
3079 print '<input type="hidden" name="ws_entity" value="'.$ws_entity.'">';
3080 print '<input type="hidden" name="ws_thirdparty" value="'.$ws_thirdparty.'">';
3081 if ($error_occurred) {
3082 print "<br>".$langs->trans("ErrorOccurredReviseAndRetry")."<br>";
3083 } else {
3084 print '<input type="submit" class="button" id="ws_submit" name="ws_submit" value="'.$langs->trans("Confirm").'">';
3085 print ' &nbsp; &nbsp; ';
3086 }
3087 print '<input class="button button-cancel" type="submit" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
3088 print '</form>';
3089 }
3090 }
3091
3092 // Presend form
3093 $modelmail = 'order_supplier_send';
3094 $defaulttopic = 'SendOrderRef';
3095 $diroutput = $conf->fournisseur->commande->dir_output;
3096 $autocopy = 'MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO';
3097 $trackid = 'sord'.$object->id;
3098
3099 include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
3100 }
3101}
3102
3103// End of page
3104llxFooter();
3105$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.