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