dolibarr 22.0.5
paiement.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2003-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
4 * Copyright (C) 2004-2020 Laurent Destailleur <eldy@users.sourceforge.net>
5 * Copyright (C) 2004 Christophe Combelles <ccomb@free.fr>
6 * Copyright (C) 2005 Marc Barilley / Ocebo <marc@ocebo.com>
7 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
8 * Copyright (C) 2014 Teddy Andreotti <125155@supinfo.com>
9 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
10 * Copyright (C) 2015 Juanjo Menent <jmenent@2byte.es>
11 * Copyright (C) 2017 Alexandre Spangaro <aspangaro@open-dsi.fr>
12 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
13 * Copyright (C) 2021 Charlene Benke <charlene@patas-monkey.com>
14 * Copyright (C) 2022 Udo Tamm <dev@dolibit.de>
15 * Copyright (C) 2023 Sylvain Legrand <technique@infras.fr>
16 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 3 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program. If not, see <https://www.gnu.org/licenses/>.
30 */
31
38// Load Dolibarr environment
39require '../../main.inc.php';
40require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php';
41require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
42require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php';
43require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
44require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
45require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
46
55// Load translation files required by the page
56$langs->loadLangs(array('companies', 'bills', 'banks', 'compta'));
57
58$action = GETPOST('action', 'alpha');
59$confirm = GETPOST('confirm', 'alpha');
60$optioncss = GETPOST('optioncss', 'alpha');
61$cancel = GETPOST('cancel', 'alpha');
62$backtopage = GETPOST('backtopage', 'alpha');
63$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
64
65$facid = GETPOSTINT('facid');
66$socid = GETPOSTINT('socid');
67$accountid = GETPOSTINT('accountid');
68$day = GETPOSTINT('day');
69$month = GETPOSTINT('month');
70$year = GETPOSTINT('year');
71
72$search_ref = GETPOST('search_ref', 'alpha');
73$search_account = GETPOST('search_account', 'alpha');
74$search_paymenttype = GETPOST('search_paymenttype');
75$search_amount = GETPOST('search_amount', 'alpha'); // alpha because we must be able to search on "< x"
76$search_company = GETPOST('search_company', 'alpha');
77$search_payment_num = GETPOST('search_payment_num', 'alpha');
78
79$displayAllInvoices = getDolGlobalInt('MAIN_PAIMENTS_SHOW_ALL_INVOICE_TYPES', 0);
80if (GETPOSTISSET('display-all-invoices')) {
81 $displayAllInvoices = GETPOSTINT('display-all-invoices');
82}
83
84$limit = GETPOSTINT('limit') ? GETPOST('limit') : $conf->liste_limit;
85$sortfield = GETPOST('sortfield', 'aZ09comma');
86$sortorder = GETPOST('sortorder', 'aZ09comma');
87$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
88if (empty($page) || $page == -1) {
89 $page = 0;
90} // If $page is not defined, or '' or -1
91$offset = $limit * $page;
92$pageprev = $page - 1;
93$pagenext = $page + 1;
94if (!$sortorder) {
95 $sortorder = "DESC";
96}
97if (!$sortfield) {
98 $sortfield = "p.rowid";
99}
100
101$amounts = array();
102$amountsresttopay = array();
103$addwarning = 0;
104
105$multicurrency_amounts = array();
106$multicurrency_amountsresttopay = array();
107
108// Security check
109if ($user->socid > 0) {
110 $socid = $user->socid;
111}
112
113$object = new PaiementFourn($db);
114
115// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
116$hookmanager->initHooks(array('paymentsupplierlist'));
117$extrafields = new ExtraFields($db);
118
119// fetch optionals attributes and labels
120$extrafields->fetch_name_optionals_label($object->table_element);
121
122$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
123
124$arrayfields = array();
125
126$permissiontoadd = ($user->hasRight("fournisseur", "facture", "creer") || $user->hasRight("supplier_invoice", "creer"));
127
128
129/*
130 * Actions
131 */
132$error = 0;
133
134if ($cancel) {
135 if (!empty($backtopageforcancel)) {
136 header("Location: ".$backtopageforcancel);
137 exit;
138 } elseif (!empty($backtopage)) {
139 header("Location: ".$backtopage);
140 exit;
141 }
142 header("Location: ".DOL_URL_ROOT.'/fourn/facture/list.php');
143 exit;
144}
145
146if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
147 $search_ref = "";
148 $search_account = "";
149 $search_amount = "";
150 $search_paymenttype = "";
151 $search_payment_num = "";
152 $search_company = "";
153 $day = '';
154 $year = '';
155 $month = '';
156 $search_array_options = array();
157}
158
159$parameters = array('socid' => $socid);
160$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
161if ($reshook < 0) {
162 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
163}
164
165$formquestion = array();
166if (empty($reshook)) {
167 if (($action == 'add_paiement' || ($action == 'confirm_paiement' && $confirm == 'yes')) && $permissiontoadd) {
168 $datepaye = GETPOSTDATE('re', '12:00:00');
169 $paiement_id = 0;
170 $totalpayment = 0;
171 $atleastonepaymentnotnull = 0;
172 $multicurrency_totalpayment = 0;
173
174 // Generate payment array and check if there is payment higher than invoice and payment date before invoice date
175 $tmpinvoice = new FactureFournisseur($db);
176 $i = 0;
177 foreach ($_POST as $key => $value) {
178 if (substr($key, 0, 7) == 'amount_') {
179 $cursorfacid = (int) substr($key, 7);
180 $amounts[$cursorfacid] = price2num(GETPOST($key));
181 if (!empty($amounts[$cursorfacid])) {
182 $atleastonepaymentnotnull++;
183 if (is_numeric($amounts[$cursorfacid])) {
184 $totalpayment += (float) $amounts[$cursorfacid];
185 } else {
186 setEventMessages($langs->transnoentities("InputValueIsNotAnNumber", GETPOST($key)), null, 'warnings');
187 }
188 }
189 $result = $tmpinvoice->fetch($cursorfacid);
190 if ($result <= 0) {
191 dol_print_error($db);
192 }
193 $amountsresttopay[$cursorfacid] = price2num($tmpinvoice->total_ttc - $tmpinvoice->getSommePaiement());
194 if ($amounts[$cursorfacid]) {
195 // Check amount
196 if ((abs((float) $amounts[$cursorfacid]) > abs((float) $amountsresttopay[$cursorfacid]))) {
197 $addwarning = 1;
198 $formquestion['text'] = img_warning($langs->trans("PaymentHigherThanReminderToPaySupplier")).' '.$langs->trans("HelpPaymentHigherThanReminderToPaySupplier");
199 }
200 // Check date
201 if ($datepaye && ($datepaye < $tmpinvoice->date)) {
202 $langs->load("errors");
203 //$error++;
204 setEventMessages($langs->transnoentities("WarningPaymentDateLowerThanInvoiceDate", dol_print_date($datepaye, 'day'), dol_print_date($tmpinvoice->date, 'day'), $tmpinvoice->ref), null, 'warnings');
205 }
206 }
207
208 $formquestion[$i++] = array('type' => 'hidden', 'name' => $key, 'value' => GETPOST($key));
209 } elseif (substr($key, 0, 21) == 'multicurrency_amount_') {
210 $cursorfacid = (int) substr($key, 21);
211 $multicurrency_amounts[$cursorfacid] = (GETPOST($key) ? price2num(GETPOST($key)) : 0);
212 $multicurrency_totalpayment += $multicurrency_amounts[$cursorfacid];
213 if (!empty($multicurrency_amounts[$cursorfacid])) {
214 $atleastonepaymentnotnull++;
215 }
216 $result = $tmpinvoice->fetch($cursorfacid);
217 if ($result <= 0) {
218 dol_print_error($db);
219 }
220 $multicurrency_amountsresttopay[$cursorfacid] = price2num($tmpinvoice->multicurrency_total_ttc - $tmpinvoice->getSommePaiement(1));
221 if ($multicurrency_amounts[$cursorfacid]) {
222 // Check amount
223 if ((abs((float) $multicurrency_amounts[$cursorfacid]) > abs((float) $multicurrency_amountsresttopay[$cursorfacid]))) {
224 $addwarning = 1;
225 $formquestion['text'] = img_warning($langs->trans("PaymentHigherThanReminderToPaySupplier")).' '.$langs->trans("HelpPaymentHigherThanReminderToPaySupplier");
226 }
227 // Check date
228 if ($datepaye && ($datepaye < $tmpinvoice->date)) {
229 $langs->load("errors");
230 //$error++;
231 setEventMessages($langs->transnoentities("WarningPaymentDateLowerThanInvoiceDate", dol_print_date($datepaye, 'day'), dol_print_date($tmpinvoice->date, 'day'), $tmpinvoice->ref), null, 'warnings');
232 }
233 }
234
235 $formquestion[$i++] = array('type' => 'hidden', 'name' => $key, 'value' => GETPOSTFLOAT($key));
236 }
237 }
238
239 // Check parameters
240 if (GETPOST('paiementid') <= 0) {
241 setEventMessages($langs->transnoentities('ErrorFieldRequired', $langs->transnoentities('PaymentMode')), null, 'errors');
242 $error++;
243 }
244
245 if (isModEnabled("bank")) {
246 // If bank module is on, account is required to enter a payment
247 if (GETPOST('accountid') <= 0) {
248 setEventMessages($langs->transnoentities('ErrorFieldRequired', $langs->transnoentities('AccountToCredit')), null, 'errors');
249 $error++;
250 }
251 }
252
253 if (empty($totalpayment) && empty($multicurrency_totalpayment) && empty($atleastonepaymentnotnull)) {
254 setEventMessages($langs->transnoentities('ErrorFieldRequired', $langs->trans('PaymentAmount')), null, 'errors');
255 $error++;
256 }
257
258 if (empty($datepaye)) {
259 setEventMessages($langs->transnoentities('ErrorFieldRequired', $langs->transnoentities('Date')), null, 'errors');
260 $error++;
261 }
262
263 // Check if payments in both currency
264 if ($totalpayment > 0 && $multicurrency_totalpayment > 0) {
265 setEventMessages($langs->transnoentities('ErrorPaymentInBothCurrency'), null, 'errors');
266 $error++;
267 }
268 }
269
270 /*
271 * Action add_paiement
272 */
273 if ($action == 'add_paiement') { // Test on permission not required
274 if ($error) {
275 $action = 'create';
276 }
277 // All the next of this action is displayed at the page's bottom.
278 }
279
280
281 /*
282 * Action confirm_paiement
283 */
284 if ($action == 'confirm_paiement' && $confirm == 'yes' && $permissiontoadd) {
285 $datepaye = dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
286
287 $multicurrency_code = array();
288 $multicurrency_tx = array();
289
290 // Clean parameters amount if payment is for a credit note
291 foreach ($amounts as $key => $value) { // How payment is dispatched
292 $tmpinvoice = new FactureFournisseur($db);
293 $tmpinvoice->fetch($key);
294 if ($tmpinvoice->type == FactureFournisseur::TYPE_CREDIT_NOTE) {
295 $newvalue = price2num($value, 'MT');
296 $amounts[$key] = - abs((float) $newvalue);
297 }
298 $multicurrency_code[$key] = $tmpinvoice->multicurrency_code;
299 $multicurrency_tx[$key] = $tmpinvoice->multicurrency_tx;
300 }
301
302 foreach ($multicurrency_amounts as $key => $value) { // How payment is dispatched
303 $tmpinvoice = new FactureFournisseur($db);
304 $tmpinvoice->fetch($key);
305 if ($tmpinvoice->type == FactureFournisseur::TYPE_CREDIT_NOTE) {
306 $newvalue = price2num($value, 'MT');
307 $multicurrency_amounts[$key] = - abs((float) $newvalue);
308 }
309 $multicurrency_code[$key] = $tmpinvoice->multicurrency_code;
310 $multicurrency_tx[$key] = $tmpinvoice->multicurrency_tx;
311 }
312
313 if (!$error) {
314 $db->begin();
315
316 $thirdparty = new Societe($db);
317 if ($socid > 0) {
318 $thirdparty->fetch($socid);
319 }
320
321 // Creation of payment line
322 $paiement = new PaiementFourn($db);
323 $paiement->datepaye = $datepaye;
324
325 $correctedAmounts = [];
326 foreach ($amounts as $key => $value) {
327 $correctedAmounts[$key] = (float) $value;
328 }
329
330 $paiement->amounts = $correctedAmounts; // Array of amounts
331 $paiement->multicurrency_amounts = $multicurrency_amounts;
332 $paiement->multicurrency_code = $multicurrency_code; // Array with all currency of payments dispatching
333 $paiement->multicurrency_tx = $multicurrency_tx; // Array with all currency tx of payments dispatching
334 $paiement->paiementid = GETPOSTINT('paiementid');
335 $paiement->num_payment = GETPOST('num_paiement', 'alphanohtml');
336 $paiement->note_private = GETPOST('comment', 'alpha');
337 $paiement->fk_account = GETPOSTINT('accountid');
338
339 // Create payment and update this->multicurrency_amounts if this->amounts filled or
340 // this->amounts if this->multicurrency_amounts filled.
341 // This also set ->amount and ->multicurrency_amount
342 $paiement_id = $paiement->create($user, (GETPOST('closepaidinvoices') == 'on' ? 1 : 0), $thirdparty);
343 if ($paiement_id < 0) {
344 setEventMessages($paiement->error, $paiement->errors, 'errors');
345 $error++;
346 }
347
348 if (!$error) {
349 $result = $paiement->addPaymentToBank($user, 'payment_supplier', '(SupplierInvoicePayment)', $accountid, GETPOST('chqemetteur'), GETPOST('chqbank'));
350 if ($result < 0) {
351 setEventMessages($paiement->error, $paiement->errors, 'errors');
352 $error++;
353 }
354 }
355
356 if (!$error) {
357 $db->commit();
358
359 // If payment dispatching on more than one invoice, we stay on summary page, otherwise go on invoice card
360 $invoiceid = 0;
361 foreach ($paiement->amounts as $key => $amount) {
362 $facid = $key;
363 if (is_numeric($amount) && $amount != 0) {
364 if ($invoiceid != 0) {
365 $invoiceid = -1; // There is more than one invoice paid by this payment
366 } else {
367 $invoiceid = $facid;
368 }
369 }
370 }
371 if ($invoiceid > 0) {
372 $loc = DOL_URL_ROOT.'/fourn/facture/card.php?facid='.$invoiceid;
373 } else {
374 $loc = DOL_URL_ROOT.'/fourn/paiement/card.php?id='.$paiement_id;
375 }
376 header('Location: '.$loc);
377 exit;
378 } else {
379 $db->rollback();
380 }
381 }
382 }
383}
384
385
386/*
387 * View
388 */
389
390$form = new Form($db);
391$formother = new FormOther($db);
392
393$supplierstatic = new Societe($db);
394$invoicesupplierstatic = new FactureFournisseur($db);
395
396llxHeader('', $langs->trans('ListPayment'), '', '', 0, 0, '', '', '', 'mod-fourn-facture page-paiement');
397
398if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paiement') {
399 $object = new FactureFournisseur($db);
400 $result = $object->fetch($facid);
401
402 $datefacture = dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
403 $dateinvoice = ($datefacture == '' ? (!getDolGlobalString('MAIN_AUTOFILL_DATE') ? -1 : '') : $datefacture);
404
405 $sql = 'SELECT s.nom as name, s.rowid as socid,';
406 $sql .= ' f.rowid, f.ref, f.ref_supplier, f.total_ttc as total, f.fk_mode_reglement, f.fk_account';
407 if (!$user->hasRight("societe", "client", "voir") && !$socid) {
408 $sql .= ", sc.fk_soc, sc.fk_user ";
409 }
410 $sql .= ' FROM '.MAIN_DB_PREFIX.'societe as s, '.MAIN_DB_PREFIX.'facture_fourn as f';
411 if (!$user->hasRight("societe", "client", "voir") && !$socid) {
412 $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
413 }
414 $sql .= ' WHERE f.fk_soc = s.rowid';
415 $sql .= ' AND f.rowid = '.((int) $facid);
416 if (!$user->hasRight("societe", "client", "voir") && !$socid) {
417 $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
418 }
419 $resql = $db->query($sql);
420 if ($resql) {
421 $totalnboflines = $num = $db->num_rows($resql);
422 if ($num) {
423 $obj = $db->fetch_object($resql);
424 $total = $obj->total;
425
426 print load_fiche_titre($langs->trans('DoPayment'));
427
428 // Add realtime total information
429 if (!empty($conf->use_javascript_ajax)) {
430 print "\n".'<script type="text/javascript">';
431 print '$(document).ready(function () {
432
433 function _elemToJson(selector)
434 {
435 var subJson = {};
436 $.map(selector.serializeArray(), function(n,i)
437 {
438 subJson[n["name"]] = n["value"];
439 });
440
441 return subJson;
442 }
443 function callForResult(imgId)
444 {
445 console.log("callForResult Calculate total of payment");
446 var json = {};
447 var form = $("#payment_form");
448
449 json["invoice_type"] = $("#invoice_type").val();
450 json["amountPayment"] = $("#amountpayment").attr("value");
451 json["amounts"] = _elemToJson(form.find("input.amount"));
452 json["remains"] = _elemToJson(form.find("input.remain"));
453 json["token"] = "'.currentToken().'";
454 if (imgId != null) {
455 json["imgClicked"] = imgId;
456 }
457
458 $.post("'.DOL_URL_ROOT.'/compta/ajaxpayment.php", json, function(data)
459 {
460 json = $.parseJSON(data);
461
462 form.data(json);
463
464 for (var key in json)
465 {
466 if (key == "result") {
467 if (json["makeRed"]) {
468 $("#"+key).addClass("error");
469 } else {
470 $("#"+key).removeClass("error");
471 }
472 json[key]=json["label"]+" "+json[key];
473 $("#"+key).text(json[key]);
474 } else {console.log(key);
475 form.find("input[name*=\""+key+"\"]").each(function() {
476 $(this).attr("value", json[key]);
477 });
478 }
479 }
480 });
481 }
482 callForResult();
483 $("#payment_form").find("input.amount").change(function() {
484 callForResult();
485 });
486 $("#payment_form").find("input.amount").keyup(function() {
487 callForResult();
488 });
489 ';
490
491 print ' });'."\n";
492
493 //Add js for AutoFill
494 print ' $(document).ready(function () {';
495 print ' $(".AutoFillAmount").on(\'click touchstart\', function(e){
496 e.preventDefault();
497 $("input[name="+$(this).data(\'rowname\')+"]").val($(this).data("value")).trigger("change");
498 });';
499 print ' });'."\n";
500
501 print ' </script>'."\n";
502 }
503
504 print '<form id="payment_form" name="addpaiement" action="'.$_SERVER["PHP_SELF"].'" method="POST">';
505 print '<input type="hidden" name="token" value="'.newToken().'">';
506 print '<input type="hidden" name="action" value="add_paiement">';
507 print '<input type="hidden" name="display-all-invoices" value="'.(int) $displayAllInvoices.'">';
508 print '<input type="hidden" name="facid" value="'.$facid.'">';
509 print '<input type="hidden" name="ref_supplier" value="'.$obj->ref_supplier.'">';
510 print '<input type="hidden" name="socid" value="'.$obj->socid.'">';
511 print '<input type="hidden" name="type" id="invoice_type" value="'.$object->type.'">';
512 print '<input type="hidden" name="societe" value="'.$obj->name.'">';
513
514 print dol_get_fiche_head([]);
515
516 print '<table class="border centpercent">';
517
518 print '<tr><td class="fieldrequired titlefieldcreate">'.$langs->trans('Company').'</td><td>';
519 $supplierstatic->id = $obj->socid;
520 $supplierstatic->name = $obj->name;
521 print $supplierstatic->getNomUrl(1, 'supplier');
522 print '</td></tr>';
523
524 print '<tr><td class="fieldrequired">'.$langs->trans('Date').'</td><td>';
525 // $object is default vendor invoice
526 $adddateof = array(array('adddateof' => $object->date));
527 $adddateof[] = array('adddateof' => $object->date_echeance, 'labeladddateof' => $langs->transnoentities('DateDue'));
528 print $form->selectDate($dateinvoice, '', 0, 0, 0, "addpaiement", 1, 1, 0, '', '', $adddateof);
529 print '</td></tr>';
530 print '<tr><td class="fieldrequired">'.$langs->trans('PaymentMode').'</td><td>';
531 $form->select_types_paiements(!GETPOST('paiementid') ? $obj->fk_mode_reglement : GETPOST('paiementid'), 'paiementid');
532 print '</td>';
533 if (isModEnabled("bank")) {
534 print '<tr><td class="fieldrequired">'.$langs->trans('Account').'</td><td>';
535 print img_picto('', 'bank_account', 'class="pictofixedwidth"');
536 print $form->select_comptes(empty($accountid) ? $obj->fk_account : $accountid, 'accountid', 0, '', 2, '', 0, 'widthcentpercentminusx maxwidth500', 1);
537 print '</td></tr>';
538 } else {
539 print '<tr><td>&nbsp;</td></tr>';
540 }
541 print '<tr><td>'.$langs->trans('Numero').'</td><td><input name="num_paiement" type="text" value="'.(!GETPOST('num_paiement') ? '' : GETPOST('num_paiement')).'"></td></tr>';
542 print '<tr><td>'.$langs->trans('Comments').'</td>';
543 print '<td class="tdtop">';
544 print '<textarea name="comment" wrap="soft" class="quatrevingtpercent" rows="'.ROWS_3.'">'.(!GETPOST('comment') ? '' : GETPOST('comment')).'</textarea></td></tr>';
545 print '</table>';
546 print dol_get_fiche_end();
547
548 $parameters = array(
549 'facid' => $facid,
550 'ref' => $obj->ref
551 );
552 $reshook = $hookmanager->executeHooks('paymentsupplierinvoices', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
553 $error = $hookmanager->error;
554 $errors = $hookmanager->errors;
555 if (empty($reshook)) {
556 /*
557 * All unpaid supplier invoices
558 */
559 $sql = 'SELECT f.rowid as facid, f.ref, f.ref_supplier, f.type, f.total_ht, f.total_ttc,';
560 $sql .= ' f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc,';
561 $sql .= ' f.datef as df, f.date_lim_reglement as dlr,';
562 $sql .= ' SUM(pf.amount) as am, SUM(pf.multicurrency_amount) as multicurrency_am';
563 $sql .= ' FROM '.MAIN_DB_PREFIX.'facture_fourn as f';
564 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'paiementfourn_facturefourn as pf ON pf.fk_facturefourn = f.rowid';
565 $sql .= ' WHERE f.entity = '.((int) $conf->entity);
566 $sql .= ' AND (f.fk_soc = '.((int) $object->socid);
567 $aux = $object->fetch_thirdparty();
568 // Can pay invoices of all child of parent company
569 if (getDolGlobalString('FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS') && !empty($object->thirdparty->parent)) {
570 $sql .= ' OR f.fk_soc IN (SELECT rowid FROM '.MAIN_DB_PREFIX.'societe WHERE parent = '.((int) $object->thirdparty->parent).')';
571 }
572 // Can pay invoices of all child of myself
573 if (getDolGlobalString('FACTURE_PAYMENTS_ON_SUBSIDIARY_COMPANIES')) {
574 $sql .= ' OR f.fk_soc IN (SELECT rowid FROM '.MAIN_DB_PREFIX.'societe WHERE parent = '.((int) $object->thirdparty->id).')';
575 }
576 $sql .= ') AND f.paye = 0';
577 $sql .= ' AND f.fk_statut = 1'; // Status=0 => unvalidated, Status=2 => canceled
578
579 if (!$displayAllInvoices) {
581 $sql .= ' AND f.type IN (0,1,3,5)'; // Standard invoice, replacement, deposit, situation
582 } else {
583 $sql .= ' AND f.type = 2'; // If paying back a credit note, we show all credit notes
584 }
585 }
586
587 // Group by because we have a total
588 $sql .= ' GROUP BY f.datef, f.ref, f.ref_supplier, f.rowid, f.type, f.total_ht, f.total_ttc,';
589 $sql .= ' f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc,';
590 $sql .= ' f.datef, f.date_lim_reglement';
591 // Sort invoices by date and serial number: the older one comes first
592 $sql .= ' ORDER BY f.datef ASC, f.ref ASC';
593
594 $resql = $db->query($sql);
595 if ($resql) {
596 $num = $db->num_rows($resql);
597 if ($num > 0) {
598 $i = 0;
599 print '<br>';
600
601 if (!empty($conf->use_javascript_ajax)) {
602 //Add js for AutoFill
603 print "\n".'<script type="text/javascript">';
604 print ' $(document).ready(function () {';
605 print ' $(".AutoFillAmount").on(\'click touchstart\', function(e){
606 e.preventDefault();
607 $("input[name="+$(this).data(\'rowname\')+"]").val($(this).data("value"));
608 });';
609 print ' });'."\n";
610 print ' </script>'."\n";
611 }
612
613 $moreHtmlRight = '';
614 if ($action == 'create') {
615 $urlToggleDisplayMod = $_SERVER["PHP_SELF"].'?facid='.((int) $facid).'&action='.urlencode($action).'&accountid='.((int) $accountid).'&display-all-invoices=' . (intval(!$displayAllInvoices));
616
617 if (empty($displayAllInvoices)) {
618 $btnTitle = $langs->trans('DisplayOtherInvoicesToo');
620 $btnTitle = $langs->trans('DisplayCreditNotesToo');
621 }
622 } else {
623 $btnTitle = $langs->trans('HideOtherInvoices');
625 $btnTitle = $langs->trans('HideCreditNotes');
626 }
627 }
628
629 $btnIcon = empty($displayAllInvoices) ? 'fa fa-eye' : 'fa fa-eye-slash';
630 $moreHtmlRight.= dolGetButtonTitle($btnTitle, '', $btnIcon, $urlToggleDisplayMod);
631 }
632
633 print_barre_liste($langs->trans('Invoices'), 0, $_SERVER["PHP_SELF"], '', '', '', '', $num, $totalnboflines, 'bill', 0, $moreHtmlRight, '', 0, 0, 0, 1);
634
635
636 print '<div class="div-table-responsive-no-min">';
637 print '<table id="fourn-invoices-paiments-list" data-display-all-invoices="' . (int) $displayAllInvoices . '" class="tagtable liste" >'."\n";
638 print '<thead>';
639 print '<tr class="liste_titre">';
640 print '<th>'.$langs->trans('Invoice').'</th>';
641 print '<th>'.$langs->trans('RefSupplier').'</th>';
642 if ($displayAllInvoices) {
643 print '<th class="center">' . $langs->trans('Type') . '</th>';
644 }
645 print '<th class="center">'.$langs->trans('Date').'</th>';
646 print '<th class="center">'.$langs->trans('DateMaxPayment').'</th>';
647 if (isModEnabled("multicurrency")) {
648 print '<th>'.$langs->trans('Currency').'</th>';
649 print '<th class="right">'.$langs->trans('MulticurrencyAmountTTC').'</th>';
650 print '<th class="right">'.$langs->trans('MulticurrencyAlreadyPaid').'</th>';
651 print '<th class="right">'.$langs->trans('MulticurrencyRemainderToPay').'</th>';
652 print '<th class="center">'.$langs->trans('MulticurrencyPaymentAmount').'</th>';
653 }
654 print '<th class="right">'.$langs->trans('AmountTTC').'</th>';
655 print '<th class="right">'.$langs->trans('AlreadyPaid').'</th>';
656 print '<th class="right">'.$langs->trans('RemainderToPay').'</th>';
657 print '<th class="center">'.$langs->trans('PaymentAmount').'</th>';
658 print '</tr>';
659 print '</thead>';
660 print '<tbody>';
661 $total = 0;
662 $total_ttc = 0;
663 $totalrecu = 0;
664 $totalrecucreditnote = 0; // PHP Warning: Undefined variable $totalrecucreditnote
665 $totalrecudeposits = 0; // PHP Warning: Undefined variable $totalrecudeposits
666 while ($i < $num) {
667 $objp = $db->fetch_object($resql);
668
669 $sign = 1;
670 if ($objp->type == FactureFournisseur::TYPE_CREDIT_NOTE && !$displayAllInvoices) {
671 $sign = -1;
672 }
673
674 $invoice = new FactureFournisseur($db);
675 $invoice->fetch($objp->facid);
676
677 $invoicesupplierstatic->ref = $objp->ref;
678 $invoicesupplierstatic->id = $objp->facid;
679
680 $paiement = $invoice->getSommePaiement();
681 $creditnotes = $invoice->getSumCreditNotesUsed();
682 $deposits = $invoice->getSumDepositsUsed();
683 $alreadypayed = price2num($paiement + $creditnotes + $deposits, 'MT');
684 $remaintopay = price2num($invoice->total_ttc - $paiement - $creditnotes - $deposits, 'MT');
685
686 // Multicurrency Price
687 $multicurrency_payment = 0;
688 $multicurrency_creditnotes = 0;
689 $multicurrency_deposits = 0;
690 $multicurrency_remaintopay = 0;
691 if (isModEnabled("multicurrency")) {
692 $multicurrency_payment = $invoice->getSommePaiement(1);
693 $multicurrency_creditnotes = $invoice->getSumCreditNotesUsed(1);
694 $multicurrency_deposits = $invoice->getSumDepositsUsed(1);
695 $multicurrency_alreadypayed = price2num($multicurrency_payment + $multicurrency_creditnotes + $multicurrency_deposits, 'MT');
696 $multicurrency_remaintopay = price2num($invoice->multicurrency_total_ttc - $multicurrency_payment - $multicurrency_creditnotes - $multicurrency_deposits, 'MT');
697 }
698
699 print '<tr data-row-type="'.$objp->type.'" class="oddeven'.(($invoice->id == $facid) ? ' highlight' : '').'">';
700
701 // Ref
702 print '<td data-col="object-name" class="nowraponall">';
703 print $invoicesupplierstatic->getNomUrl(1);
704 print '</td>';
705
706 // Ref supplier
707 print '<td data-col="ref-supplier" >'.$objp->ref_supplier.'</td>';
708
709 // type
710 if ($displayAllInvoices) {
711 $typearray = [
712 FactureFournisseur::TYPE_STANDARD => $langs->trans("InvoiceStandard"),
713 FactureFournisseur::TYPE_REPLACEMENT => $langs->trans("InvoiceReplacement"),
714 FactureFournisseur::TYPE_CREDIT_NOTE => $langs->trans("InvoiceAvoir"),
715 FactureFournisseur::TYPE_DEPOSIT => $langs->trans("InvoiceDeposit"),
716 ];
717 // Primary Secondary Success Danger Warning Info Light Dark status0 status1 status2 status3 status4 status5 status6 status7 status8 status9
718 print '<td class="center nowraponall">' . $typearray[$objp->type] . '</td>';
719 }
720
721 // Date
722 if ($objp->df > 0) {
723 print '<td data-col="datef" data-col-value="'.$db->jdate($objp->df).'" class="center nowraponall">';
724 print dol_print_date($db->jdate($objp->df), 'day').'</td>';
725 } else {
726 print '<td data-col="datef" data-col-value="" class="center"><b>!!!</b></td>';
727 }
728
729 // Date Max Payment
730 if ($objp->dlr > 0) {
731 print '<td data-col="dater" data-col-value="'.$db->jdate($objp->dlr).'" class="center nowraponall">';
732 print dol_print_date($db->jdate($objp->dlr), 'day');
733
734 if ($invoice->hasDelay()) {
735 print img_warning($langs->trans('Late'));
736 }
737
738 print '</td>';
739 } else {
740 print '<td data-col="dater" data-col-value="" class="center"><b>--</b></td>';
741 }
742
743 // Multicurrency
744 if (isModEnabled("multicurrency")) {
745 // Currency
746 print '<td data-col="multicurrency-code" class="center">'.$objp->multicurrency_code."</td>\n";
747
748 print '<td data-col="multicurrency-total-ttc" class="right">';
749 if ($objp->multicurrency_code && $objp->multicurrency_code != $conf->currency) {
750 print price($objp->multicurrency_total_ttc);
751 }
752 print '</td>';
753
754 print '<td data-col="multicurrency-payment" class="right">';
755 if ($objp->multicurrency_code && $objp->multicurrency_code != $conf->currency) {
756 print price($sign * $multicurrency_payment);
757 if ($multicurrency_creditnotes) {
758 print '+'.price($multicurrency_creditnotes);
759 }
760 if ($multicurrency_deposits) {
761 print '+'.price($multicurrency_deposits);
762 }
763 }
764 print '</td>';
765
766 print '<td data-col="remain-to-pay" class="right">';
767 if ($objp->multicurrency_code && $objp->multicurrency_code != $conf->currency) {
768 print price($sign * (float) $multicurrency_remaintopay);
769 }
770 print '</td>';
771
772 print '<td data-col="remain-to-pay-multicurrency-amount" class="right">';
773 // Add remind multicurrency amount
774 $namef = 'multicurrency_amount_'.$objp->facid;
775 $nameRemain = 'multicurrency_remain_'.$objp->facid;
776
777 $min = $max = '';
778 if ($displayAllInvoices) {
779 if ($objp->type == FactureFournisseur::TYPE_CREDIT_NOTE) {
780 $max = ' max="0" ';
781 } else {
782 $min = ' min="0" ';
783 }
784 }
785
786 if ($objp->multicurrency_code && $objp->multicurrency_code != $conf->currency) {
787 if ($action != 'add_paiement') {
788 if (!empty($conf->use_javascript_ajax)) {
789 print '<button class="btn-low-emphasis --btn-icon AutoFillAmount" data-rowname="'.$namef.'" data-value="'.($sign * (float) $multicurrency_remaintopay).'">'.img_picto("Auto fill", 'rightarrow');
790 }
791 print '<input type=hidden class="multicurrency_remain" name="'.$nameRemain.'" value="'.$multicurrency_remaintopay.'">';
792 print '<input '.$min.' '.$max.' type="text" class="multicurrency_amount width100" name="'.$namef.'" value="'.GETPOST($namef).'">';
793 } else {
794 print '<input type="text" class="width100" name="'.$namef.'_disabled" value="'.GETPOST($namef).'" disabled>';
795 print '<input type="hidden" name="'.$namef.'" value="'.GETPOST($namef).'">';
796 }
797 }
798 print "</td>";
799 }
800
801 print '<td class="right">'.price($sign * $objp->total_ttc).'</td>';
802
803 print '<td class="right">'.price($sign * $objp->am);
804 if ($creditnotes) {
805 print '+'.price($creditnotes);
806 }
807 if ($deposits) {
808 print '+'.price($deposits);
809 }
810 print '</td>';
811
812 print '<td class="right">';
813 print price($sign * (float) $remaintopay);
814 if (isModEnabled('paymentbybanktransfer')) {
815 $numdirectdebitopen = 0;
816 $totaldirectdebit = 0;
817 $sql = "SELECT COUNT(pfd.rowid) as nb, SUM(pfd.amount) as amount";
818 $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as pfd";
819 $sql .= " WHERE fk_facture_fourn = ".((int) $objp->facid);
820 $sql .= " AND pfd.traite = 0";
821 $sql .= " AND pfd.ext_payment_id IS NULL";
822
823 $result_sql = $db->query($sql);
824 if ($result_sql) {
825 $obj = $db->fetch_object($result_sql);
826 $numdirectdebitopen = $obj->nb;
827 $totaldirectdebit = $obj->amount;
828 } else {
829 dol_print_error($db);
830 }
831 if ($numdirectdebitopen) {
832 $langs->load("withdrawals");
833 print img_warning($langs->trans("WarningSomeCreditTransferAlreadyExists", $numdirectdebitopen, price(price2num($totaldirectdebit, 'MT'), 0, $langs, 1, -1, -1, $conf->currency)), '', 'classfortooltip');
834 }
835 }
836 print '</td>';
837
838 // Amount
839 print '<td class="center nowraponall">';
840
841 $namef = 'amount_'.$objp->facid;
842 $nameRemain = 'remain_'.$objp->facid;
843
844 $min = $max = '';
845 if ($displayAllInvoices) {
846 if ($objp->type == FactureFournisseur::TYPE_CREDIT_NOTE) {
847 $max = ' max="0" ';
848 } else {
849 $min = ' min="0" ';
850 }
851 }
852
853 if ($action != 'add_paiement') {
854 if (!empty($conf->use_javascript_ajax)) {
855 print '<button class="btn-low-emphasis --btn-icon AutoFillAmount" data-rowname="'.$namef.'" data-value="'.($sign * (float) $remaintopay).'">'.img_picto("Auto fill", 'rightarrow').'</button>';
856 }
857 print '<input type="hidden" class="remain" name="'.$nameRemain.'" value="'.$remaintopay.'">';
858 print '<input '.$max.' '.$min.' type="text" class="amount width100" name="'.$namef.'" value="'.dol_escape_htmltag(GETPOST($namef)).'">'; // class is required to be used by javascript callForResult();
859 } else {
860 print '<input type="text" class="width100" name="'.$namef.'_disabled" value="'.dol_escape_htmltag(GETPOST($namef)).'" disabled>';
861 print '<input type="hidden" class="amount" name="'.$namef.'" value="'.dol_escape_htmltag(GETPOST($namef)).'">'; // class is required to be used by javascript callForResult();
862 }
863 print "</td>";
864
865 print "</tr>\n";
866 $total += $objp->total_ht;
867 $total_ttc += $objp->total_ttc;
868 $totalrecu += $objp->am;
869 $totalrecucreditnote += $creditnotes;
870 $totalrecudeposits += $deposits;
871 $i++;
872 }
873 print '</tbody>';
874
875 if ($i > 1) {
876 print '<tfoot>';
877 // Print total
878 print '<tr class="liste_total">';
879 $colspan = 4;
880
881 // type
882 if ($displayAllInvoices) {
883 $colspan++;
884 }
885
886 print '<td colspan="'.$colspan.'" class="left">'.$langs->trans('TotalTTC').':</td>';
887 if (isModEnabled("multicurrency")) {
888 print '<td>&nbsp;</td>';
889 print '<td>&nbsp;</td>';
890 print '<td>&nbsp;</td>';
891 print '<td>&nbsp;</td>';
892 print '<td class="right" id="multicurrency_result" style="font-weight: bold;"></td>';
893 }
894 print '<td class="right"><b>'.price($total_ttc).'</b></td>';
895 print '<td class="right"><b>'.price($totalrecu);
896 if ($totalrecucreditnote) {
897 print '+'.price($totalrecucreditnote);
898 }
899 if ($totalrecudeposits) {
900 print '+'.price($totalrecudeposits);
901 }
902 print '</b></td>';
903 print '<td class="right"><b>'.price((float) price2num($total_ttc - $totalrecu - $totalrecucreditnote - $totalrecudeposits, 'MT')).'</b></td>';
904 print '<td class="center" id="result" style="font-weight: bold;"></td>'; // Autofilled
905 print "</tr>\n";
906 print '</tfoot>';
907 }
908 print "</table>\n";
909
910 print "</div>";
911 }
912 $db->free($resql);
913 } else {
914 dol_print_error($db);
915 }
916 }
917
918 // Save + Cancel Buttons
919 if ($action != 'add_paiement') {
920 print '<br><div class="center">';
921 print '<input type="checkbox" checked id="closepaidinvoices" name="closepaidinvoices"> <label for="closepaidinvoices">'.$langs->trans("ClosePaidInvoicesAutomatically").'</label><br>';
922 print '<input type="submit" class="button" value="'.$langs->trans('ToMakePayment').'">';
923 print ' &nbsp; <input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
924 print '</div>';
925 }
926
927 // Form to confirm payment
928 if ($action == 'add_paiement') {
929 $preselectedchoice = $addwarning ? 'no' : 'yes';
930
931 print '<br>';
932 $text = '';
933 if (!empty($totalpayment)) {
934 $text = $langs->trans('ConfirmSupplierPayment', price($totalpayment), $langs->transnoentitiesnoconv("Currency".$conf->currency));
935 }
936 if (!empty($multicurrency_totalpayment)) {
937 $text .= '<br>'.$langs->trans('ConfirmSupplierPayment', price($multicurrency_totalpayment), $langs->transnoentitiesnoconv("paymentInInvoiceCurrency"));
938 }
939 if (GETPOST('closepaidinvoices')) {
940 $text .= '<br>'.$langs->trans("AllCompletelyPayedInvoiceWillBeClosed");
941 print '<input type="hidden" name="closepaidinvoices" value="'.GETPOST('closepaidinvoices').'">';
942 }
943 print $form->formconfirm($_SERVER['PHP_SELF'].'?facid='.$object->id.'&socid='.$object->socid.'&type='.$object->type, $langs->trans('PayedSuppliersPayments'), $text, 'confirm_paiement', $formquestion, $preselectedchoice);
944 }
945
946 print '</form>';
947 }
948 } else {
949 dol_print_error($db);
950 }
951}
952
953// End of page
954llxFooter();
955$db->close();
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:67
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 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 TYPE_STANDARD
Standard invoice.
Class to manage generation of HTML components Only common components must be here.
Class permettant la generation de composants html autre Only common components are here.
Class to manage payments for supplier invoices.
Class to manage third parties objects (customers, suppliers, prospects...)
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...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
GETPOSTDATE($prefix, $hourTime='', $gm='auto', $saverestore='')
Helper function that combines values of a dolibarr DatePicker (such as Form\selectDate) for year,...
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $selectlimitsuffix=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
GETPOSTFLOAT($paramname, $rounding='')
Return the value of a $_GET or $_POST supervariable, converted into float.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79