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