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