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