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