dolibarr 25.0.0-alpha
card.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2002-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2020 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2004 Christophe Combelles <ccomb@free.fr>
5 * Copyright (C) 2005 Marc Barilley <marc@ocebo.fr>
6 * Copyright (C) 2005-2013 Regis Houssin <regis.houssin@inodbox.com>
7 * Copyright (C) 2010-2023 Juanjo Menent <jmenent@simnandez.es>
8 * Copyright (C) 2013-2022 Philippe Grand <philippe.grand@atoo-net.com>
9 * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
10 * Copyright (C) 2014-2016 Marcos García <marcosgdf@gmail.com>
11 * Copyright (C) 2016-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
12 * Copyright (C) 2018-2026 Frédéric France <frederic.france@free.fr>
13 * Copyright (C) 2019 Ferran Marcet <fmarcet@2byte.es>
14 * Copyright (C) 2022 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
15 * Copyright (C) 2023 Nick Fragoulis
16 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
17 * Copyright (C) 2026 Vincent de Grandpré <vincent@de-grandpre.quebec>
18 * Copyright (C) 2026 Lionel Vessiller <lvessiller@open-dsi.fr>
19 * Copyright (C) 2026 José MARTINEZ <jose.martinez@pichinov.com>
20 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 3 of the License, or
24 * (at your option) any later version.
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 *
31 * You should have received a copy of the GNU General Public License
32 * along with this program. If not, see <https://www.gnu.org/licenses/>.
33 */
34
41// Load Dolibarr environment
42require '../../main.inc.php';
51require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
52require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
53require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php';
54require_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_invoice/modules_facturefournisseur.php';
55require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
56require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture-rec.class.php';
57require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php';
58require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php';
59require_once DOL_DOCUMENT_ROOT.'/core/lib/fourn.lib.php';
60require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
61require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
62require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
63if (isModEnabled("product")) {
64 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
65 require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
66}
67if (isModEnabled('project')) {
68 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
69 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
70}
71
72if (isModEnabled('variants')) {
73 require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
74}
75if (isModEnabled('accounting')) {
76 require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
77}
78
79$langs->loadLangs(array('bills', 'compta', 'suppliers', 'companies', 'products', 'banks', 'admin'));
80if (isModEnabled('incoterm')) {
81 $langs->load('incoterm');
82}
83
84$id = (GETPOSTINT('facid') ? GETPOSTINT('facid') : GETPOSTINT('id'));
85
86$action = GETPOST('action', 'aZ09');
87$confirm = GETPOST("confirm");
88$ref = GETPOST('ref', 'alpha');
89$cancel = GETPOST('cancel', 'alpha');
90$backtopage = GETPOST('backtopage', 'alpha');
91$backtopageforcancel = '';
92
93$lineid = GETPOSTINT('lineid');
94$projectid = GETPOSTINT('projectid');
95$origin = GETPOST('origin', 'alpha');
96$originid = GETPOSTINT('originid');
97$fac_recid = GETPOSTINT('fac_rec');
98$rank = (GETPOSTINT('rank') > 0) ? GETPOSTINT('rank') : -1;
99
100// PDF
101$hidedetails = (GETPOSTINT('hidedetails') ? GETPOSTINT('hidedetails') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 1 : 0));
102$hidedesc = (GETPOSTINT('hidedesc') ? GETPOSTINT('hidedesc') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 1 : 0));
103$hideref = (GETPOSTINT('hideref') ? GETPOSTINT('hideref') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF') ? 1 : 0));
104
105// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
106$hookmanager->initHooks(array('invoicesuppliercard', 'globalcard'));
107
109$extrafields = new ExtraFields($db);
110
111// fetch optionals attributes and labels
112$extrafields->fetch_name_optionals_label($object->table_element);
113
114// Load object
115if ($id > 0 || !empty($ref)) {
116 $ret = $object->fetch($id, $ref);
117 if ($ret < 0) {
118 dol_print_error($db, $object->error);
119 }
120 $ret = $object->fetch_thirdparty();
121 if ($ret < 0) {
122 dol_print_error($db, $object->error);
123 }
124}
125
126// Security check
127$socid = GETPOSTINT('socid');
128if (!empty($user->socid)) {
129 $socid = $user->socid;
130}
131
132$isdraft = (($object->status == FactureFournisseur::STATUS_DRAFT) ? 1 : 0);
133$result = restrictedArea($user, 'fournisseur', $id, 'facture_fourn', 'facture', 'fk_soc', 'rowid', $isdraft);
134
135// Common permissions
136$usercanread = ($user->hasRight("fournisseur", "facture", "lire") || $user->hasRight("supplier_invoice", "lire"));
137$usercancreate = ($user->hasRight("fournisseur", "facture", "creer") || $user->hasRight("supplier_invoice", "creer"));
138$usercandelete = (($user->hasRight("fournisseur", "facture", "supprimer") || $user->hasRight("supplier_invoice", "supprimer")) || ($usercancreate && $object->is_erasable() == 1));
139$usercancreatecontract = $user->hasRight("contrat", "creer");
140
141// Advanced permissions
142$usercanvalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !empty($usercancreate)) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight("fournisseur", "supplier_invoice_advance", "validate")));
143$usercansend = (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || $user->hasRight("fournisseur", "supplier_invoice_advance", "send"));
144$usercancreatecreditransfer = $user->hasRight('paymentbybanktransfer', 'create');
145
146// Permissions for includes
147$permissionnote = $usercancreate; // Used by the include of actions_setnotes.inc.php
148$permissiondellink = $usercancreate; // Used by the include of actions_dellink.inc.php
149$permissiontoedit = $usercancreate; // Used by the include of actions_lineupdown.inc.php
150$permissiontoadd = $usercancreate; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
151$permissiontodelete = $usercandelete;
152$permissiontoeditextra = $permissiontoadd;
153if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
154 // For action 'update_extras', is there a specific permission set for the attribute to update
155 $permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
156}
157
158$error = 0;
159$classname = null;
160
161
162/*
163 * Actions
164 */
165
166$parameters = array('socid' => $socid);
167$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
168if ($reshook < 0) {
169 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
170}
171
172if (empty($reshook)) {
173 $backurlforlist = dolBuildUrl(DOL_URL_ROOT.'/fourn/facture/list.php');
174
175 if (empty($backtopage) || ($cancel && empty($id))) {
176 if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
177 if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
178 $backtopage = $backurlforlist;
179 } else {
180 $backtopage = dolBuildUrl(DOL_URL_ROOT.'/fourn/facture/card.php', ['id' => ((!empty($id) && $id > 0) ? $id : '__ID__')]);
181 }
182 }
183 }
184
185 if ($cancel) {
186 if (!empty($backtopageforcancel)) {
187 header("Location: ".$backtopageforcancel);
188 exit;
189 } elseif (!empty($backtopage)) {
190 header("Location: ".$backtopage);
191 exit;
192 }
193 $action = '';
194 }
195
196 include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be 'include', not 'include_once'
197
198 include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
199
200 include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; // Must be 'include', not 'include_once'
201
202 // Link invoice to order
203 if (GETPOST('linkedOrder') && empty($cancel) && $id > 0 && $permissiontoadd) {
204 $object->fetch($id);
205 $object->fetch_thirdparty();
206 $result = $object->add_object_linked('order_supplier', GETPOSTINT('linkedOrder'));
207 }
208
209 // Action clone object
210 if ($action == 'confirm_clone' && $confirm == 'yes' && $permissiontoadd) {
211 $objectutil = dol_clone($object, 1); // To avoid to denaturate loaded object when setting some properties for clone. We use native clone to keep this->db valid.
212 '@phan-var-force FactureFournisseur $objectutil'; // Same object type for cloned object
213
214 if (GETPOST('newsupplierref', 'alphanohtml')) {
215 $objectutil->ref_supplier = GETPOST('newsupplierref', 'alphanohtml');
216 }
217 $objectutil->date = dol_mktime(12, 0, 0, GETPOSTINT('newdatemonth'), GETPOSTINT('newdateday'), GETPOSTINT('newdateyear'));
218
219 $result = $objectutil->createFromClone($user, $id);
220 if ($result > 0) {
221 header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result);
222 exit;
223 } else {
224 $langs->load("errors");
225 setEventMessages($objectutil->error, $objectutil->errors, 'errors');
226 $action = '';
227 }
228 } elseif ($action == 'confirm_valid' && $confirm == 'yes' && $usercanvalidate) {
229 $idwarehouse = GETPOST('idwarehouse');
230
231 $object->fetch($id);
232 $object->fetch_thirdparty();
233
234 $qualified_for_stock_change = 0;
235 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
236 $qualified_for_stock_change = $object->hasProductsOrServices(2);
237 } else {
238 $qualified_for_stock_change = $object->hasProductsOrServices(1);
239 }
240
241 // Check parameters
242 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_BILL') && $qualified_for_stock_change) {
243 $langs->load("stocks");
244 if (!$idwarehouse || $idwarehouse == -1) {
245 $error++;
246 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
247 $action = '';
248 }
249 }
250
251 if (!$error) {
252 $db->begin();
253
254 $result = $object->validate($user, '', $idwarehouse);
255 if ($result < 0) {
256 $db->rollback();
257
258 setEventMessages($object->error, $object->errors, 'errors');
259 } else {
260 if (isModEnabled('category')) {
261 $categories = GETPOST('categories', 'array:int');
262 if (method_exists($object, 'setCategories')) {
263 $object->setCategories($categories);
264 }
265 }
266
267 $db->commit();
268
269 // Define output language
270 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
271 $outputlangs = $langs;
272 $newlang = '';
273 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
274 $newlang = GETPOST('lang_id', 'aZ09');
275 }
276 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
277 $newlang = $object->thirdparty->default_lang;
278 }
279 if (!empty($newlang)) {
280 $outputlangs = new Translate("", $conf);
281 $outputlangs->setDefaultLang($newlang);
282 }
283 $model = $object->model_pdf;
284 $ret = $object->fetch($id); // Reload to get new records
285
286 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
287 if ($result < 0) {
288 setEventMessages($object->error, $object->errors, 'errors');
289 }
290 }
291 }
292 }
293 } elseif ($action == 'confirm_delete' && $confirm == 'yes' && $permissiontodelete) {
294 $object->fetch($id);
295 $object->fetch_thirdparty();
296
297 $isErasable = $object->is_erasable();
298
299 if ($usercandelete && $isErasable > 0) {
300 $revertstock = GETPOST('revertstock');
301
302 if ($revertstock) {
303 $idwarehouse = GETPOSTINT('idwarehouse');
304
305 $qualified_for_stock_change = 0;
306 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
307 $qualified_for_stock_change = $object->hasProductsOrServices(2);
308 } else {
309 $qualified_for_stock_change = $object->hasProductsOrServices(1);
310 }
311
312 // Check parameters
313 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_BILL') && $qualified_for_stock_change) {
314 $langs->load("stocks");
315 if (!$idwarehouse || $idwarehouse == -1) {
316 $error++;
317 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
318 $action = 'delete';
319 } else {
320 $result = $object->setDraft($user, $idwarehouse);
321 if ($result < 0) {
322 $error++;
323 }
324 }
325 }
326 }
327
328 if (!$error) {
329 $result = $object->delete($user);
330 if ($result > 0) {
331 header('Location: list.php?restore_lastsearch_values=1');
332 exit;
333 } else {
334 setEventMessages($object->error, $object->errors, 'errors');
335 }
336 }
337 }
338 } elseif ($action == 'confirm_deleteline' && $confirm == 'yes' && $usercancreate) {
339 // Remove a product line
340 $result = $object->deleteLine($lineid);
341 if ($result > 0) {
342 // reorder lines
343 $object->line_order(true);
344 // Define output language
345 /*$outputlangs = $langs;
346 $newlang = '';
347 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id','aZ09'))
348 $newlang = GETPOST('lang_id','aZ09');
349 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang))
350 $newlang = $object->thirdparty->default_lang;
351 if (!empty($newlang)) {
352 $outputlangs = new Translate("", $conf);
353 $outputlangs->setDefaultLang($newlang);
354 }
355 if (!getDolGlobalStringempty('MAIN_DISABLE_PDF_AUTOUPDATE')) {
356 $ret = $object->fetch($object->id); // Reload to get new records
357 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
358 }*/
359
360 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
361 exit;
362 } else {
363 setEventMessages($object->error, $object->errors, 'errors');
364 /* Fix bug 1485 : Reset action to avoid asking again confirmation on failure */
365 $action = '';
366 }
367 } elseif ($action == 'confirm_delete_subtotalline' && $confirm == 'yes' && $usercancreate) {
368 // Remove a subtotal / title / text line (subtotals module)
369 $object->fetch($id);
370 $object->fetch_thirdparty();
371
372 $result = $object->deleteSubtotalLine($langs, $lineid, (bool) GETPOST('deletecorrespondingsubtotalline'));
373 if ($result > 0) {
374 $object->line_order(true);
375 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
376 exit;
377 } else {
378 setEventMessages($object->error, $object->errors, 'errors');
379 $action = '';
380 }
381 } elseif ($action == 'unlinkdiscount' && $usercancreate) {
382 // Delete link of credit note to invoice
383 $discount = new DiscountAbsolute($db);
384 $result = $discount->fetch(GETPOSTINT("discountid"));
385 $discount->unlink_invoice();
386 $object->fetch($id);
387 if ($object->paye == 1 && (float) $object->getRemainToPay() > 0) {
388 $object->setUnpaid($user);
389 }
390 } elseif ($action == 'confirm_paid' && $confirm == 'yes' && $usercancreate) {
391 $object->fetch($id);
392 $result = $object->setPaid($user);
393 if ($result < 0) {
394 setEventMessages($object->error, $object->errors, 'errors');
395 }
396 } elseif ($action == 'confirm_paid_partially' && $confirm == 'yes' && $usercancreate) {
397 // Classif "paid partially"
398 $object->fetch($id);
399 $close_code = GETPOST("close_code", 'restricthtml');
400 $close_note = GETPOST("close_note", 'restricthtml');
401 if ($close_code) {
402 $result = $object->setPaid($user, $close_code, $close_note);
403 if ($result < 0) {
404 setEventMessages($object->error, $object->errors, 'errors');
405 }
406 } else {
407 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Reason")), null, 'errors');
408 }
409 } elseif ($action == 'confirm_canceled' && $confirm == 'yes' && $usercancreate) {
410 // Classify "abandoned"
411 $object->fetch($id);
412 $close_code = GETPOST("close_code", 'restricthtml');
413 $close_note = GETPOST("close_note", 'restricthtml');
414 if ($close_code) {
415 $result = $object->setCanceled($user, $close_code, $close_note);
416 if ($result < 0) {
417 setEventMessages($object->error, $object->errors, 'errors');
418 }
419 } else {
420 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Reason")), null, 'errors');
421 }
422 }
423
424 // Set supplier ref
425 if ($action == 'setref_supplier' && $usercancreate) {
426 $object->ref_supplier = GETPOST('ref_supplier', 'alpha');
427
428 if ($object->update($user) < 0) {
429 setEventMessages($object->error, $object->errors, 'errors');
430 } else {
431 // Define output language
432 $outputlangs = $langs;
433 $newlang = '';
434 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
435 $newlang = GETPOST('lang_id', 'aZ09');
436 }
437 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
438 $newlang = $object->thirdparty->default_lang;
439 }
440 if (!empty($newlang)) {
441 $outputlangs = new Translate("", $conf);
442 $outputlangs->setDefaultLang($newlang);
443 }
444 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
445 $ret = $object->fetch($object->id); // Reload to get new records
446 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
447 }
448 }
449 }
450
451 // payments conditions
452 if ($action == 'setconditions' && $usercancreate) {
453 $object->fetch($id);
454 $object->cond_reglement_code = 0; // To clean property
455 $object->cond_reglement_id = 0; // To clean property
456
457 $error = 0;
458
459 $db->begin();
460
461 if (!$error) {
462 $result = $object->setPaymentTerms(GETPOSTINT('cond_reglement_id'));
463 if ($result < 0) {
464 $error++;
465 setEventMessages($object->error, $object->errors, 'errors');
466 }
467 }
468
469 if (!$error) {
470 $new_date_echeance = $object->calculate_date_lim_reglement();
471 if ($new_date_echeance) {
472 $object->date_echeance = $new_date_echeance;
473 }
474 if ($object->date_echeance < $object->date) {
475 $object->date_echeance = $object->date;
476 }
477 $result = $object->update($user);
478 if ($result < 0) {
479 $error++;
480 setEventMessages($object->error, $object->errors, 'errors');
481 }
482 }
483
484 if ($error) {
485 $db->rollback();
486 } else {
487 $db->commit();
488 }
489 } elseif ($action == 'set_incoterms' && isModEnabled('incoterm') && $usercancreate) {
490 // Set incoterm
491 $result = $object->setIncoterms(GETPOSTINT('incoterm_id'), GETPOST('location_incoterms'));
492 } elseif ($action == 'settags' && isModEnabled('category') && $usercancreate) {
493 // Set tags
494 $result = $object->setCategories(GETPOST('categories', 'array'));
495 } elseif ($action == 'setmode' && $usercancreate) {
496 // payment mode
497 $result = $object->setPaymentMethods(GETPOSTINT('mode_reglement_id'));
498 } elseif ($action == 'setmulticurrencycode' && $usercancreate) {
499 // Multicurrency Code
500 $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha'));
501 } elseif ($action == 'setmulticurrencyrate' && $usercancreate) {
502 // Multicurrency rate
503 $result = $object->setMulticurrencyRate((float) price2num(GETPOST('multicurrency_tx', 'alpha')), GETPOSTINT('calculation_mode'));
504 } elseif ($action == 'setbankaccount' && $usercancreate) {
505 // bank account
506 $result = $object->setBankAccount(GETPOSTINT('fk_account'));
507 } elseif ($action == 'setvatreversecharge' && $usercancreate) {
508 // vat reverse charge
509 $vatreversecharge = GETPOST('vat_reverse_charge') == 'on' ? 1 : 0;
510 $result = $object->setVATReverseCharge($vatreversecharge);
511 }
512
513 if ($action == 'settransportmode' && $usercancreate) {
514 // transport mode
515 $result = $object->setTransportMode(GETPOSTINT('transport_mode_id'));
516 } elseif ($action == 'setlabel' && $usercancreate) {
517 // Set label
518 $object->fetch($id);
519 $object->label = GETPOST('label');
520 $result = $object->update($user);
521 if ($result < 0) {
522 setEventMessages($object->error, $object->errors, 'errors');
523 }
524 } elseif ($action == 'setdatef' && $usercancreate) {
525 $newdate = dol_mktime(0, 0, 0, GETPOSTINT('datefmonth'), GETPOSTINT('datefday'), GETPOSTINT('datefyear'), 'tzserver');
526 if ($newdate > (dol_now('tzuserrel') + getDolGlobalInt('INVOICE_MAX_FUTURE_DELAY'))) {
527 if (!getDolGlobalString('INVOICE_MAX_FUTURE_DELAY')) {
528 setEventMessages($langs->trans("WarningInvoiceDateInFuture"), null, 'warnings');
529 } else {
530 setEventMessages($langs->trans("WarningInvoiceDateTooFarInFuture"), null, 'warnings');
531 }
532 }
533
534 $object->fetch($id);
535
536 $object->date = $newdate;
537 $date_echence_calc = $object->calculate_date_lim_reglement();
538 if (!empty($object->date_echeance)) {
539 $object->date_echeance = $date_echence_calc;
540 }
541 if ($object->date_echeance && $object->date_echeance < $object->date) {
542 $object->date_echeance = $object->date;
543 }
544
545 $result = $object->update($user);
546 if ($result < 0) {
547 setEventMessages($object->error, $object->errors, 'errors');
548 }
549 } elseif ($action == 'setdate_lim_reglement' && $usercancreate) {
550 $object->fetch($id);
551 $object->date_echeance = dol_mktime(12, 0, 0, GETPOSTINT('date_lim_reglementmonth'), GETPOSTINT('date_lim_reglementday'), GETPOSTINT('date_lim_reglementyear'));
552 if (!empty($object->date_echeance) && $object->date_echeance < $object->date) {
553 $object->date_echeance = $object->date;
554 setEventMessages($langs->trans("DatePaymentTermCantBeLowerThanObjectDate"), null, 'warnings');
555 }
556 $result = $object->update($user);
557 if ($result < 0) {
558 setEventMessages($object->error, $object->errors, 'errors');
559 }
560 } elseif ($action == "setabsolutediscount" && $usercancreate) {
561 $db->begin();
562 // We use the credit to reduce amount of invoice
563 if (GETPOSTINT("remise_id")) {
564 $ret = $object->fetch($id);
565 if ($ret > 0) {
566 $result = $object->insert_discount(GETPOSTINT("remise_id"));
567 if ($result < 0) {
568 setEventMessages($object->error, $object->errors, 'errors');
569 }
570 } else {
571 dol_print_error($db, $object->error);
572 }
573 }
574 // We use the credit to reduce remain to pay
575 if (GETPOSTINT("remise_id_for_payment")) {
576 require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php';
577 $discount = new DiscountAbsolute($db);
578 $discount->fetch(GETPOSTINT("remise_id_for_payment"));
579
580 //var_dump($object->getRemainToPay(0));
581 //var_dump($discount->amount_ttc);exit;
582 $remaintopay = $object->getRemainToPay(0);
583 if (price2num($discount->amount_ttc) > price2num($remaintopay)) {
584 // TODO Split the discount in 2 automatically
585 $error++;
586 setEventMessages($langs->trans("ErrorDiscountLargerThanRemainToPaySplitItBefore"), null, 'errors');
587 }
588
589 if (!$error) {
590 $result = $discount->link_to_invoice(0, $id);
591 if ($result < 0) {
592 $error++;
593 setEventMessages($discount->error, $discount->errors, 'errors');
594 }
595 }
596 if (!$error) {
597 $newremaintopay = $object->getRemainToPay(0);
598 if ($newremaintopay == 0) {
599 $object->setPaid($user);
600 }
601 }
602 }
603 if (!$error) {
604 $db->commit();
605 } else {
606 $db->rollback();
607 }
608 if (empty($error) && !getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
609 $outputlangs = $langs;
610 $newlang = '';
611 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
612 $newlang = GETPOST('lang_id', 'aZ09');
613 }
614 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
615 $newlang = $object->thirdparty->default_lang;
616 }
617 if (!empty($newlang)) {
618 $outputlangs = new Translate("", $conf);
619 $outputlangs->setDefaultLang($newlang);
620 }
621 $ret = $object->fetch($id); // Reload to get new records
622
623 $result = $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
624 if ($result < 0) {
625 setEventMessages($object->error, $object->errors, 'errors');
626 }
627 }
628 } elseif ($action == 'confirm_addtitleline' && $usercancreate) {
629 // Handling adding a new title line for subtotals module
630
631 $langs->load('subtotals');
632
633 $desc = GETPOST('subtotallinedesc', 'alphanohtml');
634 $depth = GETPOSTINT('subtotallinelevel') ?? 1;
635
636 $subtotal_options = array();
637
638 foreach (FactureFournisseur::$TITLE_OPTIONS as $option) {
639 $value = GETPOST($option, 'alphanohtml');
640 if ($value) {
641 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
642 }
643 }
644
645 // Insert line
646 $result = $object->addSubtotalLine($langs, $desc, (int) $depth, $subtotal_options);
647
648 if ($result >= 0) {
649 if ($result == 0) {
650 setEventMessages($object->error, $object->errors, 'warnings');
651 }
652 $ret = $object->fetch($object->id); // Reload to get new records
653 $object->fetch_thirdparty();
654
655 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
656 // Define output language
657 $outputlangs = $langs;
658 $newlang = GETPOST('lang_id', 'alpha');
659 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
660 $newlang = $object->thirdparty->default_lang;
661 }
662 if (!empty($newlang)) {
663 $outputlangs = new Translate("", $conf);
664 $outputlangs->setDefaultLang($newlang);
665 }
666
667 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
668 }
669 } else {
670 setEventMessages($object->error, $object->errors, 'errors');
671 }
672 header('Location: '.dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $id]));
673 exit();
674 } elseif ($action == 'confirm_addsubtotalline' && $usercancreate) {
675 // Handling adding a new subtotal line for subtotals module
676
677 $langs->load('subtotals');
678
679 $choosen_line = GETPOST('subtotaltitleline', 'alphanohtml');
680 foreach ($object->lines as $line) {
681 if ($line->desc == $choosen_line && $line->special_code == SUBTOTALS_SPECIAL_CODE) {
682 $desc = $line->desc;
683 $depth = -$line->qty;
684 }
685 }
686
687 $subtotal_options = array();
688
689 foreach (FactureFournisseur::$SUBTOTAL_OPTIONS as $option) {
690 $value = GETPOST($option, 'alphanohtml');
691 if ($value) {
692 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
693 }
694 }
695
696 // Insert line
697 if (isset($desc) && isset($depth)) {
698 $result = $object->addSubtotalLine($langs, $desc, (int) $depth, $subtotal_options);
699 } else {
700 $result = -1;
701 $object->errors[] = $langs->trans("CorrespondingTitleNotFound");
702 }
703
704 if ($result >= 0) {
705 $ret = $object->fetch($object->id); // Reload to get new records
706 $object->fetch_thirdparty();
707
708 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
709 // Define output language
710 $outputlangs = $langs;
711 $newlang = GETPOST('lang_id', 'alpha');
712 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
713 $newlang = $object->thirdparty->default_lang;
714 }
715 if (!empty($newlang)) {
716 $outputlangs = new Translate("", $conf);
717 $outputlangs->setDefaultLang($newlang);
718 }
719
720 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
721 }
722 } else {
723 setEventMessages($object->error, $object->errors, 'errors');
724 }
725 header('Location: '.dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $id]));
726 exit();
727 } elseif ($action == 'confirm_addtextline' && $usercancreate) {
728 // Handling adding a new text line for subtotals module
729
730 $langs->load('subtotals');
731
732 $desc = GETPOST('subtotaltextcontent', 'restricthtml');
733
734 // Insert line
735 $result = $object->addSubtotalLine($langs, $desc, 0, array());
736
737 if ($result >= 0) {
738 if ($result == 0) {
739 setEventMessages($object->error, $object->errors, 'warnings');
740 }
741 $ret = $object->fetch($object->id); // Reload to get new records
742 $object->fetch_thirdparty();
743
744 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
745 // Define output language
746 $outputlangs = $langs;
747 $newlang = GETPOST('lang_id', 'alpha');
748 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
749 $newlang = $object->thirdparty->default_lang;
750 }
751 if (!empty($newlang)) {
752 $outputlangs = new Translate("", $conf);
753 $outputlangs->setDefaultLang($newlang);
754 }
755
756 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
757 }
758 } else {
759 setEventMessages($object->error, $object->errors, 'errors');
760 }
761 header('Location: '.dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $id]));
762 exit();
763 } elseif ($action == 'confirm_converttoreduc' && $confirm == 'yes' && $usercancreate) {
764 // Convertir en reduc
765 $object->fetch($id);
766 $object->fetch_thirdparty();
767 //$object->fetch_lines(); // Already done into fetch
768
769 // Check if there is already a discount (protection to avoid duplicate creation when resubmit post)
770 $discountcheck = new DiscountAbsolute($db);
771 $result = $discountcheck->fetch(0, 0, $object->id);
772
773 $canconvert = 0;
774 if ($object->type == FactureFournisseur::TYPE_DEPOSIT && empty($discountcheck->id)) {
775 $canconvert = 1; // we can convert deposit into discount if deposit is paid (completely, partially or not at all) and not already converted (see real condition into condition used to show button converttoreduc)
776 }
777 if (($object->type == FactureFournisseur::TYPE_CREDIT_NOTE || $object->type == FactureFournisseur::TYPE_STANDARD) && $object->paid == 0 && empty($discountcheck->id)) {
778 $canconvert = 1; // we can convert credit note into discount if credit note is not refunded completely and not already converted and amount of payment is 0 (see also the real condition used as the condition to show button converttoreduc)
779 }
780 if ($canconvert) {
781 $db->begin();
782
783 $amount_ht = $amount_tva = $amount_ttc = array();
784 $multicurrency_amount_ht = $multicurrency_amount_tva = $multicurrency_amount_ttc = array();
785
786 // Loop on each vat rate
787 $i = 0;
788 foreach ($object->lines as $line) {
789 if ($line->product_type < 9 && $line->total_ht != 0) { // Remove lines with product_type greater than or equal to 9 and no need to create discount if amount is null
790 $keyforvatrate = $line->tva_tx.($line->vat_src_code ? ' ('.$line->vat_src_code.')' : '');
791
792 $amount_ht[$keyforvatrate] += $line->total_ht;
793 $amount_tva[$keyforvatrate] += $line->total_tva;
794 $amount_ttc[$keyforvatrate] += $line->total_ttc;
795 $multicurrency_amount_ht[$keyforvatrate] += $line->multicurrency_total_ht;
796 $multicurrency_amount_tva[$keyforvatrate] += $line->multicurrency_total_tva;
797 $multicurrency_amount_ttc[$keyforvatrate] += $line->multicurrency_total_ttc;
798 $i++;
799 }
800 }
801 '@phan-var-force array<string,float> $amount_ht
802 @phan-var-force array<string,float> $amount_tva
803 @phan-var-force array<string,float> $amount_ttc
804 @phan-var-force array<string,float> $multicurrency_amount_ht
805 @phan-var-force array<string,float> $multicurrency_amount_tva
806 @phan-var-force array<string,float> $multicurrency_amount_ttc';
807
808 // If some payments were already done, we change the amount to pay using same prorate
809 if (getDolGlobalString('SUPPLIER_INVOICE_ALLOW_REUSE_OF_CREDIT_WHEN_PARTIALLY_REFUNDED') && $object->type == FactureFournisseur::TYPE_CREDIT_NOTE) {
810 $alreadypaid = $object->getSommePaiement(); // This can be not 0 if we allow to create credit to reuse from credit notes partially refunded.
811 if ($alreadypaid && abs($alreadypaid) < abs($object->total_ttc)) {
812 $ratio = abs(($object->total_ttc - $alreadypaid) / $object->total_ttc);
813 foreach ($amount_ht as $vatrate => $val) {
814 $amount_ht[$vatrate] = price2num($amount_ht[$vatrate] * $ratio, 'MU');
815 $amount_tva[$vatrate] = price2num($amount_tva[$vatrate] * $ratio, 'MU');
816 $amount_ttc[$vatrate] = price2num($amount_ttc[$vatrate] * $ratio, 'MU');
817 $multicurrency_amount_ht[$vatrate] = price2num($multicurrency_amount_ht[$vatrate] * $ratio, 'MU');
818 $multicurrency_amount_tva[$vatrate] = price2num($multicurrency_amount_tva[$vatrate] * $ratio, 'MU');
819 $multicurrency_amount_ttc[$vatrate] = price2num($multicurrency_amount_ttc[$vatrate] * $ratio, 'MU');
820 }
821 }
822 }
823 //var_dump($amount_ht);var_dump($amount_tva);var_dump($amount_ttc);exit;
824
825 // Insert one discount by VAT rate category
826 $discount = new DiscountAbsolute($db);
828 $discount->description = '(CREDIT_NOTE)';
829 } elseif ($object->type == FactureFournisseur::TYPE_DEPOSIT) {
830 $discount->description = '(DEPOSIT)';
832 $discount->description = '(EXCESS PAID)';
833 } else {
834 setEventMessages($langs->trans('CantConvertToReducAnInvoiceOfThisType'), null, 'errors');
835 }
836 $discount->discount_type = 1; // Supplier discount
837 $discount->fk_soc = $object->socid;
838 $discount->socid = $object->socid;
839 $discount->fk_invoice_supplier_source = $object->id;
840
841 $error = 0;
842
844 // If we're on a standard invoice, we have to get excess paid to create a discount in TTC without VAT
845
846 // Total payments
847 $sql = 'SELECT SUM(pf.amount) as total_paiements';
848 $sql .= ' FROM '.MAIN_DB_PREFIX.'paiementfourn_facturefourn as pf, '.MAIN_DB_PREFIX.'paiementfourn as p';
849 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as c ON p.fk_paiement = c.id AND c.entity IN ('.getEntity('c_paiement').')';
850 $sql .= ' WHERE pf.fk_facturefourn = '.((int) $object->id);
851 $sql .= ' AND pf.fk_paiementfourn = p.rowid';
852 $sql .= ' AND p.entity IN ('.getEntity('invoice').')';
853
854 $resql = $db->query($sql);
855 if (!$resql) {
857 }
858
859 $res = $db->fetch_object($resql);
860 $total_paiements = $res->total_paiements;
861
862 // Total credit note and deposit
863 $total_creditnote_and_deposit = 0;
864 $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
865 $sql .= " re.description, re.fk_invoice_supplier_source";
866 $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re";
867 $sql .= " WHERE fk_invoice_supplier = ".((int) $object->id);
868 $resql = $db->query($sql);
869 if (!empty($resql)) {
870 while ($obj = $db->fetch_object($resql)) {
871 $total_creditnote_and_deposit += $obj->amount_ttc;
872 }
873 } else {
875 }
876
877 $discount->amount_ht = $discount->amount_ttc = $total_paiements + $total_creditnote_and_deposit - $object->total_ttc;
878 $discount->amount_tva = 0;
879 $discount->tva_tx = 0;
880 $discount->vat_src_code = '';
881
882 // multi-currency
883 $discount->multicurrency_code = $object->multicurrency_code;
884 $discount->multicurrency_tx = $object->multicurrency_tx;
885 $discount->multicurrency_total_ht = $discount->multicurrency_total_ttc = (float) price2num((float) $discount->amount_ttc * (float) $object->multicurrency_tx, 'MT');
886 $discount->multicurrency_total_tva = 0;
887 // keep compatibility
888 $discount->multicurrency_amount_ht = $discount->multicurrency_amount_ttc = $discount->multicurrency_total_ttc;
889 $discount->multicurrency_amount_tva = 0;
890
891 $result = $discount->create($user);
892 if ($result < 0) {
893 $error++;
894 }
895 }
897 foreach ($amount_ht as $tva_tx => $xxx) {
898 $discount->amount_ht = abs((float) $amount_ht[$tva_tx]);
899 $discount->amount_tva = abs((float) $amount_tva[$tva_tx]);
900 $discount->amount_ttc = abs((float) $amount_ttc[$tva_tx]);
901 // multi-currency
902 $discount->multicurrency_code = $object->multicurrency_code;
903 $discount->multicurrency_tx = $object->multicurrency_tx;
904 $discount->multicurrency_total_ht = abs((float) $multicurrency_amount_ht[$tva_tx]);
905 $discount->multicurrency_total_tva = abs((float) $multicurrency_amount_tva[$tva_tx]);
906 $discount->multicurrency_total_ttc = abs((float) $multicurrency_amount_ttc[$tva_tx]);
907 // keep compatibility
908 $discount->multicurrency_amount_ht = abs((float) $discount->multicurrency_total_ht);
909 $discount->multicurrency_amount_tva = abs((float) $discount->multicurrency_total_tva);
910 $discount->multicurrency_amount_ttc = abs((float) $discount->multicurrency_total_ttc);
911
912 // Clean vat code
913 $reg = array();
914 $vat_src_code = '';
915 if (preg_match('/\‍((.*)\‍)/', $tva_tx, $reg)) {
916 $vat_src_code = $reg[1];
917 $tva_tx = preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx); // Remove code into vatrate.
918 }
919
920 $discount->tva_tx = abs((float) $tva_tx);
921 $discount->vat_src_code = $vat_src_code;
922
923 $result = $discount->create($user);
924 if ($result < 0) {
925 $error++;
926 break;
927 }
928 }
929 }
930
931 if (empty($error)) {
933 // Set invoice as paid
934 $result = $object->setPaid($user);
935 if ($result >= 0) {
936 $db->commit();
937 } else {
938 setEventMessages($object->error, $object->errors, 'errors');
939 $db->rollback();
940 }
941 } else {
942 $db->commit();
943 }
944 } else {
945 setEventMessages($discount->error, $discount->errors, 'errors');
946 $db->rollback();
947 }
948 }
949 } elseif ($action == 'confirm_delete_paiement' && $confirm == 'yes' && $usercancreate) {
950 // Delete payment
951 $object->fetch($id);
952 if ($object->status == FactureFournisseur::STATUS_VALIDATED && $object->paid == 0) {
953 $paiementfourn = new PaiementFourn($db);
954 $result = $paiementfourn->fetch(GETPOSTINT('paiement_id'));
955 if ($result > 0) {
956 $result = $paiementfourn->delete($user);
957 if ($result > 0) {
958 header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
959 exit;
960 }
961 }
962 if ($result < 0) {
963 setEventMessages($paiementfourn->error, $paiementfourn->errors, 'errors');
964 }
965 }
966 } elseif ($action == 'add' && $usercancreate) {
967 // Insert new invoice in database
968 if ($socid > 0) {
969 $object->socid = GETPOSTINT('socid');
970 }
971 $selectedLines = GETPOST('toselect', 'array:int');
972
973 $db->begin();
974
975 $error = 0;
976 $tmpproject = 0; // Ensure a value
977
978 // Fill array 'array_options' with data from add form
979 $ret = $extrafields->setOptionalsFromPost(null, $object);
980 if ($ret < 0) {
981 $error++;
982 }
983
984 $dateinvoice = dol_mktime(0, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'), 'tzserver'); // If we enter the 02 january, we need to save the 02 january for server
985 $datedue = dol_mktime(0, 0, 0, GETPOSTINT('echmonth'), GETPOSTINT('echday'), GETPOSTINT('echyear'), 'tzserver');
986 //var_dump($dateinvoice.' '.dol_print_date($dateinvoice, 'dayhour'));
987 //var_dump(dol_now('tzuserrel').' '.dol_get_last_hour(dol_now('tzuserrel')).' '.dol_print_date(dol_now('tzuserrel'),'dayhour').' '.dol_print_date(dol_get_last_hour(dol_now('tzuserrel')), 'dayhour'));
988 //var_dump($db->idate($dateinvoice));
989 //exit;
990
991 // Replacement invoice
992 if (GETPOST('type') === '') {
993 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
994 $error++;
995 }
996
998 if (empty($dateinvoice)) {
999 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('DateInvoice')), null, 'errors');
1000 $action = 'create';
1001 //$_GET['socid'] = $_POST['socid'];
1002 $error++;
1003 } elseif ($dateinvoice > (dol_get_last_hour(dol_now('tzuserrel')) + getDolGlobalInt('INVOICE_MAX_FUTURE_DELAY'))) {
1004 $error++;
1005 setEventMessages($langs->trans("ErrorDateIsInFuture"), null, 'errors');
1006 $action = 'create';
1007 }
1008
1009 if (!(GETPOSTINT('fac_replacement') > 0)) {
1010 $error++;
1011 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ReplaceInvoice")), null, 'errors');
1012 }
1013
1014 if (!$error) {
1015 // This is a replacement invoice
1016 $result = $object->fetch(GETPOSTINT('fac_replacement'));
1017 $object->fetch_thirdparty();
1018
1019 $object->ref = GETPOST('ref', 'alphanohtml');
1020 $object->ref_supplier = GETPOST('ref_supplier', 'alpha');
1021 $object->socid = GETPOSTINT('socid');
1022 $object->label = GETPOST('label', 'alphanohtml');
1023 $object->libelle = $object->label; // deprecated
1024 $object->date = $dateinvoice;
1025 $object->date_echeance = $datedue;
1026 $object->note_public = GETPOST('note_public', 'restricthtml');
1027 $object->note_private = GETPOST('note_private', 'restricthtml');
1028 $object->cond_reglement_id = GETPOSTINT('cond_reglement_id');
1029 $object->mode_reglement_id = GETPOSTINT('mode_reglement_id');
1030 $object->fk_account = GETPOSTINT('fk_account');
1031 $object->vat_reverse_charge = GETPOST('vat_reverse_charge') == 'on' ? 1 : 0;
1032 $object->fk_project = ($tmpproject > 0) ? $tmpproject : null;
1033 $object->fk_incoterms = GETPOSTINT('incoterm_id');
1034 $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
1035 $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
1036 $object->multicurrency_tx = GETPOSTFLOAT('originmulticurrency_tx');
1037 $object->transport_mode_id = GETPOSTINT('transport_mode_id');
1038
1039 // Proprietes particulieres a facture de replacement
1040 $object->fk_facture_source = GETPOSTINT('fac_replacement');
1042
1043 $id = $object->createFromCurrent($user);
1044 if ($id <= 0) {
1045 $error++;
1046 setEventMessages($object->error, $object->errors, 'errors');
1047 }
1048 }
1049 }
1050
1051 // Credit note invoice
1053 $sourceinvoice = GETPOSTINT('fac_avoir');
1054 if (!($sourceinvoice > 0) && !getDolGlobalString('INVOICE_CREDIT_NOTE_STANDALONE')) {
1055 $error++;
1056 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CorrectInvoice")), null, 'errors');
1057 }
1058 if (GETPOSTINT('socid') < 1) {
1059 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Supplier')), null, 'errors');
1060 $action = 'create';
1061 $error++;
1062 }
1063
1064 if (empty($dateinvoice)) {
1065 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('DateInvoice')), null, 'errors');
1066 $action = 'create';
1067 //$_GET['socid'] = $_POST['socid'];
1068 $error++;
1069 } elseif ($dateinvoice > (dol_get_last_hour(dol_now('tzuserrel')) + getDolGlobalInt('INVOICE_MAX_FUTURE_DELAY'))) {
1070 $error++;
1071 setEventMessages($langs->trans("ErrorDateIsInFuture"), null, 'errors');
1072 $action = 'create';
1073 }
1074
1075 if (!GETPOST('ref_supplier')) {
1076 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('RefSupplierBill')), null, 'errors');
1077 $action = 'create';
1078 //$_GET['socid'] = $_POST['socid'];
1079 $error++;
1080 }
1081
1082 if (getDolGlobalInt('INVOICE_SUBTYPE_ENABLED') && empty(GETPOST("subtype"))) {
1083 $error++;
1084 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("InvoiceSubtype")), null, 'errors');
1085 $action = 'create';
1086 }
1087
1088 if (!$error) {
1089 $tmpproject = GETPOSTINT('projectid');
1090
1091 // Create Supplier Invoice
1092 $object->ref = GETPOST('ref', 'alphanohtml');
1093 $object->ref_supplier = GETPOST('ref_supplier', 'alphanohtml');
1094 $object->subtype = GETPOSTINT('subtype');
1095 $object->socid = GETPOSTINT('socid');
1096 $object->label = GETPOST('label', 'alphanohtml');
1097 $object->libelle = $object->label; // Deprecated
1098 $object->date = $dateinvoice;
1099 $object->date_echeance = $datedue;
1100 $object->note_public = GETPOST('note_public', 'restricthtml');
1101 $object->note_private = GETPOST('note_private', 'restricthtml');
1102 $object->cond_reglement_id = GETPOSTINT('cond_reglement_id');
1103 $object->mode_reglement_id = GETPOSTINT('mode_reglement_id');
1104 $object->fk_account = GETPOSTINT('fk_account');
1105 $object->vat_reverse_charge = GETPOST('vat_reverse_charge') == 'on' ? 1 : 0;
1106 $object->fk_project = ($tmpproject > 0) ? $tmpproject : null;
1107 $object->fk_incoterms = GETPOSTINT('incoterm_id');
1108 $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
1109 $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
1110 $object->multicurrency_tx = GETPOSTFLOAT('originmulticurrency_tx');
1111 $object->transport_mode_id = GETPOSTINT('transport_mode_id');
1112
1113 // Proprietes particulieres a facture avoir
1114 $object->fk_facture_source = $sourceinvoice > 0 ? $sourceinvoice : '';
1116
1117 $id = $object->create($user);
1118
1119 if ($id <= 0) {
1120 $error++;
1121 }
1122
1123 if (GETPOSTINT('invoiceAvoirWithLines') == 1 && $id > 0) {
1124 $facture_source = new FactureFournisseur($db); // fetch origin object
1125 if ($facture_source->fetch($object->fk_facture_source) > 0) {
1126 $fk_parent_line = 0;
1127
1128 foreach ($facture_source->lines as $line) {
1129 // Extrafields
1130 if (method_exists($line, 'fetch_optionals')) {
1131 $line->fetch_optionals();
1132 }
1133
1134 // Reset fk_parent_line for no child products and special product
1135 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
1136 $fk_parent_line = 0;
1137 }
1138
1139 $line->fk_facture_fourn = $object->id;
1140 $line->fk_parent_line = $fk_parent_line;
1141
1142 $line->subprice = -$line->subprice; // invert price for object
1143 $line->pa_ht = -((float) $line->pa_ht);
1144 $line->total_ht = -$line->total_ht;
1145 $line->total_tva = -$line->total_tva;
1146 $line->total_ttc = -$line->total_ttc;
1147 $line->total_localtax1 = -$line->total_localtax1;
1148 $line->total_localtax2 = -$line->total_localtax2;
1149 $line->multicurrency_total_ht = -$line->multicurrency_total_ht;
1150 $line->multicurrency_total_tva = -$line->multicurrency_total_tva;
1151 $line->multicurrency_total_ttc = -$line->multicurrency_total_ttc;
1152
1153 $result = $line->insert();
1154
1155 $object->lines[] = $line; // insert new line in current object
1156
1157 // Defined the new fk_parent_line
1158 if ($result > 0 && $line->product_type == 9) {
1159 $fk_parent_line = $result;
1160 }
1161 }
1162
1163 $object->update_price(1);
1164 }
1165 }
1166
1167 if (GETPOSTINT('invoiceAvoirWithPaymentRestAmount') == 1 && $id > 0) {
1168 $facture_source = new FactureFournisseur($db); // fetch origin object if not previously defined
1169 if ($facture_source->fetch($object->fk_facture_source) > 0) {
1170 $totalpaid = $facture_source->getSommePaiement();
1171 $totalcreditnotes = $facture_source->getSumCreditNotesUsed();
1172 $totaldeposits = $facture_source->getSumDepositsUsed();
1173 $remain_to_pay = abs($facture_source->total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits);
1174 $desc = $langs->trans('invoiceAvoirLineWithPaymentRestAmount');
1175 // Pass the amount already signed: addline() forces -abs() on credit notes with the default setup, so this
1176 // changes nothing there, but it keeps the line negative when that forcing is relaxed (see addline()).
1177 $retAddLine = $object->addline($desc, -$remain_to_pay, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 'TTC');
1178
1179 if ($retAddLine < 0) {
1180 $error++;
1181 }
1182 }
1183 }
1184
1185 // Add link between credit note and origin objects
1186 if (!empty($object->fk_facture_source) && $id > 0) {
1187 $facture_source_link = new FactureFournisseur($db);
1188 if ($facture_source_link->fetch($object->fk_facture_source) > 0) {
1189 $facture_source_link->fetchObjectLinked();
1190 if (!empty($facture_source_link->linkedObjectsIds)) {
1191 foreach ($facture_source_link->linkedObjectsIds as $sourcetype => $TIds) {
1192 $object->add_object_linked($sourcetype, current($TIds));
1193 }
1194 }
1195 }
1196 }
1197 }
1198 } elseif ($fac_recid > 0 && (GETPOSTINT('type') == FactureFournisseur::TYPE_STANDARD || GETPOSTINT('type') == FactureFournisseur::TYPE_DEPOSIT)) {
1199 // Standard invoice or Deposit invoice, created from a Predefined template invoice
1200 if (empty($dateinvoice)) {
1201 $error++;
1202 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
1203 $action = 'create';
1204 } elseif ($dateinvoice > (dol_get_last_hour(dol_now('tzuserrel')) + getDolGlobalInt('INVOICE_MAX_FUTURE_DELAY'))) {
1205 $error++;
1206 setEventMessages($langs->trans("ErrorDateIsInFuture"), null, 'errors');
1207 $action = 'create';
1208 }
1209
1210 if (getDolGlobalInt('INVOICE_SUBTYPE_ENABLED') && empty(GETPOST("subtype"))) {
1211 $error++;
1212 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("InvoiceSubtype")), null, 'errors');
1213 $action = 'create';
1214 }
1215
1216 if (!$error) {
1217 $object->socid = GETPOSTINT('socid');
1218 $object->type = GETPOSTINT('type');
1219 $object->subtype = GETPOSTINT('subtype');
1220 $object->ref = GETPOST('ref', 'alphanohtml');
1221 $object->date = $dateinvoice;
1222 $object->note_public = trim(GETPOST('note_public', 'restricthtml'));
1223 $object->note_private = trim(GETPOST('note_private', 'restricthtml'));
1224 $object->ref_supplier = GETPOST('ref_supplier', 'alphanohtml');
1225 $object->model_pdf = GETPOST('model', 'alphanohtml');
1226 $object->fk_project = GETPOSTINT('projectid');
1227 $object->cond_reglement_id = (GETPOSTINT('type') == 3 ? 1 : GETPOSTINT('cond_reglement_id'));
1228 $object->mode_reglement_id = GETPOSTINT('mode_reglement_id');
1229 $object->fk_account = GETPOSTINT('fk_account');
1230 $object->amount = (float) price2num(GETPOST('amount')); // FIXME: FactureFournisseur::$amount is deprecated and not used?
1231 $object->fk_incoterms = GETPOSTINT('incoterm_id');
1232 $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
1233 $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
1234 $object->multicurrency_tx = GETPOSTFLOAT('originmulticurrency_tx');
1235
1236 // Source facture
1237 $object->fac_rec = $fac_recid;
1238 $fac_rec = new FactureFournisseurRec($db);
1239 $fac_rec->fetch($object->fac_rec);
1240 $fac_rec->fetch_lines();
1241 $object->lines = $fac_rec->lines;
1242
1243 $id = $object->create($user); // This include recopy of links from recurring invoice and recurring invoice lines
1244 }
1245 } elseif ($fac_recid <= 0 && (GETPOSTINT('type') == FactureFournisseur::TYPE_STANDARD || GETPOSTINT('type') == FactureFournisseur::TYPE_DEPOSIT)) {
1246 // Standard invoice or Deposit invoice, not from a Predefined template invoice
1247 if (GETPOSTINT('socid') < 1) {
1248 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Supplier')), null, 'errors');
1249 $action = 'create';
1250 $error++;
1251 }
1252
1253 if (empty($dateinvoice)) {
1254 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('DateInvoice')), null, 'errors');
1255 $action = 'create';
1256 //$_GET['socid'] = $_POST['socid'];
1257 $error++;
1258 } elseif ($dateinvoice > (dol_get_last_hour(dol_now('tzuserrel')) + getDolGlobalInt('INVOICE_MAX_FUTURE_DELAY'))) {
1259 $error++;
1260 setEventMessages($langs->trans("ErrorDateIsInFuture"), null, 'errors');
1261 $action = 'create';
1262 }
1263
1264 if (!GETPOST('ref_supplier')) {
1265 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('RefSupplierBill')), null, 'errors');
1266 $action = 'create';
1267 //$_GET['socid'] = $_POST['socid'];
1268 $error++;
1269 }
1270
1271 if (getDolGlobalInt('INVOICE_SUBTYPE_ENABLED') && empty(GETPOST("subtype"))) {
1272 $error++;
1273 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("InvoiceSubtype")), null, 'errors');
1274 $action = 'create';
1275 }
1276
1277 if (!$error) {
1278 $tmpproject = GETPOSTINT('projectid');
1279
1280 // Creation invoice
1281 $object->socid = GETPOSTINT('socid');
1282 $object->type = GETPOSTINT('type');
1283 $object->subtype = GETPOSTINT('subtype');
1284 $object->ref = GETPOST('ref', 'alphanohtml');
1285 $object->ref_supplier = GETPOST('ref_supplier', 'alphanohtml');
1286 $object->socid = GETPOSTINT('socid');
1287 $object->label = GETPOST('label', 'alphanohtml');
1288 $object->libelle = $object->label; // deprecated
1289 $object->date = $dateinvoice;
1290 $object->date_echeance = $datedue;
1291 $object->note_public = GETPOST('note_public', 'restricthtml');
1292 $object->note_private = GETPOST('note_private', 'restricthtml');
1293 $object->cond_reglement_id = GETPOSTINT('cond_reglement_id');
1294 $object->mode_reglement_id = GETPOSTINT('mode_reglement_id');
1295 $object->fk_account = GETPOSTINT('fk_account');
1296 $object->vat_reverse_charge = GETPOST('vat_reverse_charge') == 'on' ? 1 : 0;
1297 $object->fk_project = ($tmpproject > 0) ? $tmpproject : null;
1298 $object->fk_incoterms = GETPOSTINT('incoterm_id');
1299 $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
1300 $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
1301 $object->multicurrency_tx = GETPOSTFLOAT('originmulticurrency_tx');
1302 $object->transport_mode_id = GETPOSTINT('transport_mode_id');
1303
1304 // Auto calculation of date due if not filled by user
1305 if (empty($object->date_echeance)) {
1306 $object->date_echeance = $object->calculate_date_lim_reglement();
1307 }
1308
1309 $object->fetch_thirdparty();
1310
1311 // If creation from another object of another module
1312 if (!$error && GETPOST('origin', 'alpha') && GETPOST('originid')) {
1313 // Parse element/subelement (ex: project_task)
1314 $element = $subelement = GETPOST('origin', 'alpha');
1315 /*if (preg_match('/^([^_]+)_([^_]+)/i', GETPOST('origin'),$regs))
1316 {
1317 $element = $regs[1];
1318 $subelement = $regs[2];
1319 }*/
1320
1321 // For compatibility
1322 if ($element == 'order') {
1323 $element = $subelement = 'commande';
1324 }
1325 if ($element == 'propal') {
1326 $element = 'comm/propal';
1327 $subelement = 'propal';
1328 }
1329 if ($element == 'contract') {
1330 $element = $subelement = 'contrat';
1331 }
1332 if ($element == 'order_supplier') {
1333 $element = 'fourn';
1334 $subelement = 'fournisseur.commande';
1335 }
1336 if ($element == 'project') {
1337 $element = 'projet';
1338 }
1339 $object->origin_type = GETPOST('origin', 'alpha');
1340 $object->origin = $object->origin_type;
1341 $object->origin_id = GETPOSTINT('originid');
1342
1343
1344 dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
1345 $classname = ucfirst($subelement);
1346 if ($classname == 'Fournisseur.commande') {
1347 $classname = 'CommandeFournisseur';
1348 }
1349 $objectsrc = new $classname($db);
1350 $objectsrc->fetch($originid);
1351 $objectsrc->fetch_thirdparty();
1352
1353 if (!empty($object->origin_type) && !empty($object->origin_id)) {
1354 $object->linkedObjectsIds[$object->origin_type][-1] = $object->origin_id;
1355 }
1356
1357 // Add also link with order if object is reception
1358 if ($object->origin_type == 'reception') {
1359 $objectsrc->fetchObjectLinked();
1360
1361 if (count($objectsrc->linkedObjectsIds['order_supplier']) > 0) {
1362 foreach ($objectsrc->linkedObjectsIds['order_supplier'] as $key => $value) {
1363 $object->linkedObjectsIds['order_supplier'][-1] = $value;
1364 }
1365 }
1366 }
1367
1368 $id = $object->create($user);
1369
1370 // Add lines
1371 if ($id > 0) {
1372 dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
1373 $classname = ucfirst($subelement);
1374 if ($classname == 'Fournisseur.commande') {
1375 $classname = 'CommandeFournisseur';
1376 }
1377 $srcobject = new $classname($db);
1378
1379 $result = $srcobject->fetch(GETPOSTINT('originid'));
1380
1381 // If deposit invoice - down payment with 1 line (fixed amount or percent)
1382 $typeamount = GETPOST('typedeposit', 'alpha');
1383 if (GETPOSTINT('type') == FactureFournisseur::TYPE_DEPOSIT && in_array($typeamount, array('amount', 'variable'))) {
1384 $valuedeposit = price2num(GETPOST('valuedeposit', 'alpha'), 'MU');
1385
1386 // Define the array $amountdeposit
1387 $amountdeposit = array();
1388 if (getDolGlobalString('MAIN_DEPOSIT_MULTI_TVA')) {
1389 if ($typeamount == 'amount') {
1390 $amount = $valuedeposit;
1391 } else {
1392 $amount = $srcobject->total_ttc * ((float) $valuedeposit / 100);
1393 }
1394
1395 $TTotalByTva = array();
1396 foreach ($srcobject->lines as &$line) {
1397 if (!empty($line->special_code)) {
1398 continue;
1399 }
1400 $TTotalByTva[$line->tva_tx] += $line->total_ttc;
1401 }
1402 '@phan-var-force array<string,float> $TTotalByTva';
1403
1404 $amount_ttc_diff = 0.;
1405 foreach ($TTotalByTva as $tva => &$total) {
1406 $coef = $total / $srcobject->total_ttc; // Calc coef
1407 $am = $amount * $coef;
1408 $amount_ttc_diff += $am;
1409 $amountdeposit[$tva] += $am / (1 + (float) $tva / 100); // Convert into HT for the addline
1410 }
1411 } else {
1412 if ($typeamount == 'amount') {
1413 $amountdeposit[0] = $valuedeposit;
1414 } elseif ($typeamount == 'variable') {
1415 if ($result > 0) {
1416 $totalamount = 0;
1417 $lines = $srcobject->lines;
1418 $numlines = count($lines);
1419 for ($i = 0; $i < $numlines; $i++) {
1420 $qualified = 1;
1421 if (empty($lines[$i]->qty)) {
1422 $qualified = 0; // We discard qty=0, it is an option
1423 }
1424 if (!empty($lines[$i]->special_code)) {
1425 $qualified = 0; // We discard special_code (frais port, ecotaxe, option, ...)
1426 }
1427 if ($qualified) {
1428 $totalamount += $lines[$i]->total_ht; // Fixme : is it not for the customer ? Shouldn't we take total_ttc ?
1429 $tva_tx = $lines[$i]->tva_tx;
1430 $amountdeposit[$tva_tx] += ($lines[$i]->total_ht * (float) $valuedeposit) / 100;
1431 }
1432 }
1433
1434 if ($totalamount == 0) {
1435 $amountdeposit[0] = 0;
1436 }
1437 } else {
1438 setEventMessages($srcobject->error, $srcobject->errors, 'errors');
1439 $error++;
1440 $amountdeposit[0] = 0;
1441 }
1442 }
1443
1444 $amount_ttc_diff = array_key_exists(0, $amountdeposit) ? $amountdeposit[0] : 0;
1445 }
1446
1447 foreach ($amountdeposit as $tva => $amount) {
1448 if (empty($amount)) {
1449 continue;
1450 }
1451
1452 $arraylist = array(
1453 'amount' => 'FixAmount',
1454 'variable' => 'VarAmount'
1455 );
1456 $descline = '(DEPOSIT)';
1457 //$descline.= ' - '.$langs->trans($arraylist[$typeamount]);
1458 if ($typeamount == 'amount') {
1459 $descline .= ' ('.price($valuedeposit, 0, $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)).')';
1460 } elseif ($typeamount == 'variable') {
1461 $descline .= ' ('.$valuedeposit.'%)';
1462 }
1463
1464 $descline .= ' - '.$srcobject->ref;
1465 $result = $object->addline(
1466 $descline,
1467 (float) $amount, // subprice
1468 $tva, // vat rate
1469 0, // localtax1_tx
1470 0, // localtax2_tx
1471 1, // quantity
1472 getDolGlobalInt('SUPPLIER_INVOICE_PRODUCTID_DEPOSIT', getDolGlobalInt('INVOICE_PRODUCTID_DEPOSIT')), // fk_product
1473 0, // remise_percent
1474 0, // date_start
1475 0, // date_end
1476 0,
1477 0, // info_bits
1478 'HT',
1479 0, // product_type
1480 1,
1481 0,
1482 array(), // array_options
1483 null,
1484 $object->origin_id,
1485 0,
1486 '',
1487 0, // special_code
1488 0,
1489 0,
1490 $object->origin_type
1491 );
1492 }
1493
1494 $diff = $object->total_ttc - $amount_ttc_diff;
1495
1496 if (getDolGlobalString('MAIN_DEPOSIT_MULTI_TVA') && $diff != 0) {
1497 $object->fetch_lines();
1498 $subprice_diff = $object->lines[0]->subprice - $diff / (1 + $object->lines[0]->tva_tx / 100);
1499 $object->updateline(
1500 $object->lines[0]->id,
1501 $object->lines[0]->desc,
1502 $subprice_diff,
1503 $object->lines[0]->tva_tx,
1504 $object->lines[0]->localtax1_tx,
1505 $object->lines[0]->localtax2_tx,
1506 $object->lines[0]->qty,
1507 $object->lines[0]->fk_product,
1508 'HT',
1509 $object->lines[0]->info_bits,
1510 $object->lines[0]->product_type,
1511 $object->lines[0]->remise_percent,
1512 0,
1513 $object->lines[0]->date_start,
1514 $object->lines[0]->date_end,
1515 array(), // array_options
1516 0,
1517 0,
1518 '',
1519 100
1520 );
1521 }
1522 } elseif ($result > 0) {
1523 $lines = $srcobject->lines;
1524 if (empty($lines) && method_exists($srcobject, 'fetch_lines')) {
1525 $srcobject->fetch_lines();
1526 $lines = $srcobject->lines;
1527 }
1528
1529 $num = count($lines);
1530 for ($i = 0; $i < $num; $i++) { // TODO handle subprice < 0
1531 if (!in_array($lines[$i]->id, $selectedLines)) {
1532 continue; // Skip unselected lines
1533 }
1534
1535 $desc = ($lines[$i]->desc ? $lines[$i]->desc : $lines[$i]->product_label);
1536 $product_type = ($lines[$i]->product_type ? $lines[$i]->product_type : 0);
1537
1538 // Extrafields
1539 if (method_exists($lines[$i], 'fetch_optionals')) {
1540 $lines[$i]->fetch_optionals();
1541 }
1542
1543 // Dates
1544 // TODO mutualiser
1545 $date_start = $lines[$i]->date_debut_prevue;
1546 if ($lines[$i]->date_debut_reel) {
1547 $date_start = $lines[$i]->date_debut_reel;
1548 }
1549 if ($lines[$i]->date_start) {
1550 $date_start = $lines[$i]->date_start;
1551 }
1552 $date_end = $lines[$i]->date_fin_prevue;
1553 if ($lines[$i]->date_fin_reel) {
1554 $date_end = $lines[$i]->date_fin_reel;
1555 }
1556 if ($lines[$i]->date_end) {
1557 $date_end = $lines[$i]->date_end;
1558 }
1559
1560 $tva_tx = $lines[$i]->tva_tx;
1561 // @phan-suppress-next-line PhanTypeMismatchArgumentInternal
1562 if (!empty($lines[$i]->vat_src_code) && !preg_match('/\‍(/', (string) $tva_tx)) {
1563 $tva_tx .= ' ('.$lines[$i]->vat_src_code.')';
1564 }
1565
1566 // FIXME Missing special_code into addline and updateline methods
1567 $object->special_code = $lines[$i]->special_code;
1568
1569 // FIXME If currency different from main currency, take multicurrency price
1570 // Preserve the original entry mode of the line so the total is computed from the typed value (no rounding drift).
1571 $line_price_base_type = $lines[$i]->getPriceBaseType();
1572 if ($line_price_base_type === 'TTC') {
1573 // TTC mode: use the local TTC unit price; the currency price is re-derived (no rounding drift).
1574 $pu = (float) $lines[$i]->subprice_ttc;
1575 $pu_currency = 0;
1576 } elseif ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) {
1577 $pu = 0;
1578 $pu_currency = $lines[$i]->multicurrency_subprice;
1579 } else {
1580 $pu = $lines[$i]->subprice;
1581 $pu_currency = 0;
1582 }
1583
1584 // FIXME Missing $lines[$i]->ref_supplier and $lines[$i]->label into addline and updateline methods. They are filled when coming from order for example.
1585 $result = $object->addline(
1586 $desc,
1587 $pu,
1588 $tva_tx,
1589 $lines[$i]->localtax1_tx,
1590 $lines[$i]->localtax2_tx,
1591 $lines[$i]->qty,
1592 $lines[$i]->fk_product,
1593 $lines[$i]->remise_percent,
1594 (int) $date_start,
1595 (int) $date_end,
1596 0,
1597 $lines[$i]->info_bits,
1598 $line_price_base_type,
1599 $product_type,
1600 $lines[$i]->rang,
1601 0,
1602 $lines[$i]->array_options,
1603 $lines[$i]->fk_unit,
1604 $lines[$i]->id,
1605 $pu_currency,
1606 $lines[$i]->ref_supplier,
1607 $lines[$i]->special_code
1608 );
1609
1610 if ($result < 0) {
1611 $error++;
1612 break;
1613 }
1614 }
1615
1616 // Now reload line
1617 $object->fetch_lines();
1618 } else {
1619 $error++;
1620 }
1621
1622 if (!$error) {
1623 // Hooks
1624 $parameters = array('objFrom' => $srcobject);
1625 $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been
1626 // modified by hook
1627 if ($reshook < 0) {
1628 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1629 $error++;
1630 }
1631 }
1632 } else {
1633 $error++;
1634 }
1635 } elseif (!$error) {
1636 $id = $object->create($user);
1637 if ($id < 0) {
1638 $error++;
1639 }
1640 }
1641 }
1642 }
1643
1644 if ($error) {
1645 $langs->load("errors");
1646 $db->rollback();
1647
1648 setEventMessages($object->error, $object->errors, 'errors');
1649 $action = 'create';
1650 //$_GET['socid'] = $_POST['socid'];
1651 } else {
1652 $db->commit();
1653
1654 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1655 $outputlangs = $langs;
1656 $result = $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1657 if ($result < 0) {
1658 dol_print_error($db, $object->error, $object->errors);
1659 exit;
1660 }
1661 }
1662
1663 header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
1664 exit;
1665 }
1666 } elseif ($action == 'updateline' && $usercancreate) {
1667 // Edit line
1668 $db->begin();
1669
1670 if (! $object->fetch($id) > 0) {
1672 }
1673 $object->fetch_thirdparty();
1674
1675 $tva_tx = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
1676 $tva_tx = str_replace('*', '', $tva_tx);
1677
1678 $pu_ht = price2num(GETPOST('price_ht'), '', 2);
1679 $pu_ttc = price2num(GETPOST('price_ttc'), '', 2);
1680
1681 // The form JS clears the other field when the user edits one of them: only the modified field is filled.
1682 // When both fields are submitted, the user did not change the price - we must preserve the original
1683 // storage mode of the line, otherwise a no-op save would shift the total by rounding.
1684 $up = $pu_ht;
1685 $price_base_type = 'HT';
1686 if (empty($pu_ht) && !empty($pu_ttc)) {
1687 $up = $pu_ttc;
1688 $price_base_type = 'TTC';
1689 } elseif (!empty($pu_ht) && !empty($pu_ttc)) {
1690 foreach ($object->lines as $line_obj) {
1691 if ($line_obj->id == GETPOSTINT('lineid')) {
1692 // Line was originally entered in TTC mode (subprice_ttc filled by addline)
1693 if ($line_obj->wasEnteredIncludingTax()) {
1694 $up = $pu_ttc;
1695 $price_base_type = 'TTC';
1696 }
1697 break;
1698 }
1699 }
1700 }
1701
1702 if (GETPOST('productid') > 0) {
1703 $productsupplier = new ProductFournisseur($db);
1704 if (getDolGlobalInt('SUPPLIER_INVOICE_WITH_PREDEFINED_PRICES_ONLY') == 1) { // Not the common case
1705 if (GETPOST('productid') > 0 && $productsupplier->get_buyprice(0, (float) price2num(GETPOST('qty')), GETPOSTINT('productid'), 'restricthtml', GETPOSTINT('socid')) < 0) {
1706 setEventMessages($langs->trans("ErrorQtyTooLowForThisSupplier"), null, 'warnings');
1707 }
1708 }
1709
1710 $prod = new Product($db);
1711 $prod->fetch(GETPOSTINT('productid'));
1712 $label = $prod->description;
1713 if (trim(GETPOST('product_desc', 'restricthtml')) != trim($label)) {
1714 $label = GETPOST('product_desc', 'restricthtml');
1715 }
1716
1717 $type = $prod->type;
1718 } else {
1719 $label = GETPOST('product_desc', 'restricthtml');
1720 $type = GETPOSTINT("type");
1721 }
1722
1723 $date_start = dol_mktime(GETPOSTINT('date_starthour'), GETPOSTINT('date_startmin'), GETPOSTINT('date_startsec'), GETPOSTINT('date_startmonth'), GETPOSTINT('date_startday'), GETPOSTINT('date_startyear'));
1724 $date_end = dol_mktime(GETPOSTINT('date_endhour'), GETPOSTINT('date_endmin'), GETPOSTINT('date_endsec'), GETPOSTINT('date_endmonth'), GETPOSTINT('date_endday'), GETPOSTINT('date_endyear'));
1725
1726 // Define info_bits
1727 $info_bits = 0;
1728 if (preg_match('/\*/', $tva_tx)) {
1729 $info_bits |= 0x01;
1730 }
1731
1732 // Define vat_rate
1733 $tva_tx = str_replace('*', '', $tva_tx);
1734 $localtax1_tx = get_localtax($tva_tx, 1, $mysoc, $object->thirdparty);
1735 $localtax2_tx = get_localtax($tva_tx, 2, $mysoc, $object->thirdparty);
1736
1737 $remise_percent = price2num(GETPOST('remise_percent'), '', 2);
1738 $pu_devise = price2num(GETPOST('multicurrency_subprice'), 'MU', 2);
1739
1740 // Extrafields Lines
1741 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
1742 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
1743 // Unset extrafield POST Data
1744 if (is_array($extralabelsline)) {
1745 foreach ($extralabelsline as $key => $value) {
1746 unset($_POST["options_".$key]);
1747 }
1748 }
1749
1750 $result = $object->updateline(
1751 GETPOSTINT('lineid'),
1752 $label,
1753 (float) $up,
1754 $tva_tx,
1755 $localtax1_tx,
1756 $localtax2_tx,
1757 (float) price2num(GETPOST('qty'), 'MS'),
1758 GETPOSTINT('productid'),
1759 $price_base_type,
1760 $info_bits,
1761 $type,
1762 (float) $remise_percent,
1763 0,
1765 $date_end,
1766 $array_options,
1767 GETPOST('units') != '' ? GETPOSTINT('units') : null,
1768 (float) $pu_devise,
1769 GETPOST('fourn_ref', 'alpha')
1770 );
1771 if ($result >= 0) {
1772 unset($_POST['label']);
1773 unset($_POST['fourn_ref']);
1774 unset($_POST['date_starthour']);
1775 unset($_POST['date_startmin']);
1776 unset($_POST['date_startsec']);
1777 unset($_POST['date_startday']);
1778 unset($_POST['date_startmonth']);
1779 unset($_POST['date_startyear']);
1780 unset($_POST['date_endhour']);
1781 unset($_POST['date_endmin']);
1782 unset($_POST['date_endsec']);
1783 unset($_POST['date_endday']);
1784 unset($_POST['date_endmonth']);
1785 unset($_POST['date_endyear']);
1786 unset($_POST['price_ttc']);
1787 unset($_POST['price_ht']);
1788
1789 $db->commit();
1790 } else {
1791 $db->rollback();
1792 setEventMessages($object->error, $object->errors, 'errors');
1793 }
1794 } elseif ($action == 'addline' && GETPOST('submitforalllines', 'aZ09') && (GETPOST('alldate_start', 'alpha') || GETPOST('alldate_end', 'alpha')) && $usercancreate) {
1795 // Define date start and date end for all line
1796 $alldate_start = dol_mktime(GETPOSTINT('alldate_starthour'), GETPOSTINT('alldate_startmin'), 0, GETPOSTINT('alldate_startmonth'), GETPOSTINT('alldate_startday'), GETPOSTINT('alldate_startyear'));
1797 $alldate_end = dol_mktime(GETPOSTINT('alldate_endhour'), GETPOSTINT('alldate_endmin'), 0, GETPOSTINT('alldate_endmonth'), GETPOSTINT('alldate_endday'), GETPOSTINT('alldate_endyear'));
1798 foreach ($object->lines as $line) {
1799 if ($line->product_type == 1) { // only service line
1800 // Preserve the original entry mode of the line so the total is not drifted by rounding.
1801 $line_price_base_type = $line->getPriceBaseType();
1802 $line_pu = ($line_price_base_type === 'TTC') ? (float) $line->subprice_ttc : (float) $line->subprice;
1803 $result = $object->updateline($line->id, $line->desc, $line_pu, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, $line->qty, $line->fk_product, $line_price_base_type, $line->info_bits, $line->product_type, $line->remise_percent, 0, $alldate_start, $alldate_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice, $line->ref_supplier, $line->rang);
1804 }
1805 }
1806 } elseif ($action == 'addline' && GETPOST('submitforalllines', 'alpha') && GETPOST('remiseforalllines', 'alpha') !== '' && $usercancreate) {
1807 // Define vat_rate
1808 $remise_percent = (GETPOST('remiseforalllines') ? GETPOST('remiseforalllines') : 0);
1809 $remise_percent = (float) str_replace('*', '', $remise_percent);
1810 foreach ($object->lines as $line) {
1811 // Preserve the original entry mode of the line so the total is not drifted by rounding.
1812 $line_price_base_type = $line->getPriceBaseType();
1813 $line_pu = ($line_price_base_type === 'TTC') ? (float) $line->subprice_ttc : (float) $line->subprice;
1814 $result = $object->updateline($line->id, $line->desc, $line_pu, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, $line->qty, $line->fk_product, $line_price_base_type, $line->info_bits, $line->product_type, $remise_percent, 0, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice, $line->ref_supplier, $line->rang);
1815 }
1816 } elseif ($action == 'addline' && GETPOST('submitforalllines', 'aZ09') && GETPOST('vatforalllines', 'alpha') != '' && $usercancreate) {
1817 // Define vat_rate
1818 $vat_rate = (GETPOST('vatforalllines') ? GETPOST('vatforalllines') : 0);
1819 $vat_rate = str_replace('*', '', $vat_rate);
1820 $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty, $mysoc);
1821 $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty, $mysoc);
1822 foreach ($object->lines as $line) {
1823 // Preserve the original entry mode of the line so the total is not drifted by rounding.
1824 $line_price_base_type = $line->getPriceBaseType();
1825 $line_pu = ($line_price_base_type === 'TTC') ? (float) $line->subprice_ttc : (float) $line->subprice;
1826 $result = $object->updateline($line->id, $line->desc, $line_pu, $vat_rate, $localtax1_rate, $localtax2_rate, $line->qty, $line->fk_product, $line_price_base_type, $line->info_bits, $line->product_type, $line->remise_percent, 0, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice, $line->ref_supplier, $line->rang);
1827 }
1828 } elseif ($action == 'addline' && $usercancreate) {
1829 // Add a product line
1830 $db->begin();
1831
1832 $ret = $object->fetch($id);
1833 if ($ret < 0) {
1834 dol_print_error($db, $object->error);
1835 exit;
1836 }
1837 $ret = $object->fetch_thirdparty();
1838
1839 $langs->load('errors');
1840 $error = 0;
1841
1842 // Set if we used free entry or predefined product
1843 $predef = '';
1844 $line_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
1845 $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'));
1846 $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'));
1847
1848 $prod_entry_mode = GETPOST('prod_entry_mode');
1849 if ($prod_entry_mode == 'free') {
1850 $idprod = 0;
1851 } else {
1852 $idprod = GETPOSTINT('idprod');
1853 }
1854
1855 $price_ht = '';
1856 $price_ht_devise = '';
1857 $price_ttc = '';
1858 $price_ttc_devise = '';
1859
1860 if (GETPOST('price_ht') !== '') {
1861 $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
1862 }
1863 if (GETPOST('multicurrency_price_ht') !== '') {
1864 $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU', 2);
1865 }
1866 if (GETPOST('price_ttc') !== '') {
1867 $price_ttc = price2num(GETPOST('price_ttc'), 'MU', 2);
1868 }
1869 if (GETPOST('multicurrency_price_ttc') !== '') {
1870 $price_ttc_devise = price2num(GETPOST('multicurrency_price_ttc'), 'CU', 2);
1871 }
1872
1873 $tva_tx = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0); // Can be '1.2' or '1.2 (CODE)'
1874
1875 $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS');
1876
1877 $remise_percent = (GETPOSTISSET('remise_percent'.$predef) ? price2num(GETPOST('remise_percent'.$predef, 'alpha'), '', 2) : 0);
1878 if (empty($remise_percent)) {
1879 $remise_percent = 0;
1880 }
1881
1882 // Extrafields
1883 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
1884 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
1885 // Unset extrafield
1886 if (is_array($extralabelsline)) {
1887 // Get extra fields
1888 foreach ($extralabelsline as $key => $value) {
1889 unset($_POST["options_".$key]);
1890 }
1891 }
1892
1893 if ($prod_entry_mode == 'free' && GETPOST('price_ht') < 0 && $qty < 0) {
1894 setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPrice'), $langs->transnoentitiesnoconv('Qty')), null, 'errors');
1895 $error++;
1896 }
1897 if ($prod_entry_mode == 'free' && (!GETPOST('idprodfournprice') || GETPOST('idprodfournprice') == '-1') && GETPOSTINT('type') < 0) {
1898 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
1899 $error++;
1900 }
1901
1902 // Do not allow negative lines for free products (invite to enter a discount instead)
1903 if ($prod_entry_mode == 'free' && (!GETPOST('idprodfournprice') || GETPOST('idprodfournprice') == '-1')
1904 && (((float) $price_ht < 0 && !getDolGlobalString('SUPPLIER_INVOICE_ENABLE_NEGATIVE_LINES')) || $price_ht === '')
1905 && (((float) $price_ht_devise < 0 && !getDolGlobalString('SUPPLIER_INVOICE_ENABLE_NEGATIVE_LINES')) || $price_ht_devise === '')
1906 && ((float) $price_ttc < 0 && !getDolGlobalString('SUPPLIER_INVOICE_ENABLE_NEGATIVE_LINES') || $price_ttc === '')
1907 && ((float) $price_ttc_devise < 0 && !getDolGlobalString('SUPPLIER_INVOICE_ENABLE_NEGATIVE_LINES') || $price_ttc_devise === '')
1908 && $object->type != $object::TYPE_CREDIT_NOTE) { // Unit price can be 0 but not ''
1909 if (((float) $price_ht < 0 || (float) $price_ttc < 0) && !getDolGlobalString('SUPPLIER_INVOICE_ENABLE_NEGATIVE_LINES')) {
1910 $langs->load("errors");
1911 if ($object->type == $object::TYPE_DEPOSIT) {
1912 // Using negative lines on deposit lead to headach and blocking problems when you want to consume them.
1913 setEventMessages($langs->trans("ErrorLinesCantBeNegativeOnDeposits"), null, 'errors');
1914 } else {
1915 setEventMessages($langs->trans("ErrorFieldCantBeNegativeOnInvoice", $langs->transnoentitiesnoconv("UnitPrice"), $langs->transnoentitiesnoconv("CustomerAbsoluteDiscountShort")), null, 'errors');
1916 }
1917 $error++;
1918 }
1919 }
1920 if ($prod_entry_mode == 'free' && (!GETPOST('idprodfournprice') || GETPOST('idprodfournprice') == '-1') && GETPOST('price_ht') === '' && GETPOST('price_ttc') === '' && $price_ht_devise === '') { // Unit price can be 0 but not ''
1921 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('UnitPrice')), null, 'errors');
1922 $error++;
1923 }
1924
1925 if ($prod_entry_mode == 'free' && (!GETPOST('idprodfournprice') || GETPOST('idprodfournprice') == '-1') && !GETPOST('dp_desc')) {
1926 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
1927 $error++;
1928 }
1929 if (!GETPOST('qty', 'alpha')) { // 0 is NOT allowed for invoices
1930 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
1931 $error++;
1932 }
1933
1934 if (!$error && isModEnabled('variants') && $prod_entry_mode != 'free') {
1935 if ($combinations = GETPOST('combinations', 'array:alphanohtml')) {
1936 //Check if there is a product with the given combination
1937 $prodcomb = new ProductCombination($db);
1938
1939 if ($res = $prodcomb->fetchByProductCombination2ValuePairs($idprod, $combinations)) {
1940 $idprod = $res->fk_product_child;
1941 } else {
1942 setEventMessages($langs->trans('ErrorProductCombinationNotFound'), null, 'errors');
1943 $error++;
1944 }
1945 }
1946 }
1947
1948 if ($prod_entry_mode != 'free' && empty($error)) { // With combolist mode idprodfournprice is > 0 or -1. With autocomplete, idprodfournprice is > 0 or ''
1949 $productsupplier = new ProductFournisseur($db);
1950
1951 $idprod = 0;
1952 if (GETPOST('idprodfournprice', 'alpha') == -1 || GETPOST('idprodfournprice', 'alpha') == '') {
1953 $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, ...)
1954 }
1955
1956 $reg = array();
1957 if (preg_match('/^idprod_([0-9]+)$/', GETPOST('idprodfournprice', 'alpha'), $reg)) {
1958 $idprod = (int) $reg[1];
1959 $res = $productsupplier->fetch($idprod); // Load product from its id
1960 // Call to init some price properties of $productsupplier
1961 // So if a supplier price already exists for another thirdparty (first one found), we use it as reference price
1962 if (getDolGlobalString('SUPPLIER_TAKE_FIRST_PRICE_IF_NO_PRICE_FOR_CURRENT_SUPPLIER')) {
1963 $fksoctosearch = 0;
1964 $productsupplier->get_buyprice(0, -1, $idprod, 'none', $fksoctosearch); // We force qty to -1 to be sure to find if a supplier price exist
1965 if ($productsupplier->fourn_socid != $socid) { // The price we found is for another supplier, so we clear supplier price
1966 $productsupplier->ref_supplier = '';
1967 }
1968 } else {
1969 $fksoctosearch = $object->thirdparty->id;
1970 $productsupplier->get_buyprice(0, -1, $idprod, 'none', $fksoctosearch); // We force qty to -1 to be sure to find if a supplier price exist
1971 }
1972 } elseif (GETPOSTINT('idprodfournprice') > 0) { // Should be an int at this point
1973 $qtytosearch = (float) $qty; // Just to see if a price exists for the quantity. Not used to found vat.
1974 //$qtytosearch=-1; // We force qty to -1 to be sure to find if a supplier price exist
1975 $idprod = $productsupplier->get_buyprice(GETPOSTINT('idprodfournprice'), $qtytosearch);
1976 $res = $productsupplier->fetch($idprod);
1977 }
1978
1979 if ($idprod > 0) {
1980 $label = $productsupplier->label;
1981 // Define output language
1982 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
1983 $outputlangs = $langs;
1984 $newlang = '';
1985 if (/* empty($newlang) && */ GETPOST('lang_id', 'aZ09')) {
1986 $newlang = GETPOST('lang_id', 'aZ09');
1987 }
1988 if (empty($newlang)) {
1989 $newlang = $object->thirdparty->default_lang;
1990 }
1991 if (!empty($newlang)) {
1992 $outputlangs = new Translate("", $conf);
1993 $outputlangs->setDefaultLang($newlang);
1994 }
1995 $desc = (!empty($productsupplier->multilangs[$outputlangs->defaultlang]["description"])) ? $productsupplier->multilangs[$outputlangs->defaultlang]["description"] : $productsupplier->description;
1996 } else {
1997 $desc = $productsupplier->description;
1998 }
1999 // if we use supplier description of the products
2000 if (!empty($productsupplier->desc_supplier) && getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
2001 $desc = $productsupplier->desc_supplier;
2002 }
2003
2004 if (getDolGlobalInt('PRODUIT_AUTOFILL_DESC') == 0) {
2005 // 'DoNotAutofillButAutoConcat'
2006 $desc = dol_concatdesc($desc, $line_desc, false, getDolGlobalString('MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION') ? true : false);
2007 } else {
2008 //'AutoFillFormFieldBeforeSubmit' or 'DoNotUseDescriptionOfProdut' => User has already done the modification they want
2009 $desc = $line_desc;
2010 }
2011
2012 $ref_supplier = $productsupplier->ref_supplier;
2013
2014 // Get vat rate
2015 if (!GETPOSTISSET('tva_tx')) { // If vat rate not provided from the form (the form has the priority)
2016 $tmpidprodfournprice = GETPOST('idprodfournprice', 'alpha'); // can be an id of price, or -1, -2, -99 or 'idprod_...'
2017 if (is_numeric($tmpidprodfournprice) && (int) $tmpidprodfournprice > 0) {
2018 $tmpidprodfournprice = (int) $tmpidprodfournprice;
2019 } else {
2020 $tmpidprodfournprice = 0;
2021 }
2022
2023 $tva_tx = get_default_tva($object->thirdparty, $mysoc, $productsupplier->id, $tmpidprodfournprice);
2024 $tva_npr = get_default_npr($object->thirdparty, $mysoc, $productsupplier->id, $tmpidprodfournprice);
2025 }
2026 if (empty($tva_tx) || empty($tva_npr)) {
2027 $tva_npr = 0;
2028 }
2029 $localtax1_tx = get_localtax($tva_tx, 1, $mysoc, $object->thirdparty, $tva_npr);
2030 $localtax2_tx = get_localtax($tva_tx, 2, $mysoc, $object->thirdparty, $tva_npr);
2031
2032 $type = $productsupplier->type;
2033 if (GETPOST('price_ht') != '' || GETPOST('multicurrency_price_ht') != '') {
2034 $price_base_type = 'HT';
2035 $pu = price2num($price_ht, 'MU');
2036 $pu_devise = price2num($price_ht_devise, 'CU');
2037 } elseif (GETPOST('price_ttc') != '' || GETPOST('multicurrency_price_ttc') != '') {
2038 $price_base_type = 'TTC';
2039 $pu = price2num($price_ttc, 'MU');
2040 $pu_devise = price2num($price_ttc_devise, 'CU');
2041 } else {
2042 $price_base_type = ($productsupplier->fourn_price_base_type ? $productsupplier->fourn_price_base_type : 'HT');
2043 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
2044 $pu = $productsupplier->fourn_pu;
2045 $pu_devise = 0;
2046 } else {
2047 $pu = $productsupplier->fourn_pu;
2048 $pu_devise = $productsupplier->fourn_multicurrency_unitprice;
2049 }
2050 }
2051
2052 $ref_supplier = $productsupplier->ref_supplier;
2053
2054 if (empty($pu)) {
2055 $pu = 0; // If pu is '' or null, we force to have a numeric value
2056 }
2057
2058 $result = $object->addline(
2059 $desc,
2060 $pu,
2061 $tva_tx,
2062 $localtax1_tx,
2063 $localtax2_tx,
2064 (float) $qty,
2065 $idprod,
2066 $remise_percent,
2068 $date_end,
2069 0,
2070 $tva_npr,
2071 $price_base_type,
2072 $type,
2073 min($rank, count($object->lines) + 1),
2074 0,
2075 $array_options,
2076 $productsupplier->fk_unit,
2077 0,
2078 $pu_devise,
2079 GETPOST('fourn_ref', 'alpha'),
2080 0
2081 );
2082 }
2083 if ($idprod == -99 || $idprod == 0) {
2084 // Product not selected
2085 $error++;
2086 $langs->load("errors");
2087 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")), null, 'errors');
2088 }
2089 if ($idprod == -1) {
2090 // Quantity too low
2091 $error++;
2092 $langs->load("errors");
2093 setEventMessages($langs->trans("ErrorQtyTooLowForThisSupplier"), null, 'errors');
2094 }
2095 } elseif (empty($error)) { // $price_ht is already set
2096 $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
2097 $tva_tx = str_replace('*', '', $tva_tx);
2098 $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
2099 $desc = $line_desc;
2100 $type = GETPOSTINT('type');
2101 $ref_supplier = GETPOST('fourn_ref', 'alpha');
2102
2103 $fk_unit = GETPOST('units') !== '' ? GETPOSTINT('units') : null;
2104
2105 if (!preg_match('/\‍((.*)\‍)/', $tva_tx)) {
2106 $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'
2107 }
2108
2109 // Local Taxes
2110 $localtax1_tx = get_localtax($tva_tx, 1, $mysoc, $object->thirdparty);
2111 $localtax2_tx = get_localtax($tva_tx, 2, $mysoc, $object->thirdparty);
2112
2113 // Keep the entry mode chosen by the user so the total is computed from the typed value (no rounding drift).
2114 if (GETPOST('price_ht') != '' || GETPOST('multicurrency_price_ht') != '') {
2115 $price_base_type = 'HT';
2116 $pu = price2num($price_ht, 'MU'); // $pu must be rounded according to settings
2117 $pu_devise = price2num($price_ht_devise, 'CU');
2118 } else {
2119 $price_base_type = 'TTC';
2120 $pu = price2num(GETPOST('price_ttc'), 'MU');
2121 $pu_devise = price2num($price_ttc_devise, 'CU');
2122 }
2123
2124 $result = $object->addline($line_desc, (float) $pu, $tva_tx, $localtax1_tx, $localtax2_tx, (float) $qty, 0, $remise_percent, $date_start, $date_end, 0, $tva_npr, $price_base_type, $type, -1, 0, $array_options, $fk_unit, 0, (float) $pu_devise, $ref_supplier);
2125 }
2126
2127 //print "xx".$tva_tx; exit;
2128 if (!$error && $result > 0) {
2129 $db->commit();
2130
2131 // Define output language
2132 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
2133 $outputlangs = $langs;
2134 $newlang = '';
2135 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
2136 $newlang = GETPOST('lang_id', 'aZ09');
2137 }
2138 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
2139 $newlang = $object->thirdparty->default_lang;
2140 }
2141 if (!empty($newlang)) {
2142 $outputlangs = new Translate("", $conf);
2143 $outputlangs->setDefaultLang($newlang);
2144 }
2145 $model = $object->model_pdf;
2146 $ret = $object->fetch($id); // Reload to get new records
2147
2148 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
2149 if ($result < 0) {
2150 setEventMessages($object->error, $object->errors, 'errors');
2151 }
2152 }
2153
2154 unset($_POST ['prod_entry_mode']);
2155
2156 unset($_POST['qty']);
2157 unset($_POST['type']);
2158 unset($_POST['remise_percent']);
2159 unset($_POST['pu']);
2160 unset($_POST['price_ht']);
2161 unset($_POST['multicurrency_price_ht']);
2162 unset($_POST['price_ttc']);
2163 unset($_POST['fourn_ref']);
2164 unset($_POST['tva_tx']);
2165 unset($_POST['label']);
2166 unset($localtax1_tx);
2167 unset($localtax2_tx);
2168 unset($_POST['np_marginRate']);
2169 unset($_POST['np_markRate']);
2170 unset($_POST['dp_desc']);
2171 unset($_POST['idprodfournprice']);
2172 unset($_POST['units']);
2173
2174 unset($_POST['date_starthour']);
2175 unset($_POST['date_startmin']);
2176 unset($_POST['date_startsec']);
2177 unset($_POST['date_startday']);
2178 unset($_POST['date_startmonth']);
2179 unset($_POST['date_startyear']);
2180 unset($_POST['date_endhour']);
2181 unset($_POST['date_endmin']);
2182 unset($_POST['date_endsec']);
2183 unset($_POST['date_endday']);
2184 unset($_POST['date_endmonth']);
2185 unset($_POST['date_endyear']);
2186
2187 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$id);
2188 exit();
2189 } else {
2190 $db->rollback();
2191 setEventMessages($object->error, $object->errors, 'errors');
2192 }
2193
2194 $action = '';
2195 } elseif ($action == 'classin' && $usercancreate) {
2196 $object->fetch($id);
2197 $result = $object->setProject($projectid);
2198 } elseif ($action == 'confirm_edit' && $confirm == 'yes' && $usercancreate) {
2199 // Set invoice to draft status
2200 $object->fetch($id);
2201
2202 $totalpaid = $object->getSommePaiement();
2203 $resteapayer = $object->total_ttc - $totalpaid;
2204
2205 // We check that lines of invoices are exported in accountancy
2206 $ventilExportCompta = $object->getVentilExportCompta();
2207
2208 if (!$ventilExportCompta) {
2209 // We verify that no payment was done
2210 if ($resteapayer == price2num($object->total_ttc, 'MT', 1) && $object->status == FactureFournisseur::STATUS_VALIDATED) {
2211 $idwarehouse = GETPOST('idwarehouse');
2212
2213 $object->fetch_thirdparty();
2214
2215 $qualified_for_stock_change = 0;
2216 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
2217 $qualified_for_stock_change = $object->hasProductsOrServices(2);
2218 } else {
2219 $qualified_for_stock_change = $object->hasProductsOrServices(1);
2220 }
2221
2222 // Check parameters
2223 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_BILL') && $qualified_for_stock_change) {
2224 $langs->load("stocks");
2225 if (!$idwarehouse || $idwarehouse == -1) {
2226 $error++;
2227 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
2228 $action = '';
2229 }
2230 }
2231
2232 $object->setDraft($user, $idwarehouse);
2233
2234 // Define output language
2235 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
2236 $outputlangs = $langs;
2237 $newlang = '';
2238 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
2239 $newlang = GETPOST('lang_id', 'aZ09');
2240 }
2241 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
2242 $newlang = $object->thirdparty->default_lang;
2243 }
2244 if (!empty($newlang)) {
2245 $outputlangs = new Translate("", $conf);
2246 $outputlangs->setDefaultLang($newlang);
2247 }
2248 $model = $object->model_pdf;
2249 $ret = $object->fetch($id); // Reload to get new records
2250
2251 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
2252 if ($result < 0) {
2253 dol_print_error($db, $object->error, $object->errors);
2254 }
2255 }
2256
2257 $action = '';
2258 }
2259 }
2260 } elseif ($action == 'reopen' && $usercancreate) {
2261 // Set invoice to validated/unpaid status
2262 $result = $object->fetch($id);
2264 || ($object->status == FactureFournisseur::STATUS_ABANDONED && $object->close_code != 'replaced')) {
2265 $result = $object->setUnpaid($user);
2266 if ($result > 0) {
2267 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$id);
2268 exit;
2269 } else {
2270 setEventMessages($object->error, $object->errors, 'errors');
2271 }
2272 }
2273 }
2274
2275 // Actions when printing a doc from card
2276 include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
2277
2278 // Actions to send emails
2279 $triggersendname = 'BILL_SUPPLIER_SENTBYMAIL';
2280 $paramname = 'id';
2281 $autocopy = 'MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO';
2282 $trackid = 'sinv'.$object->id;
2283 include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
2284
2285 // Actions to build doc
2286 $upload_dir = getMultidirOutput($object);
2287 $permissiontoadd = $usercancreate;
2288 include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
2289
2290 // Make calculation according to calculationrule
2291 if ($action == 'calculate' && $usercancreate) {
2292 $calculationrule = GETPOST('calculationrule');
2293
2294 $object->fetch($id);
2295 $object->fetch_thirdparty();
2296 $result = $object->update_price(0, (($calculationrule == 'totalofround') ? '0' : '1'), 0, $object->thirdparty);
2297 if ($result <= 0) {
2298 dol_print_error($db, $object->error, $object->errors);
2299 exit;
2300 }
2301 }
2302 if ($action == 'update_extras' && $permissiontoeditextra) {
2303 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
2304
2305 $attribute_name = GETPOST('attribute', 'aZ09');
2306
2307 // Fill array 'array_options' with data from update form
2308 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
2309 if ($ret < 0) {
2310 $error++;
2311 }
2312
2313 if (!$error) {
2314 $result = $object->updateExtraField($attribute_name, 'BILL_SUPPLIER_MODIFY');
2315 if ($result < 0) {
2316 setEventMessages($object->error, $object->errors, 'errors');
2317 $error++;
2318 }
2319 }
2320
2321 if ($error) {
2322 $action = 'edit_extras';
2323 }
2324 }
2325
2326 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
2327 if ($action == 'addcontact' && $usercancreate) {
2328 $result = $object->fetch($id);
2329
2330 if ($result > 0 && $id > 0) {
2331 $contactid = (GETPOST('userid') ? GETPOSTINT('userid') : GETPOSTINT('contactid'));
2332 $typeid = (GETPOST('typecontact') ? GETPOSTINT('typecontact') : GETPOSTINT('type'));
2333 $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09'));
2334 }
2335
2336 if ($result >= 0) {
2337 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
2338 exit;
2339 } else {
2340 if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
2341 $langs->load("errors");
2342 setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
2343 } else {
2344 setEventMessages($object->error, $object->errors, 'errors');
2345 }
2346 }
2347 } elseif ($action == 'swapstatut' && $usercancreate) {
2348 // bascule du statut d'un contact
2349 if ($object->fetch($id)) {
2350 $result = $object->swapContactStatus(GETPOSTINT('ligne'));
2351 } else {
2353 }
2354 } elseif ($action == 'deletecontact' && $usercancreate) {
2355 // Efface un contact
2356 $object->fetch($id);
2357 $result = $object->delete_contact(GETPOSTINT("lineid"));
2358
2359 if ($result >= 0) {
2360 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
2361 exit;
2362 } else {
2364 }
2365 }
2366 }
2367}
2368
2369
2370/*
2371 * View
2372 */
2373
2374$form = new Form($db);
2375$formfile = new FormFile($db);
2376$bankaccountstatic = new Account($db);
2377$paymentstatic = new PaiementFourn($db);
2378if (isModEnabled('project')) {
2379 $formproject = new FormProjets($db);
2380}
2381
2382$now = dol_now();
2383
2384$title = $object->ref." - ".$langs->trans('Card');
2385if ($action == 'create') {
2386 $title = $langs->trans("NewSupplierInvoice");
2387}
2388$help_url = 'EN:Module_Suppliers_Invoices|FR:Module_Fournisseurs_Factures|ES:Módulo_Facturas_de_proveedores|DE:Modul_Lieferantenrechnungen';
2389llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-fourn-facture page-card');
2390
2391// Mode creation
2392if ($action == 'create') {
2393 $facturestatic = new FactureFournisseur($db);
2394 $selectedLines = array(); // Ensure initialised
2395
2396 print load_fiche_titre($langs->trans('NewSupplierInvoice'), '', 'supplier_invoice');
2397
2399
2400 $currency_code = $conf->currency;
2401 $vat_reverse_charge = 0;
2402
2403 $societe = '';
2404 if (GETPOSTINT('socid') > 0) {
2405 $societe = new Societe($db);
2406 $societe->fetch(GETPOSTINT('socid'));
2407 if (isModEnabled("multicurrency") && !empty($societe->multicurrency_code)) {
2408 $currency_code = $societe->multicurrency_code;
2409 }
2410 }
2411
2412 $objectsrc = null; // Initialise
2413 if (!empty($origin) && !empty($originid)) {
2414 // Parse element/subelement (ex: project_task)
2415 $element = $subelement = $origin;
2416
2417 if ($element == 'project') {
2418 $projectid = $originid;
2419 $element = 'projet';
2420 }
2421
2422 // For compatibility
2423 if ($element == 'order') {
2424 $element = $subelement = 'commande';
2425 }
2426 if ($element == 'propal') {
2427 $element = 'comm/propal';
2428 $subelement = 'propal';
2429 }
2430 if ($element == 'contract') {
2431 $element = $subelement = 'contrat';
2432 }
2433 if ($element == 'order_supplier') {
2434 $element = 'fourn';
2435 $subelement = 'fournisseur.commande';
2436 }
2437
2438 dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
2439 $classname = ucfirst($subelement);
2440 if ($classname == 'Fournisseur.commande') {
2441 $classname = 'CommandeFournisseur';
2442 }
2443 $objectsrc = new $classname($db);
2444 '@phan-var-force Project|Commande|Propal|Facture|Contrat|CommandeFournisseur|CommonObject $objectsrc';
2446 $objectsrc->fetch($originid);
2447 $objectsrc->fetch_thirdparty();
2448
2449 $projectid = (int) $objectsrc->fk_project;
2450 //$ref_client = (!empty($objectsrc->ref_client)?$object->ref_client:'');
2451 $soc = $objectsrc->thirdparty;
2452
2453 $cond_reglement_id = 0;
2454 $mode_reglement_id = 0;
2455 $fk_account = 0;
2456 $transport_mode_id = 0;
2457
2458 // set from object source
2459 if (!empty($objectsrc->cond_reglement_id)) {
2460 $cond_reglement_id = $objectsrc->cond_reglement_id;
2461 }
2462 if (!empty($objectsrc->mode_reglement_id)) {
2463 $mode_reglement_id = $objectsrc->mode_reglement_id;
2464 }
2465 if (!empty($objectsrc->fk_account)) {
2466 $fk_account = $objectsrc->fk_account;
2467 }
2468 if (!empty($objectsrc->transport_mode_id)) {
2469 $transport_mode_id = $objectsrc->transport_mode_id;
2470 }
2471
2472 if (empty($cond_reglement_id)
2473 || empty($mode_reglement_id)
2474 || empty($fk_account)
2475 || empty($transport_mode_id)
2476 ) {
2477 if ($origin == 'reception') {
2478 // try to get from source of reception (supplier order)
2479 if (!isset($objectsrc->supplier_order)) {
2480 $objectsrc->fetch_origin();
2481 }
2482
2483 if (!empty($objectsrc->origin_object)) {
2484 $originObject = $objectsrc->origin_object;
2485 if (empty($cond_reglement_id) && !empty($originObject->cond_reglement_id)) {
2486 $cond_reglement_id = $originObject->cond_reglement_id;
2487 }
2488 if (empty($mode_reglement_id) && !empty($originObject->mode_reglement_id)) {
2489 $mode_reglement_id = $originObject->mode_reglement_id;
2490 }
2491 if (empty($fk_account) && !empty($originObject->fk_account)) {
2492 $fk_account = $originObject->fk_account;
2493 }
2494 if (empty($transport_mode_id) && !empty($originObject->transport_mode_id)) {
2495 $transport_mode_id = $originObject->transport_mode_id;
2496 }
2497 }
2498 }
2499
2500 // try to get from third-party of source object
2501 if (!empty($soc)) {
2502 if (empty($cond_reglement_id) && !empty($soc->cond_reglement_supplier_id)) {
2503 $cond_reglement_id = $soc->cond_reglement_supplier_id;
2504 }
2505 if (empty($mode_reglement_id) && !empty($soc->mode_reglement_supplier_id)) {
2506 $mode_reglement_id = $soc->mode_reglement_supplier_id;
2507 }
2508 if (empty($fk_account) && !empty($soc->fk_account)) {
2509 $fk_account = $soc->fk_account;
2510 }
2511 if (empty($transport_mode_id) && !empty($soc->transport_mode_id)) {
2512 $transport_mode_id = $soc->transport_mode_id;
2513 }
2514 }
2515 }
2516
2517 if (isModEnabled("multicurrency")) {
2518 if (!empty($objectsrc->multicurrency_code)) {
2519 $currency_code = $objectsrc->multicurrency_code;
2520 }
2521 if (getDolGlobalString('MULTICURRENCY_USE_ORIGIN_TX') && !empty($objectsrc->multicurrency_tx)) {
2522 $currency_tx = $objectsrc->multicurrency_tx;
2523 }
2524 }
2525
2526 $datetmp = dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
2527 $dateinvoice = ($datetmp == '' ? (getDolGlobalString('MAIN_AUTOFILL_DATE') ? '' : -1) : $datetmp);
2528 $datetmp = dol_mktime(12, 0, 0, GETPOSTINT('echmonth'), GETPOSTINT('echday'), GETPOSTINT('echyear'));
2529 $datedue = ($datetmp == '' ? -1 : $datetmp);
2530
2531 // Replicate extrafields
2532 $objectsrc->fetch_optionals();
2533 $object->array_options = $objectsrc->array_options;
2534 } else {
2535 $cond_reglement_id = !empty($societe->cond_reglement_supplier_id) ? $societe->cond_reglement_supplier_id : 0;
2536 $mode_reglement_id = !empty($societe->mode_reglement_supplier_id) ? $societe->mode_reglement_supplier_id : 0;
2537 $vat_reverse_charge = (empty($societe) ? '' : $societe->vat_reverse_charge);
2538 $transport_mode_id = !empty($societe->transport_mode_supplier_id) ? $societe->transport_mode_supplier_id : 0;
2539 $fk_account = !empty($societe->fk_account) ? $societe->fk_account : 0;
2540 $datetmp = dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
2541 $dateinvoice = ($datetmp == '' ? (getDolGlobalInt('MAIN_AUTOFILL_DATE') ? '' : -1) : $datetmp);
2542 $datetmp = dol_mktime(12, 0, 0, GETPOSTINT('echmonth'), GETPOSTINT('echday'), GETPOSTINT('echyear'));
2543 $datedue = ($datetmp == '' ? -1 : $datetmp);
2544
2545 if (isModEnabled("multicurrency") && !empty($societe->multicurrency_code)) {
2546 $currency_code = $societe->multicurrency_code;
2547 }
2548 }
2549
2550 // when payment condition is empty (means not override by payment condition form a other object, like third-party), try to use default value
2551 if (empty($cond_reglement_id)) {
2552 $cond_reglement_id = GETPOST("cond_reglement_id");
2553 }
2554
2555 // when payment mode is empty (means not override by payment condition form a other object, like third-party), try to use default value
2556 if (empty($mode_reglement_id)) {
2557 $mode_reglement_id = GETPOST("mode_reglement_id");
2558 }
2559
2560 // If form was posted (but error returned), we must reuse the value posted in priority (standard Dolibarr behaviour)
2561 if (!GETPOST('changecompany')) {
2562 if (GETPOSTISSET('cond_reglement_id')) {
2563 $cond_reglement_id = GETPOSTINT('cond_reglement_id');
2564 }
2565 if (GETPOSTISSET('mode_reglement_id')) {
2566 $mode_reglement_id = GETPOSTINT('mode_reglement_id');
2567 }
2568 if (GETPOSTISSET('cond_reglement_id')) {
2569 $fk_account = GETPOSTINT('fk_account');
2570 }
2571 }
2572
2573 $note_public = $object->getDefaultCreateValueFor('note_public', ((!empty($origin) && !empty($originid) && is_object($objectsrc) && getDolGlobalString('FACTUREFOURN_REUSE_NOTES_ON_CREATE_FROM')) ? $objectsrc->note_public : null));
2574 $note_private = $object->getDefaultCreateValueFor('note_private', ((!empty($origin) && !empty($originid) && is_object($objectsrc) && getDolGlobalString('FACTUREFOURN_REUSE_NOTES_ON_CREATE_FROM')) ? $objectsrc->note_private : null));
2575
2576 if ($origin == 'contrat') {
2577 $langs->load("admin");
2578 $text = $langs->trans("ToCreateARecurringInvoice");
2579 $text .= ' '.$langs->trans("ToCreateARecurringInvoiceGene", $langs->transnoentitiesnoconv("MenuFinancial"), $langs->transnoentitiesnoconv("SupplierBills"), $langs->transnoentitiesnoconv("ListOfTemplates"));
2580 if (!getDolGlobalString('INVOICE_DISABLE_AUTOMATIC_RECURRING_INVOICE')) {
2581 $text .= ' '.$langs->trans("ToCreateARecurringInvoiceGeneAuto", $langs->transnoentitiesnoconv('Module2300Name'));
2582 }
2583 print info_admin($text, 0, 0, '0', 'opacitymedium').'<br>';
2584 }
2585
2586 print '<form name="add" action="'.$_SERVER["PHP_SELF"].'" method="post">';
2587 print '<input type="hidden" name="token" value="'.newToken().'">';
2588 print '<input type="hidden" name="action" value="add">';
2589 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
2590
2591 if (!empty($societe->id) && $societe->id > 0) {
2592 print '<input type="hidden" name="socid" value="'.$societe->id.'">'."\n";
2593 }
2594 print '<input type="hidden" name="origin" value="'.$origin.'">';
2595 print '<input type="hidden" name="originid" value="'.$originid.'">';
2596 if (!empty($currency_tx)) {
2597 print '<input type="hidden" name="originmulticurrency_tx" value="'.$currency_tx.'">';
2598 }
2599 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
2600
2601 print dol_get_fiche_head();
2602
2603 // Call Hook tabContentCreateSupplierInvoice
2604 $parameters = array();
2605 // Note that $action and $object may be modified by hook
2606 $reshook = $hookmanager->executeHooks('tabContentCreateSupplierInvoice', $parameters, $object, $action);
2607 if (empty($reshook)) {
2608 print '<table class="border centpercent">';
2609
2610 // Ref
2611 //print '<tr><td class="titlefieldcreate">'.$langs->trans('Ref').'</td><td>'.$langs->trans('Draft').'</td></tr>';
2612
2613 $exampletemplateinvoice = new FactureFournisseurRec($db);
2614 $invoice_predefined = new FactureFournisseurRec($db);
2615 if (empty($origin) && empty($originid) && $fac_recid > 0) {
2616 $invoice_predefined->fetch($fac_recid);
2617 }
2618
2619 // Third party
2620 print '<tr><td class="fieldrequired">'.$langs->trans('Supplier').'</td>';
2621 print '<td>';
2622
2623 if (!empty($societe->id) && $societe->id > 0 && ($fac_recid <= 0 || !empty($invoice_predefined->frequency))) {
2624 $absolute_discount = $societe->getAvailableDiscounts(null, '', 0, 1);
2625 print $societe->getNomUrl(1, 'supplier');
2626 print '<input type="hidden" name="socid" value="'.$societe->id.'">';
2627 } else {
2628 $filter = '((s.fournisseur:=:1) AND (s.status:=:1))';
2629 print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company(empty($societe->id) ? 0 : $societe->id, 'socid', $filter, 'SelectThirdParty', 1, 0, array(), 0, 'minwidth175 widthcentpercentminusxx maxwidth500');
2630 // reload page to retrieve supplier information
2631 if (!getDolGlobalString('RELOAD_PAGE_ON_SUPPLIER_CHANGE_DISABLED')) {
2632 print '<script type="text/javascript">
2633 $(document).ready(function() {
2634 $("#socid").change(function() {
2635 console.log("We have changed the company - Reload page");
2636 // reload page
2637 $("input[name=action]").val("create");
2638 $("input[name=changecompany]").val("1");
2639 $("form[name=add]").submit();
2640 });
2641 });
2642 </script>';
2643 }
2644 if ($fac_recid <= 0) {
2645 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>';
2646 }
2647 }
2648 print '</td></tr>';
2649
2650 // Overwrite some values if creation of invoice is from a predefined invoice
2651 if (empty($origin) && empty($originid) && $fac_recid > 0) {
2652 $invoice_predefined->fetch($fac_recid);
2653
2654 $dateinvoice = $invoice_predefined->date_when; // To use next gen date by default later
2655 if (empty($projectid)) {
2656 $projectid = $invoice_predefined->fk_project;
2657 }
2658 $cond_reglement_id = $invoice_predefined->cond_reglement_id;
2659 $mode_reglement_id = $invoice_predefined->mode_reglement_id;
2660 $fk_account = $invoice_predefined->fk_account;
2661 $note_public = $invoice_predefined->note_public;
2662 $note_private = $invoice_predefined->note_private;
2663
2664 if (!empty($invoice_predefined->multicurrency_code)) {
2665 $currency_code = $invoice_predefined->multicurrency_code;
2666 }
2667 if (!empty($invoice_predefined->multicurrency_tx)) {
2668 $currency_tx = $invoice_predefined->multicurrency_tx;
2669 }
2670
2671 $sql = 'SELECT r.rowid, r.titre as title, r.total_ttc';
2672 $sql .= ' FROM '.MAIN_DB_PREFIX.'facture_fourn_rec as r';
2673 $sql .= ' WHERE r.fk_soc = '. (int) $invoice_predefined->socid;
2674
2675 $resql = $db->query($sql);
2676 if ($resql) {
2677 $num = $db->num_rows($resql);
2678 $i = 0;
2679
2680 if ($num > 0) {
2681 print '<tr><td>'.$langs->trans('CreateFromRepeatableInvoice').'</td><td>';
2682 //print '<input type="hidden" name="fac_rec" id="fac_rec" value="'.$fac_recid.'">';
2683 print '<select class="flat" id="fac_rec" name="fac_rec">'; // We may want to change the template to use
2684 print '<option value="0" selected></option>';
2685 while ($i < $num) {
2686 $objp = $db->fetch_object($resql);
2687 print '<option value="'.$objp->rowid.'"';
2688 if ($fac_recid == $objp->rowid) {
2689 print ' selected';
2690 $exampletemplateinvoice->fetch($fac_recid);
2691 }
2692 print '>'.$objp->title.' ('.price($objp->total_ttc).' '.$langs->trans("TTC").')</option>';
2693 $i++;
2694 }
2695 print '</select>';
2696 // Option to reload page to retrieve customer information. Note, this clear other input
2697 if (!getDolGlobalString('RELOAD_PAGE_ON_TEMPLATE_CHANGE_DISABLED')) {
2698 print '<script type="text/javascript">
2699 $(document).ready(function() {
2700 $("#fac_rec").change(function() {
2701 console.log("We have changed the template invoice - Reload page");
2702 // reload page
2703 $("input[name=action]").val("create");
2704 $("form[name=add]").submit();
2705 });
2706 });
2707 </script>';
2708 }
2709 print '</td></tr>';
2710 }
2711 $db->free($resql);
2712 } else {
2714 }
2715 }
2716
2717 print '<tr><td class="tdtop fieldrequired">'.$langs->trans('Type').'</td><td>';
2718
2719 print '<div class="tagtable">'."\n";
2720
2721 // Standard invoice
2722 print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2723 $tmp = '<input type="radio" id="radio_standard" name="type" value="0"'.(GETPOSTINT('type') ? '' : 'checked').'> ';
2724 $desc = $form->textwithpicto($tmp.'<label for="radio_standard">'.$langs->trans("InvoiceStandardAsk").'</label>', $langs->transnoentities("InvoiceStandardDesc"), 1, 'help', '', 0, 3);
2725 print $desc;
2726 print '</div></div>';
2727
2728 if (empty($origin) || (($origin == 'supplier_proposal' || $origin == 'order_supplier' || $origin == 'reception') && !empty($originid))) {
2729 // Deposit - Down payment
2730 if (!getDolGlobalString('INVOICE_DISABLE_DEPOSIT')) {
2731 print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2732 $tmp = '<input type="radio" id="radio_deposit" name="type" value="3"' . (GETPOSTINT('type') == 3 ? ' checked' : '') . '> ';
2733 print '<script type="text/javascript">
2734 jQuery(document).ready(function() {
2735 jQuery("#typestandardinvoice, #valuestandardinvoice").click(function() {
2736 jQuery("#radio_standard").prop("checked", true);
2737 });
2738 jQuery("#typedeposit, #valuedeposit").click(function() {
2739 jQuery("#radio_deposit").prop("checked", true);
2740 });
2741 jQuery("#typedeposit").change(function() {
2742 console.log("We change type of down payment");
2743 jQuery("#radio_deposit").prop("checked", true);
2744 setRadioForTypeOfInvoice();
2745 });
2746 jQuery("#radio_standard, #radio_deposit, #radio_replacement, #radio_template").change(function() {
2747 setRadioForTypeOfInvoice();
2748 });
2749 function setRadioForTypeOfInvoice() {
2750 console.log("Change radio");
2751 if (jQuery("#radio_deposit").prop("checked") && (jQuery("#typedeposit").val() == \'amount\' || jQuery("#typedeposit").val() == \'variable\')) {
2752 jQuery(".checkforselect").prop("disabled", true);
2753 jQuery(".checkforselect").prop("checked", false);
2754 } else {
2755 jQuery(".checkforselect").prop("disabled", false);
2756 jQuery(".checkforselect").prop("checked", true);
2757 }
2758 }
2759 });
2760 </script>';
2761
2762 $tmp = $tmp.'<label for="radio_deposit" >'.$langs->trans("InvoiceDeposit").'</label>';
2763 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
2764 $desc = $form->textwithpicto($tmp, $langs->transnoentities("InvoiceDepositDesc"), 1, 'help', '', 0, 3);
2765 print '<table class="nobordernopadding"><tr>';
2766 print '<td>';
2767 print $desc;
2768 print '</td>';
2769 if ($origin == 'supplier_proposal' || $origin == 'order_supplier' || $origin == 'reception') {
2770 print '<td class="nowrap" style="padding-left: 15px">';
2771 $arraylist = array(
2772 'amount' => $langs->transnoentitiesnoconv('FixAmount', $langs->transnoentitiesnoconv('Deposit')),
2773 'variable' => $langs->transnoentitiesnoconv('VarAmountOneLine', $langs->transnoentitiesnoconv('Deposit')),
2774 'variablealllines' => $langs->transnoentitiesnoconv('VarAmountAllLines')
2775 );
2776 $typedeposit = GETPOST('typedeposit', 'aZ09');
2777 $valuedeposit = GETPOST('valuedeposit', 'int');
2778 $deposit_percent = null;
2779 if ($origin == 'reception') {
2780 // try to get from source of reception (supplier order)
2781 if (!isset($objectsrc->origin_object)) {
2782 $objectsrc->fetch_origin();
2783 }
2784 if (!empty($objectsrc->origin_object)) {
2785 $deposit_percent = $objectsrc->origin_object->deposit_percent;
2786 }
2787 } elseif (!empty($objectsrc->deposit_percent)) {
2788 $deposit_percent = $objectsrc->deposit_percent;
2789 }
2790 if (empty($typedeposit) && !empty($deposit_percent)) {
2791 $origin_payment_conditions_deposit_percent = getDictionaryValue('c_payment_term', 'deposit_percent', $objectsrc->cond_reglement_id);
2792 if (!empty($origin_payment_conditions_deposit_percent)) {
2793 $typedeposit = 'variable';
2794 }
2795 }
2796 if (empty($valuedeposit) && $typedeposit == 'variable' && !empty($deposit_percent)) {
2797 $valuedeposit = $deposit_percent;
2798 }
2799 print $form->selectarray('typedeposit', $arraylist, $typedeposit, 0, 0, 0, '', 1);
2800 print '</td>';
2801 print '<td class="nowrap" style="padding-left: 5px">';
2802 print '<span class="opacitymedium paddingleft">'.$langs->trans("AmountOrPercent").'</span><input type="text" id="valuedeposit" name="valuedeposit" class="width75 right" value="' . $valuedeposit . '"/>';
2803 print '</td>';
2804 }
2805 print '</tr></table>';
2806
2807 print '</div></div>';
2808 }
2809 }
2810
2811 /* Not yet supported for supplier
2812 if ($societe->id > 0)
2813 {
2814 // Replacement
2815 if (empty($conf->global->INVOICE_DISABLE_REPLACEMENT))
2816 {
2817 // Type invoice
2818 $facids = $facturestatic->list_replacable_supplier_invoices($societe->id);
2819 if ($facids < 0) {
2820 dol_print_error($db, $facturestatic->error, $facturestatic->errors);
2821 exit();
2822 }
2823 $options = "";
2824 foreach ($facids as $facparam)
2825 {
2826 $options .= '<option value="' . $facparam ['id'] . '"';
2827 if ($facparam ['id'] == GETPOST('fac_replacement') {
2828 $options .= ' selected';
2829 }
2830 $options .= '>' . $facparam ['ref'];
2831 $options .= ' (' . $facturestatic->LibStatut(0, $facparam ['status']) . ')';
2832 $options .= '</option>';
2833 }
2834
2835 print '<!-- replacement line -->';
2836 print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2837 $tmp='<input type="radio" name="type" id="radio_replacement" value="1"' . (GETPOSTINT('type') == 1 ? ' checked' : '');
2838 if (! $options) $tmp.=' disabled';
2839 $tmp.='> ';
2840 print '<script type="text/javascript">
2841 jQuery(document).ready(function() {
2842 jQuery("#fac_replacement").change(function() {
2843 jQuery("#radio_replacement").prop("checked", true);
2844 });
2845 });
2846 </script>';
2847 $text = $tmp.$langs->trans("InvoiceReplacementAsk") . ' ';
2848 $text .= '<select class="flat" name="fac_replacement" id="fac_replacement"';
2849 if (! $options)
2850 $text .= ' disabled';
2851 $text .= '>';
2852 if ($options) {
2853 $text .= '<option value="-1">&nbsp;</option>';
2854 $text .= $options;
2855 } else {
2856 $text .= '<option value="-1">' . $langs->trans("NoReplacableInvoice") . '</option>';
2857 }
2858 $text .= '</select>';
2859 $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceReplacementDesc"), 1, 'help', '', 0, 3);
2860 print $desc;
2861 print '</div></div>';
2862 }
2863 }
2864 else
2865 {
2866 print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2867 $tmp='<input type="radio" name="type" id="radio_replacement" value="0" disabled> ';
2868 $text = $tmp.$langs->trans("InvoiceReplacement") . ' ';
2869 $text.= '('.$langs->trans("YouMustCreateInvoiceFromSupplierThird").') ';
2870 $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceReplacementDesc"), 1, 'help', '', 0, 3);
2871 print $desc;
2872 print '</div></div>';
2873 }
2874 */
2875
2876 if (empty($origin)) {
2877 if (!empty($societe->id) && $societe->id > 0) {
2878 // Credit note
2879 if (!getDolGlobalString('INVOICE_DISABLE_CREDIT_NOTE')) {
2880 // Show link for credit note
2881 $facids = $facturestatic->list_qualified_avoir_supplier_invoices($societe->id);
2882 if ($facids < 0) {
2883 dol_print_error($db, $facturestatic->error, $facturestatic->errors);
2884 exit;
2885 }
2886 $optionsav = "";
2887 $newinvoice_static = new FactureFournisseur($db);
2888 foreach ($facids as $key => $valarray) {
2889 $newinvoice_static->id = $key;
2890 $newinvoice_static->ref = $valarray ['ref'];
2891 $newinvoice_static->status = $valarray ['status'];
2892 $newinvoice_static->statut = $valarray ['status'];
2893 $newinvoice_static->type = $valarray ['type'];
2894 $newinvoice_static->paid = $valarray ['paye'];
2895 $newinvoice_static->paye = $valarray ['paye'];
2896
2897 $optionsav .= '<option value="'.$key.'"';
2898 if ($key == GETPOSTINT('fac_avoir')) {
2899 $optionsav .= ' selected';
2900 // pre-fill extra fields with selected source invoice
2901 $newinvoice_static->fetch_optionals($key);
2902 $object->array_options = $newinvoice_static->array_options;
2903 }
2904 $optionsav .= '>';
2905 $optionsav .= $newinvoice_static->ref;
2906 $optionsav .= ' ('.$newinvoice_static->getLibStatut(1, $valarray ['paymentornot']).')';
2907 $optionsav .= '</option>';
2908 }
2909
2910 print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2911 $tmp = '<input type="radio" id="radio_creditnote" name="type" value="2"'.(GETPOSTINT('type') == 2 ? ' checked' : '');
2912 if (!$optionsav && !getDolGlobalString('INVOICE_CREDIT_NOTE_STANDALONE')) {
2913 $tmp .= ' disabled';
2914 }
2915 $tmp .= '> ';
2916 // Show credit note options only if we checked credit note
2917 print '<script type="text/javascript">
2918 jQuery(document).ready(function() {
2919 if (! jQuery("#radio_creditnote").is(":checked"))
2920 {
2921 jQuery("#credit_note_options").hide();
2922 }
2923 jQuery("#radio_creditnote").click(function() {
2924 jQuery("#credit_note_options").show();
2925 });
2926 jQuery("#radio_standard, #radio_replacement, #radio_deposit").click(function() {
2927 jQuery("#credit_note_options").hide();
2928 });
2929 });
2930 </script>';
2931 $text = $tmp.'<label for="radio_creditnote">'.$langs->transnoentities("InvoiceAvoirAsk").'</label> ';
2932 // $text.='<input type="text" value="">';
2933 $text .= '<select class="flat valignmiddle" name="fac_avoir" id="fac_avoir"';
2934 if (!$optionsav) {
2935 $text .= ' disabled';
2936 }
2937 $text .= '>';
2938 if ($optionsav) {
2939 $text .= '<option value="-1"></option>';
2940 $text .= $optionsav;
2941 } else {
2942 $text .= '<option value="-1">'.$langs->trans("NoInvoiceToCorrect").'</option>';
2943 }
2944 $text .= '</select>';
2945 $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceAvoirDesc"), 1, 'help', '', 0, 3);
2946 print $desc;
2947
2948 print '<div id="credit_note_options" class="clearboth">';
2949 print '&nbsp;&nbsp;&nbsp; <input type="checkbox" name="invoiceAvoirWithLines" id="invoiceAvoirWithLines" value="1" onclick="if($(this).is(\':checked\') ) { $(\'#radio_creditnote\').prop(\'checked\', true); $(\'#invoiceAvoirWithPaymentRestAmount\').removeAttr(\'checked\'); }" '.(GETPOSTINT('invoiceAvoirWithLines') > 0 ? 'checked' : '').' /> ';
2950 print '<label for="invoiceAvoirWithLines">'.$langs->trans('invoiceAvoirWithLines')."</label>";
2951 print '<br>&nbsp;&nbsp;&nbsp; <input type="checkbox" name="invoiceAvoirWithPaymentRestAmount" id="invoiceAvoirWithPaymentRestAmount" value="1" onclick="if($(this).is(\':checked\') ) { $(\'#radio_creditnote\').prop(\'checked\', true); $(\'#invoiceAvoirWithLines\').removeAttr(\'checked\'); }" '.(GETPOSTINT('invoiceAvoirWithPaymentRestAmount') > 0 ? 'checked' : '').' /> ';
2952 print '<label for="invoiceAvoirWithPaymentRestAmount">'.$langs->trans('invoiceAvoirWithPaymentRestAmount')."</label>";
2953 print '</div>';
2954
2955 print '</div></div>';
2956 }
2957 } else {
2958 print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2959 if (!getDolGlobalString('INVOICE_CREDIT_NOTE_STANDALONE')) {
2960 $tmp = '<input type="radio" name="type" id="radio_creditnote" value="0" disabled> ';
2961 } else {
2962 $tmp = '<input type="radio" name="type" id="radio_creditnote" value="2"> ';
2963 }
2964 $text = $tmp.$langs->trans("InvoiceAvoir").' ';
2965 $text .= '<span class="opacitymedium">('.$langs->trans("YouMustCreateInvoiceFromSupplierThird").')</span> ';
2966 $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceAvoirDesc"), 1, 'help', '', 0, 3);
2967 print $desc;
2968 print '</div></div>'."\n";
2969 }
2970 }
2971
2972 print '</div><br>';
2973
2974 print '</td></tr>';
2975
2976
2977 // Ref supplier
2978 print '<tr><td class="fieldrequired">';
2979 print $form->textwithpicto($langs->trans('RefSupplierBill'), $langs->trans("RefOfOnVendorSide", $langs->trans("SupplierBill"))).'</td><td>';
2980 print '<input name="ref_supplier" value="'.(GETPOSTISSET('ref_supplier') ? GETPOST('ref_supplier') : (!empty($objectsrc->ref_supplier) ? $objectsrc->ref_supplier : '')).'" type="text" spellcheck="false"';
2981 if (!empty($societe->id) && $societe->id > 0) {
2982 print ' autofocus';
2983 }
2984 print '></td>';
2985 print '</tr>';
2986
2987
2988 // Invoice Subtype
2989 if (getDolGlobalInt('INVOICE_SUBTYPE_ENABLED')) {
2990 print '<tr><td class="fieldrequired">'.$langs->trans('InvoiceSubtype').'</td><td colspan="2">';
2991 print $form->getSelectInvoiceSubtype(GETPOSTINT('subtype'), 'subtype', 1, 0, '');
2992 print '</td></tr>';
2993 }
2994
2995 if (!empty($societe->id) && $societe->id > 0) {
2996 // Discounts for third party
2997 print '<tr><td>'.$langs->trans('Discounts').'</td><td>';
2998
2999 $thirdparty = $societe;
3000 $discount_type = 1;
3001 $backtopage = urlencode($_SERVER["PHP_SELF"].'?socid='.$societe->id.'&action='.$action.'&origin='.GETPOST('origin').'&originid='.GETPOST('originid'));
3002 include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
3003
3004 print '</td></tr>';
3005 }
3006
3007 // Label
3008 print '<tr><td>'.$langs->trans('Label').'</td><td><input class="minwidth300" name="label" value="'.dol_escape_htmltag(GETPOST('label')).'" type="text"></td></tr>';
3009
3010
3011 // Date invoice
3012 print '<tr><td class="fieldrequired">'.$langs->trans('DateInvoice').'</td><td>';
3013 print img_picto('', 'action', 'class="pictofixedwidth"');
3014 print $form->selectDate($dateinvoice ? (int) $dateinvoice : '', '', 0, 0, 0, "add", 1, 1);
3015 print '</td></tr>';
3016
3017 // Payment term
3018 print '<tr><td class="nowrap">'.$langs->trans('PaymentConditionsShort').'</td><td>';
3019 print img_picto('', 'payment', 'class="pictofixedwidth"');
3020 print $form->getSelectConditionsPaiements($cond_reglement_id, 'cond_reglement_id', -1, 1, 0, 'maxwidth200 widthcentpercentminusx');
3021 print '</td></tr>';
3022
3023 // Due date
3024 print '<tr><td>'.$langs->trans('DateMaxPayment').'</td><td>';
3025 print img_picto('', 'action', 'class="pictofixedwidth"');
3026 print $form->selectDate($datedue, 'ech', 0, 0, 0, "add", 1, 1);
3027 print '</td></tr>';
3028
3029 // Payment mode
3030 print '<tr><td>'.$langs->trans('PaymentMode').'</td><td>';
3031 print img_picto('', 'bank', 'class="pictofixedwidth"');
3032 $form->select_types_paiements((string) $mode_reglement_id, 'mode_reglement_id', 'DBIT', 0, 1, 0, 0, 1, 'maxwidth200 widthcentpercentminusx');
3033 print '</td></tr>';
3034
3035 // Bank Account
3036 if (isModEnabled("bank")) {
3037 print '<tr><td>'.$langs->trans('BankAccount').'</td><td>';
3038 // when bank account is empty (means not override by payment mode form a other object, like third-party), try to use default value
3039 print img_picto('', 'bank_account', 'class="pictofixedwidth"').$form->select_comptes((int) $fk_account, 'fk_account', 0, '', 1, '', 0, 'maxwidth200 widthcentpercentminusx', 1);
3040 print '</td></tr>';
3041 }
3042
3043 // Project
3044 if (isModEnabled('project')) {
3045 $formproject = new FormProjets($db);
3046
3047 $langs->load('projects');
3048 print '<tr><td>'.$langs->trans('Project').'</td><td>';
3049 print img_picto('', 'project', 'class="pictofixedwidth"').$formproject->select_projects((!getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') ? $societe->id : -1), $projectid, 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500 widthcentpercentminusxx');
3050 print ' <a href="'.DOL_URL_ROOT.'/projet/card.php?socid='.(!empty($soc->id) ? $soc->id : 0).'&action=create&status=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create&socid='.(!empty($soc->id) ? $soc->id : 0).($fac_recid > 0 ? '&fac_rec='.$fac_recid : '')).'"><span class="fa fa-plus-circle valignmiddle" title="'.$langs->trans("AddProject").'"></span></a>';
3051 print '</td></tr>';
3052 }
3053
3054 // Incoterms
3055 if (isModEnabled('incoterm')) {
3056 print '<tr>';
3057 print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), !empty($objectsrc->label_incoterms) ? $objectsrc->label_incoterms : '', 1).'</label></td>';
3058 print '<td colspan="3" class="maxwidthonsmartphone">';
3059 print img_picto('', 'incoterm', 'class="pictofixedwidth"');
3060 print $form->select_incoterms(GETPOSTISSET('incoterm_id') ? GETPOST('incoterm_id', 'alphanohtml') : (!empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : ''), GETPOSTISSET('location_incoterms') ? GETPOST('location_incoterms', 'alphanohtml') : (!empty($objectsrc->location_incoterms) ? $objectsrc->location_incoterms : ''));
3061 print '</td></tr>';
3062 }
3063
3064 // Vat reverse-charge by default
3065 if (getDolGlobalString('ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE')) {
3066 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
3067 print '<tr><td>' . $langs->trans('VATReverseCharge') . '</td><td>';
3068 // Try to propose to use VAT reverse charge even if the VAT reverse charge is not activated in the supplier card, if this corresponds to the context of use, the activation is proposed
3069 if (GETPOSTISSET('vat_reverse_charge')) { // Check if form was submitted previously
3070 $vat_reverse_charge = (GETPOST('vat_reverse_charge', 'alpha') == 'on' || GETPOST('vat_reverse_charge', 'alpha') == '1') ? 1 : 0;
3071 } elseif ($vat_reverse_charge == 1 || $societe->vat_reverse_charge == 1 || ($societe->country_code != 'FR' && isInEEC($societe) && !empty($societe->tva_intra))) {
3072 $vat_reverse_charge = 1;
3073 } else {
3074 $vat_reverse_charge = 0;
3075 }
3076
3077 print '<input type="checkbox" name="vat_reverse_charge"'. (!empty($vat_reverse_charge) ? ' checked ' : '') . '>';
3078 print '</td></tr>';
3079 }
3080
3081 // Multicurrency
3082 if (isModEnabled("multicurrency")) {
3083 print '<tr>';
3084 print '<td>'.$form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0).'</td>';
3085 print '<td class="maxwidthonsmartphone">';
3086 print img_picto('', 'currency', 'class="pictofixedwidth"');
3087 $used_currency_code = $currency_code;
3088 if (!GETPOST('changecompany')) {
3089 $used_currency_code = GETPOSTISSET('multicurrency_code') ? GETPOST('multicurrency_code', 'alpha') : $currency_code;
3090 }
3091 print $form->selectMultiCurrency($used_currency_code, 'multicurrency_code');
3092 print '</td></tr>';
3093 }
3094
3095 // Help of substitution key
3096 $htmltext = '';
3097 if ($fac_recid > 0) {
3098 $dateexample = $dateinvoice;
3099 if (empty($dateexample)) {
3100 $dateexample = dol_now();
3101 }
3102 $substitutionarray = array(
3103 '__TOTAL_HT__' => $langs->trans("AmountHT").' ('.$langs->trans("Example").': '.price($exampletemplateinvoice->total_ht).')',
3104 '__TOTAL_TTC__' => $langs->trans("AmountTTC").' ('.$langs->trans("Example").': '.price($exampletemplateinvoice->total_ttc).')',
3105 '__INVOICE_PREVIOUS_MONTH__' => $langs->trans("PreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%m').')',
3106 '__INVOICE_MONTH__' => $langs->trans("MonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%m').')',
3107 '__INVOICE_NEXT_MONTH__' => $langs->trans("NextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%m').')',
3108 '__INVOICE_PREVIOUS_MONTH_TEXT__' => $langs->trans("TextPreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%B').')',
3109 '__INVOICE_MONTH_TEXT__' => $langs->trans("TextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%B').')',
3110 '__INVOICE_NEXT_MONTH_TEXT__' => $langs->trans("TextNextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%B').')',
3111 '__INVOICE_PREVIOUS_YEAR__' => $langs->trans("PreviousYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'y'), '%Y').')',
3112 '__INVOICE_YEAR__' => $langs->trans("YearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample, '%Y').')',
3113 '__INVOICE_NEXT_YEAR__' => $langs->trans("NextYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'y'), '%Y').')'
3114 );
3115
3116 $htmltext = '<i>'.$langs->trans("FollowingConstantsWillBeSubstituted").':<br>';
3117 foreach ($substitutionarray as $key => $val) {
3118 $htmltext .= $key.' = '.$langs->trans($val).'<br>';
3119 }
3120 $htmltext .= '</i>';
3121 }
3122
3123 // Intracomm report
3124 if (isModEnabled('intracommreport')) {
3125 $langs->loadLangs(array("intracommreport"));
3126 print '<!-- If module intracomm on -->'."\n";
3127 print '<tr><td>'.$langs->trans('IntracommReportTransportMode').'</td><td>';
3128 $form->selectTransportMode(GETPOSTISSET('transport_mode_id') ? GETPOST('transport_mode_id') : $transport_mode_id, 'transport_mode_id');
3129 print '</td></tr>';
3130 }
3131
3132 if (empty($reshook)) {
3133 print $object->showOptionals($extrafields, 'create');
3134 }
3135
3136 // Categories
3137 if (isModEnabled("category")) {
3138 print '<tr><td>'.$langs->trans("Categories").'</td><td colspan="3">';
3139 print $form->selectCategories(Categorie::TYPE_SUPPLIER_INVOICE, 'categories', $object);
3140 print "</td></tr>";
3141 }
3142
3143 // Public note
3144 print '<tr><td>'.$langs->trans('NotePublic').'</td>';
3145 print '<td>';
3146 $doleditor = new DolEditor('note_public', (GETPOSTISSET('note_public') ? GETPOST('note_public', 'restricthtml') : $note_public), '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
3147 print $doleditor->Create(1);
3148 print '</td>';
3149 // print '<td><textarea name="note" wrap="soft" cols="60" rows="'.ROWS_5.'"></textarea></td>';
3150 print '</tr>';
3151
3152 // Private note
3153 print '<tr><td>'.$langs->trans('NotePrivate').'</td>';
3154 print '<td>';
3155 $doleditor = new DolEditor('note_private', (GETPOSTISSET('note_private') ? GETPOST('note_private', 'restricthtml') : $note_private), '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
3156 print $doleditor->Create(1);
3157 print '</td>';
3158 // print '<td><textarea name="note" wrap="soft" cols="60" rows="'.ROWS_5.'"></textarea></td>';
3159 print '</tr>';
3160
3161
3162 if (!empty($objectsrc) && $classname !== null) {
3163 print "\n<!-- ".$classname." info -->";
3164 print "\n";
3165 print '<input type="hidden" name="amount" value="'.$objectsrc->total_ht.'">'."\n";
3166 print '<input type="hidden" name="total" value="'.$objectsrc->total_ttc.'">'."\n";
3167 print '<input type="hidden" name="tva" value="'.$objectsrc->total_tva.'">'."\n";
3168 print '<input type="hidden" name="origin" value="'.$objectsrc->element.'">';
3169 print '<input type="hidden" name="originid" value="'.$objectsrc->id.'">';
3170
3171 $txt = $langs->trans($classname);
3172 if ($classname == 'CommandeFournisseur') {
3173 $langs->load('orders');
3174 $txt = $langs->trans("SupplierOrder");
3175 }
3176 print '<tr><td>'.$txt.'</td><td>'.$objectsrc->getNomUrl(1);
3177 // We check if Origin document (id and type is known) has already at least one invoice attached to it
3178 $objectsrc->fetchObjectLinked($originid, $origin, null, 'invoice_supplier');
3179
3180 if (isset($objectsrc->linkedObjects['invoice_supplier'])) {
3181 $invoice_supplier = $objectsrc->linkedObjects['invoice_supplier'];
3182 } else {
3183 $invoice_supplier = [];
3184 }
3185 '@phan-var-force null|FactureFournisseur[] $invoice_supplier';
3186
3187 // count function need a array as argument (Note: the array must implement Countable too)
3188 if (is_array($invoice_supplier)) {
3189 $cntinvoice = count($invoice_supplier);
3190
3191 if ($cntinvoice >= 1) {
3192 setEventMessages('WarningBillExist', null, 'warnings');
3193 echo ' ('.$langs->trans('LatestRelatedBill').end($invoice_supplier)->getNomUrl(1).')';
3194 }
3195 }
3196
3197 print '</td></tr>';
3198 print '<tr><td>'.$langs->trans('AmountHT').'</td><td>'.price($objectsrc->total_ht).'</td></tr>';
3199 print '<tr><td>'.$langs->trans('AmountVAT').'</td><td>'.price($objectsrc->total_tva)."</td></tr>";
3200 if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) { //Localtax1
3201 print '<tr><td>'.$langs->transcountry("AmountLT1", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax1)."</td></tr>";
3202 }
3203
3204 if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) { //Localtax2
3205 print '<tr><td>'.$langs->transcountry("AmountLT2", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax2)."</td></tr>";
3206 }
3207 print '<tr><td>'.$langs->trans('AmountTTC').'</td><td>'.price($objectsrc->total_ttc)."</td></tr>";
3208
3209 if (isModEnabled("multicurrency")) {
3210 print '<tr><td>'.$langs->trans('MulticurrencyAmountHT').'</td><td>'.price($objectsrc->multicurrency_total_ht).'</td></tr>';
3211 print '<tr><td>'.$langs->trans('MulticurrencyAmountVAT').'</td><td>'.price($objectsrc->multicurrency_total_tva)."</td></tr>";
3212 print '<tr><td>'.$langs->trans('MulticurrencyAmountTTC').'</td><td>'.price($objectsrc->multicurrency_total_ttc)."</td></tr>";
3213 }
3214 }
3215
3216 // Other options
3217 $parameters = array();
3218 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
3219 print $hookmanager->resPrint;
3220
3221
3222 print "</table>\n";
3223 }
3224
3225 print dol_get_fiche_end();
3226
3227 print $form->buttonsSaveCancel("CreateDraft");
3228
3229 // Show origin lines
3230 if (!empty($objectsrc)) {
3231 print '<br>';
3232
3233 $title = $langs->trans('ProductsAndServices');
3234 print load_fiche_titre($title);
3235
3236 print '<div class="div-table-responsive-no-min">';
3237 print '<table class="noborder centpercent">';
3238
3239 $objectsrc->printOriginLinesList('', $selectedLines);
3240
3241 print '</table>';
3242 print '</div>';
3243 }
3244
3245 print "</form>\n";
3246} else {
3247 if ($id > 0 || !empty($ref)) {
3248 //
3249 // View or edit mode
3250 //
3251 $now = dol_now();
3252
3253 $result = $object->fetch($id, $ref);
3254 if ($result <= 0) {
3255 recordNotFound('', 0);
3256 }
3257
3258 $result = $object->fetch_thirdparty();
3259 if ($result < 0) {
3260 dol_print_error($db, $object->error, $object->errors);
3261 exit;
3262 }
3263
3264 $societe = $object->thirdparty;
3265
3266 $totalpaid = $object->getSommePaiement();
3267 $totalcreditnotes = $object->getSumCreditNotesUsed();
3268 $totaldeposits = $object->getSumDepositsUsed();
3269 // print "totalpaid=".$totalpaid." totalcreditnotes=".$totalcreditnotes." totaldeposts=".$totaldeposits."
3270 // selleruserrevenuestamp=".$selleruserevenustamp;
3271
3272 // We can also use bcadd to avoid pb with floating points
3273 // For example print 239.2 - 229.3 - 9.9; does not return 0.
3274 // $resteapayer=bcadd($object->total_ttc,$totalpaid,$conf->global->MAIN_MAX_DECIMALS_TOT);
3275 // $resteapayer=bcadd($resteapayer,$totalavoir,$conf->global->MAIN_MAX_DECIMALS_TOT);
3276 $resteapayer = price2num($object->total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits, 'MT');
3277
3278 // Multicurrency
3279 $multicurrency_resteapayer = 0;
3280 if (isModEnabled("multicurrency")) {
3281 $multicurrency_totalpaid = $object->getSommePaiement(1);
3282 $multicurrency_totalcreditnotes = $object->getSumCreditNotesUsed(1);
3283 $multicurrency_totaldeposits = $object->getSumDepositsUsed(1);
3284 $multicurrency_resteapayer = price2num($object->multicurrency_total_ttc - $multicurrency_totalpaid - $multicurrency_totalcreditnotes - $multicurrency_totaldeposits, 'MT');
3285 // Code to fix case of corrupted data
3286 // TODO We should not need this. Also data comes from not reliable value of $object->multicurrency_total_ttc that may be wrong if it was
3287 // calculated by summing lines that were in a currency for some of them and into another for others (lines from discount/down payment into another currency for example)
3288 if ($resteapayer == 0 && $multicurrency_resteapayer != 0 && $object->multicurrency_code != $conf->currency) {
3289 $resteapayer = price2num((float) $multicurrency_resteapayer / $object->multicurrency_tx, 'MT');
3290 }
3291 }
3292
3293 if ($object->paid) {
3294 $resteapayer = 0;
3295 }
3296 $resteapayeraffiche = $resteapayer;
3297
3298 if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) { // Never use this
3299 $filterabsolutediscount = "fk_invoice_supplier_source IS NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
3300 $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
3301 } else {
3302 $filterabsolutediscount = "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')";
3303 $filtercreditnote = "fk_invoice_supplier_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS PAID)%')";
3304 }
3305
3306 $absolute_discount = $societe->getAvailableDiscounts(null, $filterabsolutediscount, 0, 1);
3307 $absolute_creditnote = $societe->getAvailableDiscounts(null, $filtercreditnote, 0, 1);
3308 $absolute_discount = price2num($absolute_discount, 'MT');
3309 $absolute_creditnote = price2num($absolute_creditnote, 'MT');
3310
3311 // View card
3312
3313 $objectidnext = $object->getIdReplacingInvoice();
3314
3315 $head = facturefourn_prepare_head($object);
3316 $titre = $langs->trans('SupplierInvoice');
3317
3318 print dol_get_fiche_head($head, 'card', $titre, -1, 'supplier_invoice', 0, '', '', 0, '', 1);
3319
3320 $formconfirm = '';
3321
3322 // Confirmation de la conversion de l'avoir en reduc
3323 if ($action == 'converttoreduc') {
3324 $type_fac = '';
3326 $type_fac = 'ExcessPaid';
3327 } elseif ($object->type == FactureFournisseur::TYPE_CREDIT_NOTE) {
3328 $type_fac = 'CreditNote';
3329 } elseif ($object->type == FactureFournisseur::TYPE_DEPOSIT) {
3330 $type_fac = 'Deposit';
3331 }
3332 $text = $langs->trans('ConfirmConvertToReducSupplier', strtolower($langs->transnoentities($type_fac)));
3333 $text .= '<br>'.$langs->trans('ConfirmConvertToReducSupplier2');
3334 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?facid='.$object->id, $langs->trans('ConvertToReduc'), $text, 'confirm_converttoreduc', '', "yes", 2);
3335 }
3336
3337 // Clone confirmation
3338 if ($action == 'clone') {
3339 // Create an array for form
3340 $formquestion = array(
3341 array('type' => 'text', 'name' => 'newsupplierref', 'label' => $langs->trans("RefSupplierBill"), 'value' => $langs->trans("CopyOf").' '.$object->ref_supplier),
3342 array('type' => 'date', 'name' => 'newdate', 'label' => $langs->trans("Date"), 'value' => dol_now())
3343 );
3344 // Ask confirmation to clone
3345 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneInvoice', $object->ref), 'confirm_clone', $formquestion, 'yes', 1, 0);
3346 }
3347
3348 // Confirmation of validation
3349 if ($action == 'valid') {
3350 // We check if number is temporary number
3351 if (preg_match('/^[\‍(]?PROV/i', $object->ref) || empty($object->ref)) {
3352 // empty should not happened, but when it occurs, the test save life
3353 $numref = $object->getNextNumRef($societe);
3354 } else {
3355 $numref = (string) $object->ref;
3356 }
3357
3358 if ($numref < 0) {
3359 setEventMessages($object->error, $object->errors, 'errors');
3360 $action = '';
3361 } else {
3362 $text = $langs->trans('ConfirmValidateBill', $numref);
3363 /*if (isModEnabled('notification'))
3364 {
3365 require_once DOL_DOCUMENT_ROOT .'/core/class/notify.class.php';
3366 $notify=new Notify($db);
3367 $text.='<br>';
3368 $text.=$notify->confirmMessage('BILL_SUPPLIER_VALIDATE',$object->socid, $object);
3369 }*/
3370 $formquestion = array();
3371
3372 $qualified_for_stock_change = 0;
3373 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
3374 $qualified_for_stock_change = $object->hasProductsOrServices(2);
3375 } else {
3376 $qualified_for_stock_change = $object->hasProductsOrServices(1);
3377 }
3378
3379 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_BILL') && $qualified_for_stock_change) {
3380 $langs->load("stocks");
3381 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
3382 $formproduct = new FormProduct($db);
3383 $warehouse = new Entrepot($db);
3384 $warehouse_array = $warehouse->list_array();
3385 if (count($warehouse_array) == 1) {
3386 $label = $object->type == FactureFournisseur::TYPE_CREDIT_NOTE ? $langs->trans("WarehouseForStockDecrease", current($warehouse_array)) : $langs->trans("WarehouseForStockIncrease", current($warehouse_array));
3387 $value = '<input type="hidden" id="idwarehouse" name="idwarehouse" value="'.key($warehouse_array).'">';
3388 } else {
3389 $label = $object->type == FactureFournisseur::TYPE_CREDIT_NOTE ? $langs->trans("SelectWarehouseForStockDecrease") : $langs->trans("SelectWarehouseForStockIncrease");
3390 $value = $formproduct->selectWarehouses(GETPOST('idwarehouse') ? GETPOST('idwarehouse') : 'ifone', 'idwarehouse', '', 1);
3391 }
3392 $formquestion = array(
3393 array('type' => 'other', 'name' => 'idwarehouse', 'label' => $label, 'value' => $value)
3394 );
3395 }
3396
3397 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateBill'), $text, 'confirm_valid', $formquestion, 1, 1);
3398 }
3399 }
3400
3401 // Confirmation edit (back to draft)
3402 if ($action == 'edit') {
3403 $formquestion = array();
3404
3405 $qualified_for_stock_change = 0;
3406 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
3407 $qualified_for_stock_change = $object->hasProductsOrServices(2);
3408 } else {
3409 $qualified_for_stock_change = $object->hasProductsOrServices(1);
3410 }
3411 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_BILL') && $qualified_for_stock_change) {
3412 $langs->load("stocks");
3413 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
3414 $formproduct = new FormProduct($db);
3415 $warehouse = new Entrepot($db);
3416 $warehouse_array = $warehouse->list_array();
3417 if (count($warehouse_array) == 1) {
3418 $label = $object->type == FactureFournisseur::TYPE_CREDIT_NOTE ? $langs->trans("WarehouseForStockIncrease", current($warehouse_array)) : $langs->trans("WarehouseForStockDecrease", current($warehouse_array));
3419 $value = '<input type="hidden" id="idwarehouse" name="idwarehouse" value="'.key($warehouse_array).'">';
3420 } else {
3421 $label = $object->type == FactureFournisseur::TYPE_CREDIT_NOTE ? $langs->trans("SelectWarehouseForStockIncrease") : $langs->trans("SelectWarehouseForStockDecrease");
3422 $value = $formproduct->selectWarehouses(GETPOST('idwarehouse') ? GETPOST('idwarehouse') : 'ifone', 'idwarehouse', '', 1);
3423 }
3424 $formquestion = array(
3425 array('type' => 'other', 'name' => 'idwarehouse', 'label' => $label, 'value' => $value)
3426 );
3427 }
3428 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('UnvalidateBill'), $langs->trans('ConfirmUnvalidateBill', $object->ref), 'confirm_edit', $formquestion, 1, 1);
3429 }
3430
3431 // Confirmation set paid
3432 if ($action == 'paid' && ($resteapayer <= 0 || (getDolGlobalString('SUPPLIER_INVOICE_CAN_SET_PAID_EVEN_IF_PARTIALLY_PAID') && $resteapayer == $object->total_ttc))) {
3433 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ClassifyPaid'), $langs->trans('ConfirmClassifyPaidBill', $object->ref), 'confirm_paid', '', 0, 1);
3434 }
3435
3436 if ($action == 'paid' && $resteapayer > 0 && (!getDolGlobalString('SUPPLIER_INVOICE_CAN_SET_PAID_EVEN_IF_PARTIALLY_PAID') || $resteapayer != $object->total_ttc)) {
3437 $close = array();
3438 // Code
3439 $i = 0;
3440 $close[$i]['code'] = 'discount_vat'; // escompte
3441 $i++;
3442 $close[$i]['code'] = 'badsupplier';
3443 $i++;
3444 $close[$i]['code'] = 'other';
3445 $i++;
3446 // Help
3447 $i = 0;
3448 $close[$i]['label'] = $langs->trans("HelpEscompte").'<br><br>'.$langs->trans("ConfirmClassifyPaidPartiallyReasonDiscountVatDesc");
3449 $i++;
3450 $close[$i]['label'] = $langs->trans("ConfirmClassifyPaidPartiallyReasonBadSupplierDesc");
3451 $i++;
3452 $close[$i]['label'] = $langs->trans("Other");
3453 $i++;
3454 // Text
3455 $i = 0;
3456 $close[$i]['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyPaidPartiallyReasonDiscount", $resteapayer, $langs->trans("Currency".$conf->currency)), $close[$i]['label'], 1);
3457 $i++;
3458 $close[$i]['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyPaidPartiallyReasonBadCustomer", $resteapayer, $langs->trans("Currency".$conf->currency)), $close[$i]['label'], 1);
3459 $i++;
3460 $close[$i]['reason'] = $form->textwithpicto($langs->transnoentities("Other"), $close[$i]['label'], 1);
3461 $i++;
3462 // arrayreasons[code]=reason
3463 $arrayreasons = array();
3464 foreach ($close as $key => $val) {
3465 $arrayreasons[$close[$key]['code']] = $close[$key]['reason'];
3466 }
3467
3468 // Create a form table
3469 $formquestion = array('text' => $langs->trans("ConfirmClassifyPaidPartiallyQuestion"), 0 => array('type' => 'radio', 'name' => 'close_code', 'label' => $langs->trans("Reason"), 'values' => $arrayreasons), 1 => array('type' => 'text', 'name' => 'close_note', 'label' => $langs->trans("Comment"), 'value' => '', 'morecss' => 'minwidth300'));
3470 // Incomplete payment. We ask if the reason is discount or other
3471 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?facid='.$object->id, $langs->trans('ClassifyPaid'), $langs->trans('ConfirmClassifyPaidPartially', $object->ref), 'confirm_paid_partially', $formquestion, "yes", 1, 310);
3472 }
3473
3474 // Confirmation of the abandoned classification
3475 if ($action == 'canceled') {
3476 // Code
3477 $close[1]['code'] = 'badsupplier';
3478 $close[2]['code'] = 'abandon';
3479 // Help
3480 $close[1]['label'] = $langs->trans("ConfirmClassifyPaidPartiallyReasonBadSupplierDesc");
3481 $close[2]['label'] = $langs->trans("ConfirmClassifyAbandonReasonOtherDesc");
3482 // Text
3483 $close[1]['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyPaidPartiallyReasonBadSupplier", $object->ref), $close[1]['label'], 1);
3484 $close[2]['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyAbandonReasonOther"), $close[2]['label'], 1);
3485 // arrayreasons
3486 $arrayreasons[$close[1]['code']] = $close[1]['reason'];
3487 $arrayreasons[$close[2]['code']] = $close[2]['reason'];
3488
3489 // Create a form table
3490 $formquestion = array('text' => $langs->trans("ConfirmCancelBillQuestion"), 0 => array('type' => 'radio', 'name' => 'close_code', 'label' => $langs->trans("Reason"), 'values' => $arrayreasons), 1 => array('type' => 'text', 'name' => 'close_note', 'label' => $langs->trans("Comment"), 'value' => '', 'morecss' => 'minwidth300'));
3491
3492 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('CancelBill'), $langs->trans('ConfirmCancelBill', $object->ref), 'confirm_canceled', $formquestion, "yes", 1, 280);
3493 }
3494
3495 // Confirmation for supplier invoice deletion
3496 if ($action == 'delete') {
3497 $formquestion = array();
3498
3499 $qualified_for_stock_change = 0;
3500 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
3501 $qualified_for_stock_change = $object->hasProductsOrServices(2);
3502 } else {
3503 $qualified_for_stock_change = $object->hasProductsOrServices(1);
3504 }
3505
3506 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_BILL') && $qualified_for_stock_change) {
3507 $langs->load("stocks");
3508 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
3509 $formproduct = new FormProduct($db);
3510 $warehouse = new Entrepot($db);
3511 $warehouse_array = $warehouse->list_array();
3512
3513 $selectwarehouse = '<span class="questionrevertstock hidden">';
3514 if (count($warehouse_array) == 1) {
3515 $label = $object->type == FactureFournisseur::TYPE_CREDIT_NOTE ? $langs->trans("WarehouseForStockIncrease", current($warehouse_array)) : $langs->trans("WarehouseForStockDecrease", current($warehouse_array));
3516 $selectwarehouse .= '<input type="hidden" id="idwarehouse" name="idwarehouse" value="'.key($warehouse_array).'">';
3517 } else {
3518 $label = $object->type == FactureFournisseur::TYPE_CREDIT_NOTE ? $langs->trans("SelectWarehouseForStockIncrease") : $langs->trans("SelectWarehouseForStockDecrease");
3519 $selectwarehouse .= $formproduct->selectWarehouses(GETPOST('idwarehouse') ? GETPOST('idwarehouse') : 'ifone', 'idwarehouse', '', 1);
3520 }
3521 $selectwarehouse .= '</span>';
3522
3523 $selectyesno = array(0 => $langs->trans('No'), 1 => $langs->trans('Yes'));
3524
3525 print '<script type="text/javascript">
3526 $(document).ready(function() {
3527 $("#revertstock").change(function() {
3528 if(this.value > 0) {
3529 $(".questionrevertstock").removeClass("hidden");
3530 } else {
3531 $(".questionrevertstock").addClass("hidden");
3532 }
3533 });
3534 });
3535 </script>';
3536
3537 $formquestion = array(
3538 array('type' => 'select', 'name' => 'revertstock', 'label' => $langs->trans("RevertProductsToStock"), 'select_show_empty' => 0, 'values' => $selectyesno),
3539 array('type' => 'other', 'name' => 'idwarehouse', 'label' => $label, 'value' => $selectwarehouse, 'tdclass' => 'questionrevertstock hidden')
3540 );
3541 }
3542
3543 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteBill'), $langs->trans('ConfirmDeleteBill'), 'confirm_delete', $formquestion, 1, 1);
3544 }
3545 if ($action == 'deletepayment') {
3546 $payment_id = GETPOST('paiement_id');
3547 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&paiement_id='.$payment_id, $langs->trans('DeletePayment'), $langs->trans('ConfirmDeletePayment'), 'confirm_delete_paiement', '', 0, 1);
3548 }
3549
3550 // Confirmation to delete line
3551 if ($action == 'ask_deleteline') {
3552 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 0, 1);
3553 }
3554
3555 // Confirmation to delete a subtotal / title / text line (subtotals module)
3556 if ($action == 'ask_subtotal_deleteline') {
3557 $langs->load('subtotals');
3558 $subtotaltitle = 'DeleteSubtotalLine';
3559 $subtotalquestion = 'ConfirmDeleteSubtotalLine';
3560 $subtotalformquestion = array();
3561 if (GETPOST('type') == 'title') {
3562 $subtotalformquestion = array(array('type' => 'checkbox', 'name' => 'deletecorrespondingsubtotalline', 'label' => $langs->trans('DeleteCorrespondingSubtotalLine'), 'value' => 0));
3563 $subtotaltitle = 'DeleteTitleLine';
3564 $subtotalquestion = 'ConfirmDeleteTitleLine';
3565 }
3566 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans($subtotaltitle), $langs->trans($subtotalquestion), 'confirm_delete_subtotalline', $subtotalformquestion, 'no', 1);
3567 }
3568
3569 // Subtotal line form
3570 if ($action == 'add_title_line') {
3571 $langs->load('subtotals');
3572 $type = 'title';
3573 $depth_array = $object->getPossibleLevels($langs);
3574 require DOL_DOCUMENT_ROOT . '/core/tpl/subtotal_create.tpl.php';
3575 } elseif ($action == 'add_subtotal_line') {
3576 $langs->load('subtotals');
3577 $type = 'subtotal';
3578 $titles = $object->getPossibleTitles();
3579 require DOL_DOCUMENT_ROOT . '/core/tpl/subtotal_create.tpl.php';
3580 } elseif ($action == 'add_text_line') {
3581 $langs->load('subtotals');
3582 $type = 'text';
3583 require DOL_DOCUMENT_ROOT . '/core/tpl/subtotal_create.tpl.php';
3584 }
3585
3586 // Call Hook formConfirm
3587 $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
3588 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
3589 if (empty($reshook)) {
3590 $formconfirm .= $hookmanager->resPrint;
3591 } elseif ($reshook > 0) {
3592 $formconfirm = $hookmanager->resPrint;
3593 }
3594
3595 // Print form confirm
3596 print $formconfirm;
3597
3598
3599 // Supplier invoice card
3600 $linkback = '<a href="'.DOL_URL_ROOT.'/fourn/facture/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
3601
3602 $morehtmlref = '<div class="refidno">';
3603 // Ref supplier
3604 $morehtmlref .= $form->editfieldkey("RefSupplierBill", 'ref_supplier', $object->ref_supplier, $object, (int) $usercancreate, 'string', '', 0, 1);
3605 $morehtmlref .= $form->editfieldval("RefSupplierBill", 'ref_supplier', $object->ref_supplier, $object, $usercancreate, 'string', '', null, null, '', 1);
3606 // Thirdparty
3607 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1, 'supplier');
3608 if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
3609 $morehtmlref .= ' <div class="inline-block valignmiddle">(<a class="valignmiddle" href="'.DOL_URL_ROOT.'/fourn/facture/list.php?socid='.((int) $object->thirdparty->id).'">'.$langs->trans("OtherBills").'</a>)</div>';
3610 }
3611 // Project
3612 if (isModEnabled('project')) {
3613 $langs->load("projects");
3614 $morehtmlref .= '<br>';
3615 if ($permissiontoadd) {
3616 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
3617 if ($action != 'classify') {
3618 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.((int) $object->id).'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
3619 }
3620 $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'), 0, 0, 0, 1, '', 'maxwidth300');
3621 } else {
3622 if (!empty($object->fk_project)) {
3623 $proj = new Project($db);
3624 $proj->fetch($object->fk_project);
3625 $morehtmlref .= $proj->getNomUrl(1);
3626 if ($proj->title) {
3627 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
3628 }
3629 }
3630 }
3631 }
3632 $morehtmlref .= '</div>';
3633
3634 $object->totalpaid = $totalpaid; // To give a chance to dol_banner_tab to use already paid amount to show correct status
3635
3636 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
3637
3638 // Call Hook tabContentViewSupplierInvoice
3639 $parameters = array();
3640 // Note that $action and $object may be modified by hook
3641 $reshook = $hookmanager->executeHooks('tabContentViewSupplierInvoice', $parameters, $object, $action);
3642 if (empty($reshook)) {
3643 print '<div class="fichecenter">';
3644 print '<div class="fichehalfleft">';
3645 print '<div class="underbanner clearboth"></div>';
3646
3647 print '<table class="border tableforfield centpercent">';
3648
3649 // Type
3650 print '<tr><td>'.$langs->trans('Type').'</td><td>';
3651 print '<span class="badgeneutral">';
3652 print $object->getLibType();
3653 print '</span>';
3654 if ($object->subtype > 0) {
3655 print ' '.$object->getSubtypeLabel('facture_fourn');
3656 }
3658 $facreplaced = new FactureFournisseur($db);
3659 $facreplaced->fetch($object->fk_facture_source);
3660 print ' <span class="opacitymediumbycolor paddingleft">'.$langs->transnoentities("ReplaceInvoice", $facreplaced->getNomUrl(1)).'</span>';
3661 }
3663 if ($object->fk_facture_source > 0) {
3664 $facusing = new FactureFournisseur($db);
3665 $facusing->fetch($object->fk_facture_source);
3666 print ' <span class="opacitymediumbycolor paddingleft">'.$langs->transnoentities("CorrectInvoice", $facusing->getNomUrl(1)).'</span>';
3667 } else {
3668 $langs->load("errors");
3669 print ' <span class="opacitymediumbycolor paddingleft">'.$langs->transnoentities("WarningCorrectedInvoiceNotFound").'</span>';
3670 }
3671 }
3672
3673 // Retrieve credit note ids
3674 $object->getListIdAvoirFromInvoice();
3675
3676 if (!empty($object->creditnote_ids)) {
3677 $invoicecredits = array();
3678 foreach ($object->creditnote_ids as $invoiceid) {
3679 $creditnote = new FactureFournisseur($db);
3680 $creditnote->fetch($invoiceid);
3681 $invoicecredits[] = $creditnote->getNomUrl(1);
3682 }
3683 print ' <span class="opacitymediumbycolor paddingleft">'.$langs->transnoentities("InvoiceHasAvoir") . (count($invoicecredits) ? ' ' : '') . implode(',', $invoicecredits);
3684 print '</span>';
3685 }
3686 if (isset($objectidnext) && $objectidnext > 0) {
3687 $facthatreplace = new FactureFournisseur($db);
3688
3689 $facthatreplace->fetch($objectidnext);
3690 print ' <span class="opacitymediumbycolor paddingleft">'.str_replace('{s1}', $facthatreplace->getNomUrl(1), $langs->transnoentities("ReplacedByInvoice", '{s1}')).'</span>';
3691 }
3693 $discount = new DiscountAbsolute($db);
3694 $result = $discount->fetch(0, 0, $object->id);
3695 if ($result > 0) {
3696 print ' <span class="opacitymediumbycolor paddingleft">';
3697 $s = $langs->trans("CreditNoteConvertedIntoDiscount", '{s1}', '{s2}');
3698 $s = str_replace('{s1}', $object->getLibType(1), $s);
3699 $s = str_replace('{s2}', $discount->getNomUrl(1, 'discount'), $s);
3700 print $s;
3701 print '</span><br>';
3702 }
3703 }
3704
3705 if ($object->fk_fac_rec_source > 0) {
3706 $tmptemplate = new FactureFournisseurRec($db);
3707 $result = $tmptemplate->fetch($object->fk_fac_rec_source);
3708 if ($result > 0) {
3709 print ' <span class="opacitymediumbycolor paddingleft">';
3710 $link = '<a href="'.DOL_URL_ROOT.'/fourn/facture/card-rec.php?facid='.$tmptemplate->id.'">'.dol_escape_htmltag($tmptemplate->title).'</a>';
3711 $s = $langs->transnoentities("GeneratedFromSupplierTemplate", $link);
3712
3713 print $s;
3714 print '</span>';
3715 }
3716 }
3717 print '</td></tr>';
3718
3719
3720 // Relative and absolute discounts
3721 print '<!-- Discounts -->'."\n";
3722 print '<tr><td>'.$langs->trans('DiscountStillRemaining');
3723 print '</td><td>';
3724
3725 $thirdparty = $societe;
3726 $discount_type = 1;
3727 include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
3728
3729 print '</td></tr>';
3730
3731 // Label
3732 print '<tr>';
3733 print '<td>'.$form->editfieldkey("Label", 'label', $object->label, $object, (int) $usercancreate).'</td>';
3734 print '<td>'.$form->editfieldval("Label", 'label', $object->label, $object, $usercancreate).'</td>';
3735 print '</tr>';
3736
3737 //$form_permission = ($object->status < FactureFournisseur::STATUS_CLOSED) && $usercancreate && ($object->getSommePaiement() <= 0);
3738 $form_permission = ($object->status < FactureFournisseur::STATUS_CLOSED) && $usercancreate;
3739
3740 // Date
3741 print '<tr><td>';
3742 print $form->editfieldkey("DateInvoice", 'datef', (string) $object->date, $object, (int) $form_permission, 'datepicker');
3743 print '</td><td colspan="3">';
3744 print $form->editfieldval("Date", 'datef', $object->date, $object, $form_permission, 'datepicker');
3745 print '</td>';
3746
3747 // Default terms of the settlement
3748 $langs->load('bills');
3749 print '<tr><td class="nowrap">';
3750 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
3751 print $langs->trans('PaymentConditions');
3752 print '<td>';
3753 if ($action != 'editconditions' && $form_permission) {
3754 print '<td class="right"><a class="editfielda reposition" href="'.$_SERVER["PHP_SELF"].'?action=editconditions&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetConditions'), 1).'</a></td>';
3755 }
3756 print '</tr></table>';
3757 print '</td><td>';
3758 if ($action == 'editconditions') {
3759 $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->cond_reglement_id, 'cond_reglement_id');
3760 } else {
3761 $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->cond_reglement_id, 'none');
3762 }
3763 print "</td>";
3764 print '</tr>';
3765
3766 // Due date
3767 print '<tr><td>';
3768 print $form->editfieldkey("DateMaxPayment", 'date_lim_reglement', (string) $object->date_echeance, $object, (int) $form_permission, 'datepicker');
3769 print '</td><td>';
3770 print $form->editfieldval("DateMaxPayment", 'date_lim_reglement', $object->date_echeance, $object, $form_permission, 'datepicker');
3771 if ($action != 'editdate_lim_reglement' && $object->hasDelay()) {
3772 print img_warning($langs->trans('Late'));
3773 }
3774 print '</td>';
3775
3776 // Mode of payment
3777 $langs->load('bills');
3778 print '<tr><td class="nowrap">';
3779 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
3780 print $langs->trans('PaymentMode');
3781 print '</td>';
3782 if ($action != 'editmode' && $form_permission) {
3783 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>';
3784 }
3785 print '</tr></table>';
3786 print '</td><td>';
3787 if ($action == 'editmode') {
3788 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->mode_reglement_id, 'mode_reglement_id', 'DBIT', 1, 1);
3789 } else {
3790 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->mode_reglement_id, 'none');
3791 }
3792 print '</td></tr>';
3793
3794 // Bank Account
3795 if (isModEnabled("bank")) {
3796 print '<tr><td class="nowrap">';
3797 print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
3798 print $langs->trans('BankAccount');
3799 print '<td>';
3800 if ($action != 'editbankaccount' && $usercancreate) {
3801 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>';
3802 }
3803 print '</tr></table>';
3804 print '</td><td>';
3805 if ($action == 'editbankaccount') {
3806 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'fk_account', 1);
3807 } else {
3808 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'none');
3809 }
3810 print "</td>";
3811 print '</tr>';
3812 }
3813
3814 // Vat reverse-charge by default
3815 if (getDolGlobalString('ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE')) {
3816 print '<tr><td class="nowrap">';
3817 print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
3818 print $langs->trans('VATReverseCharge');
3819 print '<td>';
3820 if ($action != 'editvatreversecharge' && $usercancreate) {
3821 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editvatreversecharge&amp;token='.newToken().'&amp;id='.$object->id.'">'.img_edit($langs->trans('SetVATReverseCharge'), 1).'</a></td>';
3822 }
3823 print '</tr></table>';
3824 print '</td><td>';
3825 if ($action == 'editvatreversecharge') {
3826 print '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
3827 print '<input type="hidden" name="action" value="setvatreversecharge">';
3828 print '<input type="hidden" name="token" value="'.newToken().'">';
3829
3830 print '<input type="checkbox" name="vat_reverse_charge"' . ($object->vat_reverse_charge == '1' ? ' checked ' : '') . '>';
3831
3832 print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
3833 print '</form>';
3834 } else {
3835 print '<input type="checkbox" name="vat_reverse_charge"'. ($object->vat_reverse_charge == '1' ? ' checked ' : '') . ' disabled>';
3836 }
3837 print '</td></tr>';
3838 }
3839
3840 // Incoterms
3841 if (isModEnabled('incoterm')) {
3842 print '<tr><td>';
3843 print '<table width="100%" class="nobordernopadding"><tr><td>';
3844 print $langs->trans('IncotermLabel');
3845 print '<td><td class="right">';
3846 if ($usercancreate) {
3847 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/fourn/facture/card.php?facid='.$object->id.'&action=editincoterm&token='.newToken().'">'.img_edit().'</a>';
3848 } else {
3849 print '&nbsp;';
3850 }
3851 print '</td></tr></table>';
3852 print '</td>';
3853 print '<td>';
3854 if ($action != 'editincoterm') {
3855 print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
3856 } else {
3857 print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
3858 }
3859 print '</td></tr>';
3860 }
3861
3862 // Intracomm report
3863 if (isModEnabled('intracommreport')) {
3864 $langs->loadLangs(array("intracommreport"));
3865 print '<!-- If module intracomm on -->'."\n";
3866 print '<tr><td>';
3867 print '<table class="nobordernopadding centpercent"><tr><td>';
3868 print $langs->trans('IntracommReportTransportMode');
3869 print '</td>';
3870 if ($action != 'edittransportmode' && ($user->hasRight("fournisseur", "facture", "creer") || $user->hasRight("supplier_invoice", "creer"))) {
3871 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=edittransportmode&token='.newToken().'&id='.$object->id.'">'.img_edit().'</a></td>';
3872 }
3873 print '</tr></table>';
3874 print '</td>';
3875 print '<td>';
3876 if ($action == 'edittransportmode') {
3877 $form->formSelectTransportMode($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->transport_mode_id, 'transport_mode_id', 1, 1);
3878 } else {
3879 $form->formSelectTransportMode($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->transport_mode_id, 'none');
3880 }
3881 print '</td></tr>';
3882 }
3883
3884 // Categories
3885 if (isModEnabled('category')) {
3886 print '<tr><td>';
3887 print '<table class="nobordernopadding centpercent"><tr><td>';
3888 print $langs->trans("Categories");
3889 print '<td><td class="right">';
3890 if ($usercancreate) {
3891 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/fourn/facture/card.php?facid='.$object->id.'&action=edittags&token='.newToken().'">'.img_edit().'</a>';
3892 } else {
3893 print '&nbsp;';
3894 }
3895 print '</td></tr></table>';
3896 print '</td>';
3897 print '<td>';
3898 if ($action == 'edittags') {
3899 print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'?facid='.$object->id.'">';
3900 print '<input type="hidden" name="action" value="settags">';
3901 print '<input type="hidden" name="token" value="'.newToken().'">';
3902 print $form->selectCategories(Categorie::TYPE_SUPPLIER_INVOICE, 'categories', $object);
3903 print '<input type="submit" class="button valignmiddle smallpaddingimp" value="'.$langs->trans("Modify").'">';
3904 print '</form>';
3905 } else {
3906 print $form->showCategories($object->id, Categorie::TYPE_SUPPLIER_INVOICE, 1);
3907 }
3908 print "</td></tr>";
3909 }
3910
3911
3912 // Other attributes. Fields from hook formObjectOptions and Extrafields.
3913 $cols = 2;
3914 if ($object->status != $object::STATUS_DRAFT) {
3915 $disableedit = 1;
3916 $disableremove = 1;
3917 }
3918 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
3919
3920 print '</table>';
3921 print '</div>';
3922
3923 print '<div class="fichehalfright">';
3924 print '<div class="underbanner clearboth"></div>';
3925
3926 print '<table class="border tableforfield centpercent">';
3927
3928 include DOL_DOCUMENT_ROOT.'/core/tpl/object_currency_amount.tpl.php';
3929
3930 print '<tr>';
3931 print '<td class="titlefieldmiddle">' . $langs->trans('AmountHT') . '</td>';
3932 print '<td class="nowrap amountcard right">' . price($object->total_ht, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
3933 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
3934 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ht, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
3935 }
3936 print '</tr>';
3937
3938 print '<tr>';
3939 print '<td>' . $langs->trans('AmountVAT') . '</td>';
3940 print '<td class="nowrap amountcard right">';
3941 if (GETPOST('calculationrule')) {
3942 $calculationrule = GETPOST('calculationrule', 'alpha');
3943 } else {
3944 $calculationrule = (!getDolGlobalString('MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND_SUPPLIER') ? 'totalofround' : 'roundoftotal');
3945 }
3946 if ($calculationrule == 'totalofround') {
3947 $calculationrulenum = 1;
3948 } else {
3949 $calculationrulenum = 2;
3950 }
3951 // Show link for "recalculate"
3952 if ($object->getVentilExportCompta() == 0) {
3953 $s = '<span class="hideonsmartphone opacitymedium">' . $langs->trans("ReCalculate") . ' </span>';
3954 $s .= '<a href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=calculate&token='.newToken().'&calculationrule=totalofround">' . $langs->trans("Mode1") . '</a>';
3955 $s .= ' / ';
3956 $s .= '<a href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=calculate&token='.newToken().'&calculationrule=roundoftotal">' . ($conf->dol_optimize_smallscreen ? "2" : $langs->trans("Mode2")) . '</a>';
3957 print '<div class="inline-block">';
3958 print $form->textwithtooltip($s, $langs->trans("CalculationRuleDesc", $calculationrulenum) . '<br>' . $langs->trans("CalculationRuleDescSupplier"), 2, 1, img_picto('', 'help', 'class="paddingleft paddingright"'), '', 3, '', 0, 'recalculate');
3959 print '&nbsp; &nbsp; &nbsp; &nbsp;';
3960 print '</div>';
3961 }
3962 print '<span class="nowraponall">'.price($object->total_tva, 1, $langs, 0, -1, -1, $conf->currency).'</span>';
3963 print '</td>';
3964 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
3965 print '<td class="nowraponall amountcard right">' . price($object->multicurrency_total_tva, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
3966 }
3967 print '</tr>';
3968
3969 if ($societe->localtax1_assuj == "1") { //Localtax1
3970 print '<tr>';
3971 print '<td>' . $langs->transcountry("AmountLT1", $societe->country_code) . '</td>';
3972 print '<td class="nowrap amountcard right">' . price($object->total_localtax1, 1, $langs, 0, -1, -1, $conf->currency) . '</td>';
3973 print '</tr>';
3974 }
3975 if ($societe->localtax2_assuj == "1") { //Localtax2
3976 print '<tr>';
3977 print '<td>' . $langs->transcountry("AmountLT2", $societe->country_code) . '</td>';
3978 print '<td class="nowrap amountcard right">' . price($object->total_localtax2, 1, $langs, 0, -1, -1, $conf->currency) . '</td>';
3979 print '</tr>';
3980 }
3981
3982 print '<tr>';
3983 print '<td>' . $langs->trans('AmountTTC') . '</td>';
3984 print '<td class="nowrap amountcard right">' . price($object->total_ttc, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
3985 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
3986 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ttc, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
3987 }
3988 print '</tr>';
3989
3990 print '</table>';
3991
3992
3993 // List of payments already done
3994
3995 $totalpaid = 0;
3996
3997 $sign = 1;
3999 $sign = - 1;
4000 }
4001
4002 $nbrows = 9;
4003 $nbcols = 3;
4004 if (isModEnabled('project')) {
4005 $nbrows++;
4006 }
4007 if (isModEnabled("bank")) {
4008 $nbrows++;
4009 $nbcols++;
4010 }
4011 if (isModEnabled('incoterm')) {
4012 $nbrows++;
4013 }
4014 if (isModEnabled("multicurrency")) {
4015 $nbrows += 5;
4016 }
4017
4018 // Local taxes
4019 if ($societe->localtax1_assuj == "1") {
4020 $nbrows++;
4021 }
4022 if ($societe->localtax2_assuj == "1") {
4023 $nbrows++;
4024 }
4025
4026 $sql = 'SELECT p.datep as dp, p.ref, p.num_paiement as num_payment, p.rowid, p.fk_bank,';
4027 $sql .= ' c.id as payment_type, c.code as payment_code,';
4028 $sql .= ' pf.amount,';
4029 $sql .= ' ba.rowid as baid, ba.ref as baref, ba.label, ba.number as banumber, ba.account_number, ba.fk_accountancy_journal';
4030 $sql .= ' FROM '.MAIN_DB_PREFIX.'paiementfourn as p';
4031 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank as b ON p.fk_bank = b.rowid';
4032 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank_account as ba ON b.fk_account = ba.rowid';
4033 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as c ON p.fk_paiement = c.id';
4034 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'paiementfourn_facturefourn as pf ON pf.fk_paiementfourn = p.rowid';
4035 $sql .= ' WHERE pf.fk_facturefourn = '.((int) $object->id);
4036 $sql .= ' ORDER BY p.datep, p.tms';
4037
4038 $result = $db->query($sql);
4039 if ($result) {
4040 $num = $db->num_rows($result);
4041 $i = 0;
4042
4043 print '<div class="div-table-responsive-no-min">';
4044 print '<table class="noborder paymenttable centpercent">';
4045 print '<tr class="liste_titre">';
4046 print '<td class="liste_titre">'.($object->type == FactureFournisseur::TYPE_CREDIT_NOTE ? $langs->trans("PaymentsBack") : $langs->trans('Payments')).'</td>';
4047 print '<td><span class="hideonsmartphone">'.$langs->trans('Date').'</span></td>';
4048 print '<td><span class="hideonsmartphone">'.$langs->trans('Type').'</span></td>';
4049 if (isModEnabled("bank")) {
4050 print '<td class="right">'.$langs->trans('BankAccount').'</td>';
4051 }
4052 // Action
4053 print '<td></td>';
4054 // Amount
4055 print '<td class="right">'.$langs->trans('Amount').'</td>';
4056 print '</tr>';
4057
4058 if ($num > 0) {
4059 while ($i < $num) {
4060 $objp = $db->fetch_object($result);
4061
4062 $paymentstatic->id = $objp->rowid;
4063 $paymentstatic->datepaye = $db->jdate($objp->dp);
4064 $paymentstatic->ref = ($objp->ref ? $objp->ref : $objp->rowid);
4065 $paymentstatic->num_payment = $objp->num_payment;
4066
4067 $paymentstatic->paiementcode = $objp->payment_code;
4068 $paymentstatic->type_code = $objp->payment_code;
4069 $paymentstatic->type_label = $objp->payment_type;
4070
4071 print '<tr class="oddeven">';
4072 print '<td class="nowraponall">';
4073 print $paymentstatic->getNomUrl(1);
4074 print '</td>';
4075 print '<td>'.dol_print_date($db->jdate($objp->dp), 'day').'</td>';
4076 $s = $form->form_modes_reglement('', $objp->payment_type, 'none', '', 1, 0, '', 1).' '.$objp->num_payment;
4077 print '<td class="tdoverflowmax125" title="'.dol_escape_htmltag($s).'">';
4078 print $s;
4079 print '</td>';
4080 if (isModEnabled("bank")) {
4081 $bankaccountstatic->id = $objp->baid;
4082 $bankaccountstatic->ref = $objp->baref;
4083 $bankaccountstatic->label = $objp->baref;
4084 $bankaccountstatic->number = $objp->banumber;
4085
4086 if (isModEnabled('accounting')) {
4087 $bankaccountstatic->account_number = $objp->account_number;
4088
4089 $accountingjournal = new AccountingJournal($db);
4090 $accountingjournal->fetch($objp->fk_accountancy_journal);
4091 $bankaccountstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1);
4092 }
4093
4094 print '<td class="right nowraponall">';
4095 if ($objp->baid > 0) {
4096 print $bankaccountstatic->getNomUrl(1, 'transactions');
4097 }
4098 print '</td>';
4099 }
4100 // Delete
4101 print '<td class="center">';
4102 if ($object->status == FactureFournisseur::STATUS_VALIDATED && $object->paid == 0 && $user->socid == 0) {
4103 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=deletepayment&token='.newToken().'&paiement_id='.$objp->rowid.'">';
4104 print img_delete();
4105 print '</a>';
4106 }
4107 print '</td>';
4108 // Amount
4109 print '<td class="right">'.price($sign * $objp->amount).'</td>';
4110 print '</tr>';
4111 $totalpaid += $objp->amount;
4112 $i++;
4113 }
4114 } else {
4115 print '<tr class="oddeven"><td colspan="'.$nbcols.'"><span class="opacitymedium">'.$langs->trans("None").'</span></td>';
4116 print '<td></td>';
4117 print '<td></td>';
4118 print '</tr>';
4119 }
4120
4121 /*
4122 if ($object->paid == 0)
4123 {
4124 print '<tr><td colspan="'.$nbcols.'" class="right">'.$langs->trans('AlreadyPaid').' :</td><td class="right">'.price($totalpaid).'</td><td></td></tr>';
4125 print '<tr><td colspan="'.$nbcols.'" class="right">'.$langs->trans("Billed").' :</td><td class="right">'.price($object->total_ttc).'</td><td></td></tr>';
4126
4127 $resteapayer = $object->total_ttc - $totalpaid;
4128
4129 print '<tr><td colspan="'.$nbcols.'" class="right">'.$langs->trans('RemainderToPay').' :</td>';
4130 print '<td class="right'.($resteapayer?' amountremaintopay':'').'">'.price($resteapayer).'</td><td></td></tr>';
4131 }
4132 */
4133
4134 $db->free($result);
4135 } else {
4137 }
4138
4140 // Total already paid
4141 print '<tr><td colspan="'.($nbcols + 1).'" class="right">';
4142 print '<span class="opacitymedium">';
4144 print $langs->trans('AlreadyPaidNoCreditNotesNoDeposits');
4145 } else {
4146 print $langs->trans('AlreadyPaid');
4147 }
4148 print '</span>';
4149 print '</td>';
4150 //print '<td></td>';
4151 print '<td class="right"'.(($totalpaid > 0) ? ' class="amountalreadypaid"' : '').'>'.price($totalpaid).'</td>';
4152 print '</tr>';
4153
4154 //$resteapayer = $object->total_ttc - $totalpaid;
4155 $resteapayeraffiche = $resteapayer;
4156
4157 $cssforamountpaymentcomplete = 'amountpaymentcomplete';
4158
4159 // Loop on each credit note or deposit amount applied
4160 $creditnoteamount = 0;
4161 $depositamount = 0;
4162
4163 $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
4164 $sql .= " re.description, re.fk_invoice_supplier_source";
4165 $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re";
4166 $sql .= " WHERE fk_invoice_supplier = ".((int) $object->id);
4167 $resql = $db->query($sql);
4168 if ($resql) {
4169 $num = $db->num_rows($resql);
4170 $i = 0;
4171 $invoice = new FactureFournisseur($db);
4172 while ($i < $num) {
4173 $obj = $db->fetch_object($resql);
4174 $invoice->fetch($obj->fk_invoice_supplier_source);
4175 print '<tr><td colspan="'.$nbcols.'" class="right">';
4176 if ($invoice->type == FactureFournisseur::TYPE_CREDIT_NOTE) {
4177 print $langs->trans("CreditNote").' ';
4178 }
4179 if ($invoice->type == FactureFournisseur::TYPE_DEPOSIT) {
4180 print $langs->trans("Deposit").' ';
4181 }
4182 print $invoice->getNomUrl(0);
4183 print '</td>';
4184 // Delete
4185 print '<td class="right">';
4186 print '<a href="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'&action=unlinkdiscount&token='.newToken().'&discountid='.$obj->rowid.'">';
4187 print img_picto($langs->transnoentitiesnoconv("RemoveDiscount"), 'unlink');
4188 print '</a>';
4189 print '</td>';
4190 // Amount
4191 print '<td class="right">'.price($obj->amount_ttc).'</td>';
4192 print '</tr>';
4193 $i++;
4194 if ($invoice->type == FactureFournisseur::TYPE_CREDIT_NOTE) {
4195 $creditnoteamount += $obj->amount_ttc;
4196 }
4197 if ($invoice->type == FactureFournisseur::TYPE_DEPOSIT) {
4198 $depositamount += $obj->amount_ttc;
4199 }
4200 }
4201 } else {
4203 }
4204
4205 // Pay partially 'escompte'
4206 if (($object->status == FactureFournisseur::STATUS_CLOSED || $object->status == FactureFournisseur::STATUS_ABANDONED) && $object->close_code == 'discount_vat') {
4207 print '<tr><td colspan="'.($nbcols + 1).'" class="right nowrap">';
4208 print '<span class="opacitymedium">';
4209 print $form->textwithpicto($langs->trans("Discount"), $langs->trans("HelpEscompte"), - 1);
4210 print '</span>';
4211 print '</td>';
4212 //print '<td></td>';
4213 print '<td class="right">'.price($object->total_ttc - $creditnoteamount - $depositamount - $totalpaid).'</td>';
4214 print '</tr>';
4215 $resteapayeraffiche = 0;
4216 $cssforamountpaymentcomplete = 'amountpaymentneutral';
4217 }
4218 // Paye partiellement ou Abandon 'badsupplier'
4219 if (($object->status == FactureFournisseur::STATUS_CLOSED || $object->status == FactureFournisseur::STATUS_ABANDONED) && $object->close_code == 'badsupplier') {
4220 print '<tr><td colspan="'.($nbcols + 1).'" class="right nowrap">';
4221 print '<span class="opacitymedium">';
4222 print $form->textwithpicto($langs->trans("Abandoned"), $langs->trans("HelpAbandonBadCustomer"), - 1);
4223 print '</span>';
4224 print '</td>';
4225 //print '<td></td>';
4226 print '<td class="right">'.price($object->total_ttc - $creditnoteamount - $depositamount - $totalpaid).'</td>';
4227 print '</tr>';
4228 // $resteapayeraffiche=0;
4229 $cssforamountpaymentcomplete = 'amountpaymentneutral';
4230 }
4231 // Paye partiellement ou Abandon 'product_returned'
4232 if (($object->status == FactureFournisseur::STATUS_CLOSED || $object->status == FactureFournisseur::STATUS_ABANDONED) && $object->close_code == 'product_returned') {
4233 print '<tr><td colspan="'.($nbcols + 1).'" class="right nowrap">';
4234 print '<span class="opacitymedium">';
4235 print $form->textwithpicto($langs->trans("ProductReturned"), $langs->trans("HelpAbandonProductReturned"), - 1);
4236 print '</span>';
4237 print '</td>';
4238 //print '<td></td>';
4239 print '<td class="right">'.price($object->total_ttc - $creditnoteamount - $depositamount - $totalpaid).'</td>';
4240 print '</tr>';
4241 $resteapayeraffiche = 0;
4242 $cssforamountpaymentcomplete = 'amountpaymentneutral';
4243 }
4244 // Paye partiellement ou Abandon 'abandon'
4245 if (($object->status == FactureFournisseur::STATUS_CLOSED || $object->status == FactureFournisseur::STATUS_ABANDONED) && $object->close_code == 'abandon') {
4246 print '<tr><td colspan="'.($nbcols + 1).'" class="right nowrap">';
4247 $text = $langs->trans("HelpAbandonOther");
4248 if ($object->close_note) {
4249 $text .= '<br><br><b>'.$langs->trans("Reason").'</b>:'.$object->close_note;
4250 }
4251 print '<span class="opacitymedium">';
4252 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
4253 print $form->textwithpicto($langs->trans("Abandoned"), $text, - 1);
4254 print '</span>';
4255 print '</td>';
4256 //print '<td></td>';
4257 print '<td class="right">'.price($object->total_ttc - $creditnoteamount - $depositamount - $totalpaid).'</td>';
4258 print '</tr>';
4259 $resteapayeraffiche = 0;
4260 $cssforamountpaymentcomplete = 'amountpaymentneutral';
4261 }
4262
4263 // Billed
4264 print '<tr><td colspan="'.($nbcols + 1).'" class="right">';
4265 print '<span class="opacitymedium">';
4266 print $langs->trans("Billed");
4267 print '</span>';
4268 print '</td>';
4269 //print '<td></td>';
4270 print '<td class="right">'.price($object->total_ttc).'</td>';
4271 print '</tr>';
4272
4273 // Remainder to pay
4274 print '<tr><td colspan="'.($nbcols + 1).'" class="right">';
4275 print '<span class="opacitymedium">';
4276 print $langs->trans('RemainderToPay');
4277 if ($resteapayeraffiche < 0) {
4278 print ' ('.$langs->trans('NegativeIfExcessPaid').')';
4279 }
4280 print '</span>';
4281 print '</td>';
4282 //print '<td></td>';
4283 print '<td class="right'.($resteapayeraffiche ? ' amountremaintopay' : (' '.$cssforamountpaymentcomplete)).'">'.price($resteapayeraffiche).'</td>';
4284 print '</tr>';
4285
4286 // Remainder to pay Multicurrency
4287 if (isModEnabled('multicurrency') && (($object->multicurrency_code && $object->multicurrency_code != $conf->currency) || $object->multicurrency_tx != 1)) {
4288 print '<tr><td colspan="'.($nbcols + 1).'" class="right">';
4289 print '<span class="opacitymedium">';
4290 print $langs->trans('RemainderToPayMulticurrency');
4291 if ($resteapayeraffiche < 0) {
4292 print ' ('.$langs->trans('NegativeIfExcessPaid').')';
4293 }
4294 print '</span>';
4295 print '</td>';
4296 //print '<td></td>';
4297 print '<td class="right'.($resteapayeraffiche ? ' amountremaintopaynoresize' : (' '.$cssforamountpaymentcomplete)).'">'.price(price2num($multicurrency_resteapayer, 'MT'), 0, $langs, 1, -1, -1, $object->multicurrency_code).'</td>';
4298 print '</tr>';
4299 }
4300 } else { // Credit note
4301 $cssforamountpaymentcomplete = 'amountpaymentneutral';
4302
4303 // Total already paid back
4304 print '<tr><td colspan="'.($nbcols + 1).'" class="right">';
4305 print $langs->trans('AlreadyPaidBack');
4306 print '</td>';
4307 //print '<td></td>';
4308 print '<td class="right">'.price($sign * $totalpaid).'</td>';
4309 print '</tr>';
4310
4311 // Billed
4312 print '<tr><td colspan="'.($nbcols + 1).'" class="right">'.$langs->trans("Billed").'</td>';
4313 //print '<td></td>';
4314 print '<td class="right">'.price($sign * $object->total_ttc).'</td>';
4315 print '</tr>';
4316
4317 // Remainder to pay back
4318 print '<tr><td colspan="'.($nbcols + 1).'" class="right">';
4319 print '<span class="opacitymedium">';
4320 print $langs->trans('RemainderToPayBack');
4321 if ($resteapayeraffiche > 0) {
4322 print ' ('.$langs->trans('NegativeIfExcessRefunded').')';
4323 }
4324 print '</td>';
4325 print '</span>';
4326 //print '<td></td>';
4327 print '<td class="right'.($resteapayeraffiche ? ' amountremaintopay' : (' '.$cssforamountpaymentcomplete)).'">'.price($sign * $resteapayeraffiche).'</td>';
4328 print '</tr>';
4329
4330 // Remainder to pay back Multicurrency
4331 if (isModEnabled('multicurrency') && (($object->multicurrency_code && $object->multicurrency_code != $conf->currency) || $object->multicurrency_tx != 1)) {
4332 print '<tr><td colspan="'.($nbcols + 1).'" class="right">';
4333 print '<span class="opacitymedium">';
4334 print $langs->trans('RemainderToPayBackMulticurrency');
4335 if ($resteapayeraffiche > 0) {
4336 print ' ('.$langs->trans('NegativeIfExcessRefunded').')';
4337 }
4338 print '</span>';
4339 print '</td>';
4340 //print '<td></td>';
4341 print '<td class="right'.($resteapayeraffiche ? ' amountremaintopaynoresize' : (' '.$cssforamountpaymentcomplete)).'">'.(!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency).' '.price(price2num($sign * $object->multicurrency_tx * $resteapayeraffiche, 'MT')).'</td>';
4342 print '</tr>';
4343 }
4344
4345 // Sold credit note
4346 // print '<tr><td colspan="'.$nbcols.'" class="right">'.$langs->trans('TotalTTC').' :</td>';
4347 // print '<td class="right" style="border: 1px solid;" bgcolor="#f0f0f0"><b>'.price($sign *
4348 // $object->total_ttc).'</b></td><td>&nbsp;</td></tr>';
4349 }
4350
4351 print '</table>';
4352 print '</div>';
4353
4354 print '</div>';
4355 print '</div>';
4356
4357 print '<div class="clearboth"></div><br>';
4358
4359 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
4360 $blocname = 'contacts';
4361 $title = $langs->trans('ContactsAddresses');
4362 include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
4363 }
4364
4365 if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
4366 $colwidth = 20;
4367 $blocname = 'notes';
4368 $title = $langs->trans('Notes');
4369 include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
4370 }
4371
4372
4373 /*
4374 * Lines
4375 */
4376 print '<form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
4377 print '<input type="hidden" name="token" value="'.newToken().'">';
4378 print '<input type="hidden" name="action" value="'.(($action != 'editline') ? 'addline' : 'updateline').'">';
4379 print '<input type="hidden" name="mode" value="">';
4380 print '<input type="hidden" name="page_y" value="">';
4381 print '<input type="hidden" name="id" value="'.$object->id.'">';
4382 print '<input type="hidden" name="socid" value="'.$societe->id.'">';
4383 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
4384
4385 if (!empty($conf->use_javascript_ajax) && $object->status == FactureFournisseur::STATUS_DRAFT) {
4386 if (isModEnabled('subtotals')) {
4387 include DOL_DOCUMENT_ROOT . '/core/tpl/subtotal_ajaxrow.tpl.php';
4388 } else {
4389 include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
4390 }
4391 }
4392
4393 print '<div class="div-table-responsive-no-min">';
4394 print '<table id="tablelines" class="noborder noshadow centpercent">';
4395
4396 global $forceall, $senderissupplier, $dateSelector, $inputalsopricewithtax;
4397 $forceall = 1;
4398 $dateSelector = 0;
4399 $inputalsopricewithtax = 1;
4400 $senderissupplier = 2; // $senderissupplier=2 is same than 1 but disable test on minimum qty and disable autofill qty with minimum.
4401 if (getDolGlobalInt('SUPPLIER_INVOICE_WITH_PREDEFINED_PRICES_ONLY')) {
4402 $senderissupplier = getDolGlobalInt('SUPPLIER_INVOICE_WITH_PREDEFINED_PRICES_ONLY');
4403 }
4404
4405 // Show object lines (result may vary according to hidden option MAIN_NO_INPUT_PRICE_WITH_TAX)
4406 if (!empty($object->lines)) {
4407 $object->printObjectLines($action, $societe, $mysoc, $lineid, 1);
4408 }
4409
4410 $num = count($object->lines);
4411
4412 // Form to add new line
4413 if ($object->status == FactureFournisseur::STATUS_DRAFT && $usercancreate) {
4414 if ($action != 'editline') {
4415 // Add free products/services
4416
4417 $parameters = array();
4418 $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
4419 if ($reshook < 0) {
4420 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
4421 }
4422 if (empty($reshook)) {
4423 $object->formAddObjectLine(1, $societe, $mysoc);
4424 }
4425 }
4426 }
4427
4428 print '</table>';
4429 print '</div>';
4430 print '</form>';
4431 }
4432
4433 print dol_get_fiche_end();
4434
4435
4436 if ($action != 'presend') {
4437 // Buttons actions
4438
4439 print '<div class="tabsAction">';
4440
4441 $parameters = array();
4442 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
4443 // modified by hook
4444 if (empty($reshook)) {
4445 // Subtotal
4446 if ($object->status == FactureFournisseur::STATUS_DRAFT && isModEnabled('subtotals')
4447 && (getDolGlobalString('SUBTOTAL_TITLE_'.strtoupper($object->element)) || getDolGlobalString('SUBTOTAL_'.strtoupper($object->element)) || getDolGlobalString('SUBTOTAL_TEXT_'.strtoupper($object->element)))) {
4448 $langs->load('subtotals');
4449
4450 $url_button = array();
4451
4452 $url_button[] = array(
4453 'lang' => 'subtotals',
4454 'enabled' => true,
4455 'perm' => (bool) $usercancreate,
4456 'label' => $langs->trans('AddTitleLine'),
4457 'url' => dolBuildUrl($_SERVER['PHP_SELF'], ['id' => $object->id, 'action' => 'add_title_line'], true)
4458 );
4459
4460 $url_button[] = array(
4461 'lang' => 'subtotals',
4462 'enabled' => true,
4463 'perm' => (bool) $usercancreate,
4464 'label' => $langs->trans('AddSubtotalLine'),
4465 'url' => dolBuildUrl($_SERVER['PHP_SELF'], ['id' => $object->id, 'action' => 'add_subtotal_line'], true)
4466 );
4467
4468 $url_button[] = array(
4469 'lang' => 'subtotals',
4470 'enabled' => true,
4471 'perm' => (bool) $usercancreate,
4472 'label' => $langs->trans('AddTextLine'),
4473 'url' => dolBuildUrl($_SERVER['PHP_SELF'], ['id' => $object->id, 'action' => 'add_text_line'], true)
4474 );
4475
4476 print dolGetButtonAction('', $langs->trans('SubTotal'), 'default', $url_button, '', true);
4477 }
4478 // Modify a validated invoice with no payments
4479 if ($object->status == FactureFournisseur::STATUS_VALIDATED && $action != 'confirm_edit' && $object->getSommePaiement() == 0 && $usercancreate) {
4480 // We check if lines of invoice are not already transferred into accountancy
4481 $ventilExportCompta = $object->getVentilExportCompta(); // Should be 0 since the sum of payments are zero. But we keep the protection.
4482
4483 if ($ventilExportCompta == 0) {
4484 print '<a class="butAction'.($conf->use_javascript_ajax ? ' reposition' : '').'" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=edit&token='.newToken().'">'.$langs->trans('Modify').'</a>';
4485 } else {
4486 print '<span class="butActionRefused classfortooltip" title="'.$langs->trans("DisabledBecauseDispatchedInBookkeeping").'">'.$langs->trans('Modify').'</span>';
4487 }
4488 }
4489
4490 $discount = new DiscountAbsolute($db);
4491 $result = $discount->fetch(0, 0, $object->id);
4492
4493 // Reopen a standard paid invoice
4495 || ($object->type == FactureFournisseur::TYPE_CREDIT_NOTE && empty($discount->id))
4496 || ($object->type == FactureFournisseur::TYPE_DEPOSIT && empty($discount->id)))
4497 && ($object->status == FactureFournisseur::STATUS_CLOSED || $object->status == FactureFournisseur::STATUS_ABANDONED)) { // A paid invoice (partially or completely)
4498 if (!$objectidnext && $object->close_code != 'replaced' && $usercancreate) { // Not replaced by another invoice
4499 print '<a class="butAction'.($conf->use_javascript_ajax ? ' reposition' : '').'" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans('ReOpen').'</a>';
4500 } else {
4501 if ($usercancreate) {
4502 print '<span class="butActionRefused classfortooltip" title="'.$langs->trans("DisabledBecauseReplacedInvoice").'">'.$langs->trans('ReOpen').'</span>';
4503 } elseif (!getDolGlobalString('MAIN_BUTTON_HIDE_UNAUTHORIZED')) {
4504 print '<span class="butActionRefused classfortooltip">'.$langs->trans('ReOpen').'</span>';
4505 }
4506 }
4507 }
4508
4509 // Validate
4510 if ($action != 'confirm_edit' && $object->status == FactureFournisseur::STATUS_DRAFT && count($object->lines) > 0
4511 && ((($object->type == FactureFournisseur::TYPE_STANDARD || $object->type == FactureFournisseur::TYPE_REPLACEMENT || $object->type == FactureFournisseur::TYPE_DEPOSIT || $object->type == FactureFournisseur::TYPE_PROFORMA || $object->type == FactureFournisseur::TYPE_SITUATION) && (getDolGlobalString('SUPPLIER_INVOICE_ENABLE_NEGATIVE') || $object->total_ttc >= 0)) // @phan-suppress-current-line PhanDeprecatedClassConstant
4512 || ($object->type == FactureFournisseur::TYPE_CREDIT_NOTE && $object->total_ttc <= 0))) {
4513 // if (count($object->lines)) { // already tested in condition
4514 if ($usercanvalidate) {
4515 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=valid&token='.newToken().'"';
4516 print '>'.$langs->trans('Validate').'</a>';
4517 } else {
4518 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'"';
4519 print '>'.$langs->trans('Validate').'</a>';
4520 }
4521 //}
4522 }
4523
4524 // Send by mail
4525 if (empty($user->socid)) {
4527 if ($usercansend) {
4528 print dolGetButtonAction('', $langs->trans('SendMail'), 'email', dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id, 'action' => 'presend', 'mode' => 'init'], true).'#formmailbeforetitle', '');
4529 } else {
4530 print dolGetButtonAction('', $langs->trans('SendMail'), 'email', '#', '', false);
4531 }
4532 }
4533 }
4534
4535 // Request a direct debit order
4536 if ($object->status > FactureFournisseur::STATUS_DRAFT && $object->paid == 0) {
4537 $langs->load("withdrawals");
4538 if ($resteapayer > 0) {
4539 if ($usercancreatecreditransfer) {
4540 if (!$objectidnext && $object->close_code != 'replaced') { // Not replaced by another invoice
4541 print '<a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/prelevement.php?facid='.$object->id.'&type=bank-transfer" title="'.dol_escape_htmltag($langs->trans("MakeBankTransferOrder")).'">'.$langs->trans("MakeBankTransferOrder").'</a>';
4542 } else {
4543 print '<span class="butActionRefused classfortooltip" title="'.$langs->trans("DisabledBecauseReplacedInvoice").'">'.$langs->trans('MakeBankTransferOrder').'</span>';
4544 }
4545 } else {
4546 //print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("MakeWithdrawRequest").'</a>';
4547 }
4548 } else {
4549 //print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("AmountMustBePositive")).'">'.$langs->trans("MakeWithdrawRequest").'</a>';
4550 }
4551 }
4552
4553 // Create payment
4554 if ($object->type != FactureFournisseur::TYPE_CREDIT_NOTE && $object->status == FactureFournisseur::STATUS_VALIDATED && $object->paid == 0 && $usercancreate) {
4555 print '<a class="butAction" href="'.DOL_URL_ROOT.'/fourn/facture/paiement.php?facid='.$object->id.'&action=create'.($object->fk_account > 0 ? '&accountid='.$object->fk_account : '').'">'.$langs->trans('DoPayment').'</a>'; // must use facid because id is for payment id not invoice
4556 }
4557
4558 // Reverse back money or convert to reduction
4560 // For credit note only
4561 if ($object->type == FactureFournisseur::TYPE_CREDIT_NOTE && $object->status == 1 && $object->paid == 0) {
4562 if ($resteapayer == 0) {
4563 print '<span class="butActionRefused classfortooltip" title="'.$langs->trans("DisabledBecauseRemainderToPayIsZero").'">'.$langs->trans('DoPaymentBack').'</span>';
4564 } elseif ($usercancreate) {
4565 print '<a class="butAction" href="'.DOL_URL_ROOT.'/fourn/facture/paiement.php?facid='.$object->id.'&action=create&accountid='.$object->fk_account.'">'.$langs->trans('DoPaymentBack').'</a>';
4566 }
4567 }
4568
4569 // For standard invoice with excess paid
4570 if ($object->type == FactureFournisseur::TYPE_STANDARD && empty($object->paid) && ($object->total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits) < 0 && $usercancreate && empty($discount->id)) {
4571 print '<a class="butAction'.($conf->use_javascript_ajax ? ' reposition' : '').'" href="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'&action=converttoreduc&token='.newToken().'">'.$langs->trans('ConvertExcessPaidToReduc').'</a>';
4572 }
4573 // For credit note
4574 if ($object->type == FactureFournisseur::TYPE_CREDIT_NOTE && $object->status == 1 && $object->paid == 0 && $usercancreate
4575 && (getDolGlobalString('SUPPLIER_INVOICE_ALLOW_REUSE_OF_CREDIT_WHEN_PARTIALLY_REFUNDED') || $object->getSommePaiement() == 0)
4576 ) {
4577 print '<a class="butAction'.($conf->use_javascript_ajax ? ' reposition' : '').'" href="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'&action=converttoreduc&token='.newToken().'" title="'.dol_escape_htmltag($langs->trans("ConfirmConvertToReducSupplier2")).'">'.$langs->trans('ConvertToReduc').'</a>';
4578 }
4579 // For deposit invoice
4580 if ($object->type == FactureFournisseur::TYPE_DEPOSIT && $usercancreate && $object->status > 0 && empty($discount->id)) {
4581 print '<a class="butAction'.($conf->use_javascript_ajax ? ' reposition' : '').'" href="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'&action=converttoreduc&token='.newToken().'">'.$langs->trans('ConvertToReduc').'</a>';
4582 }
4583 }
4584
4585 // Classify paid
4586 if ($object->status == FactureFournisseur::STATUS_VALIDATED && $object->paid == 0 && (
4587 ($object->type != FactureFournisseur::TYPE_CREDIT_NOTE && $object->type != FactureFournisseur::TYPE_DEPOSIT && ($resteapayer <= 0 || (getDolGlobalString('SUPPLIER_INVOICE_CAN_SET_PAID_EVEN_IF_PARTIALLY_PAID') && $object->total_ttc == $resteapayer))) ||
4588 ($object->type == FactureFournisseur::TYPE_CREDIT_NOTE && $resteapayer >= 0) ||
4589 ($object->type == FactureFournisseur::TYPE_DEPOSIT && $object->total_ttc > 0 && ($resteapayer == 0 || (getDolGlobalString('SUPPLIER_INVOICE_CAN_SET_PAID_EVEN_IF_PARTIALLY_PAID') && $object->total_ttc == $resteapayer)))
4590 )
4591 ) {
4592 print '<a class="butAction'.($conf->use_javascript_ajax ? ' reposition' : '').'" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=paid&token='.newToken().'">'.$langs->trans('ClassifyPaid').'</a>';
4593 }
4594
4595 // Classify 'closed not completely paid' (possible if validated and not yet filed paid)
4596 if ($object->status == FactureFournisseur::STATUS_VALIDATED && $object->paid == 0 && $resteapayer > 0 && (!getDolGlobalString('SUPPLIER_INVOICE_CAN_SET_PAID_EVEN_IF_PARTIALLY_PAID') || $object->total_ttc != $resteapayer)) {
4597 if ($totalpaid > 0 || $totalcreditnotes > 0) {
4598 // If one payment or one credit note was linked to this invoice
4599 print '<a class="butAction'.($conf->use_javascript_ajax ? ' reposition' : '').'" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=paid&token='.newToken().'">'.$langs->trans('ClassifyPaidPartially').'</a>';
4600 } else {
4601 if (!getDolGlobalString('INVOICE_CAN_NEVER_BE_CANCELED')) {
4602 print '<a class="butAction'.($conf->use_javascript_ajax ? ' reposition' : '').'" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=canceled&token='.newToken().'">'.$langs->trans('ClassifyCanceled').'</a>';
4603 }
4604 }
4605 }
4606
4607 // Create event
4608 /*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.
4609 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>';
4610 }*/
4611
4612 // Create a credit note
4613 if (($object->type == FactureFournisseur::TYPE_STANDARD || $object->type == FactureFournisseur::TYPE_DEPOSIT) && $object->status > 0 && $usercancreate) {
4614 if (!$objectidnext) {
4615 print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?socid='.$object->socid.'&amp;fac_avoir='.$object->id.'&action=create&type=2'.($object->fk_project > 0 ? '&amp;projectid='.$object->fk_project : '').'">'.$langs->trans("CreateCreditNote").'</a>';
4616 }
4617 }
4618
4619 // Clone
4620 if ($action != 'edit' && $usercancreate) {
4621 print '<a class="butAction butActionClone" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=clone&socid='.$object->socid.'&token='.newToken().'">'.$langs->trans('ToClone').'</a>';
4622 }
4623
4624 // Clone as predefined / Create template
4625 if (($object->type == FactureFournisseur::TYPE_STANDARD || $object->type == FactureFournisseur::TYPE_DEPOSIT) && $object->status == 0 && $usercancreate) {
4626 if (!$objectidnext && count($object->lines) > 0) {
4627 print '<a class="butAction" href="'.DOL_URL_ROOT.'/fourn/facture/card-rec.php?facid='.$object->id.'&action=create">'.$langs->trans("ChangeIntoRepeatableInvoice").'</a>';
4628 }
4629 }
4630
4631 // Delete
4632 if ($action != 'confirm_edit' && $usercandelete) {
4633 $isErasable = $object->is_erasable();
4634
4635 $enableDelete = false;
4636 $htmltooltip = '';
4637 $params = (empty($conf->use_javascript_ajax) ? array() : array('attr' => array('class' => 'reposition')));
4638 //var_dump($isErasable); var_dump($params);
4639 if ($isErasable == -4) {
4640 $htmltooltip = $langs->trans("DisabledBecausePayments");
4641 } elseif ($isErasable == -3) { // Should never happen with supplier invoice
4642 $htmltooltip = $langs->trans("DisabledBecauseNotLastSituationInvoice");
4643 } elseif ($isErasable == -2) { // Should never happen with supplier invoice
4644 $htmltooltip = $langs->trans("DisabledBecauseNotLastInvoice");
4645 } elseif ($isErasable == -1) {
4646 $htmltooltip = $langs->trans("DisabledBecauseDispatchedInBookkeeping");
4647 } elseif ($isErasable <= 0) { // Any other cases
4648 $htmltooltip = $langs->trans("DisabledBecauseNotErasable");
4649 } else {
4650 $enableDelete = true;
4651 $htmltooltip = '';
4652 }
4653 print dolGetButtonAction($htmltooltip, $langs->trans("Delete"), 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken(), (string) $object->id, $enableDelete, $params);
4654 }
4655 print '</div>';
4656
4657 if ($action != 'confirm_edit') {
4658 print '<div class="fichecenter"><div class="fichehalfleft">';
4659
4660 /*
4661 * Generated documents
4662 */
4663 $ref = dol_sanitizeFileName($object->ref);
4664 $subdir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier').$ref;
4665 $filedir = getMultidirOutput($object).'/'.$subdir;
4666 $urlsource = $_SERVER['PHP_SELF'].'?id='.$object->id;
4667 $genallowed = $usercanread;
4668 $delallowed = $usercancreate;
4669 $modelpdf = (empty($object->model_pdf) ? getDolGlobalString('INVOICE_SUPPLIER_ADDON_PDF') : $object->model_pdf);
4670 $genifempty = 0;
4671
4672 print $formfile->showdocuments('facture_fournisseur', $subdir, $filedir, $urlsource, (int) $genallowed, (int) $delallowed, $modelpdf, $genifempty, 0, 0, 40, 0, '', '', '', $societe->default_lang);
4673 $somethingshown = $formfile->numoffiles;
4674
4675 // Show links to link elements
4676 $tmparray = $form->showLinkToObjectBlock($object, array(), array('invoice_supplier'), 1);
4677 $linktoelem = $tmparray['linktoelem'];
4678 $htmltoenteralink = $tmparray['htmltoenteralink'];
4679 print $htmltoenteralink;
4680
4681 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
4682
4683 print '</div><div class="fichehalfright">';
4684
4685 // List of actions on element
4686 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
4687 $formactions = new FormActions($db);
4688 $somethingshown = $formactions->showactions($object, 'invoice_supplier', $socid, 1, 'listaction'.($genallowed ? 'largetitle' : ''));
4689
4690 print '</div></div>';
4691 }
4692 }
4693 }
4694
4695 // Select mail models is same action as presend
4696 if (GETPOST('modelselected')) {
4697 $action = 'presend';
4698 }
4699
4700 // Presend form
4701 $modelmail = 'invoice_supplier_send';
4702 $defaulttopic = 'SendBillRef';
4703 $diroutput = getMultidirOutput($object);
4704 $autocopy = 'MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO';
4705 $trackid = 'sinv'.$object->id;
4706
4707 include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
4708 }
4709}
4710
4711
4712// End of page
4713llxFooter();
4714$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 bank accounts.
Class to manage accounting journals.
const TYPE_PROFORMA
Proforma invoice.
const TYPE_SITUATION
Situation invoice.
Class to manage absolute discounts.
Class to manage a WYSIWYG editor.
Class to manage warehouses.
Class to manage standard extra fields.
Class to manage suppliers invoices.
const TYPE_DEPOSIT
Deposit invoice.
const TYPE_CREDIT_NOTE
Credit note invoice.
const TYPE_REPLACEMENT
Replacement invoice.
const STATUS_VALIDATED
Validated (need to be paid)
const TYPE_STANDARD
Standard invoice.
const STATUS_ABANDONED
Classified abandoned and no payment done.
const STATUS_CLOSED
Classified paid.
Class to manage invoice templates.
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 with static methods for building HTML components related to products Only components common to ...
Class to manage building of HTML components.
Class to manage payments for supplier invoices.
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 to manage translations.
isInEEC($object)
Return if a country of an object is inside the EEC (European Economic Community)
global $mysoc
dol_get_last_hour($date, $gm='tzserver')
Return GMT time for last hour of a given GMT date (it replaces hours, min and second part to 23:59:59...
Definition date.lib.php:651
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:126
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:
facturefourn_prepare_head(FactureFournisseur $object)
Prepare array with list of tabs.
Definition fourn.lib.php:38
dol_now($mode='gmt')
Return date for now.
recordNotFound($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Displays an error page when a record is not found.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolBuildUrl($url, $params=[], $addtoken=false, $anchor='')
Return path of url.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
getMultidirOutput($object, $module='', $forobject=0, $mode='output')
Return the full path of the directory where a module (or an object of a module) stores its files.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTFLOAT($paramname, $rounding='', $option=2)
Return the value of a $_GET or $_POST supervariable, converted into float.
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that returns whether VAT must be recoverable collected VAT (e.g.: VAT NPR in France)
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_clone($srcobject, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) VAT...
getDictionaryValue($tablename, $field, $id, $checkentity=false, $rowidfield='rowid')
Return the value of a filed into a dictionary for the record $id.
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,...
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
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.
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
Definition html.lib.php:519
dol_get_fiche_end($notab=0)
Return tab footer of a card.
Definition html.lib.php:717
dolGetButtonAction($label, $text='', $actionType='default', $url='', $id='', $userRight=1, $params=array())
Function dolGetButtonAction.
dol_htmloutput_events($disabledoutputofmessages=0)
Print formatted messages to output (Used to show messages on html output).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='', $cssfordropdown='info_admin')
Show information in HTML for admin users or standard users.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
Definition html.lib.php:172
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.