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