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