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