dolibarr 21.0.3
paiement.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005 Marc Barilley / Ocebo <marc@ocebo.com>
5 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
7 * Copyright (C) 2012 Cédric Salvador <csalvador@gpcsolutions.fr>
8 * Copyright (C) 2014 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
9 * Copyright (C) 2014 Teddy Andreotti <125155@supinfo.com>
10 * Copyright (C) 2015 Juanjo Menent <jmenent@2byte.es>
11 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
12 * Copyright (C) 2023 Lenin Rivas <lenin.rivas777@gmail.com>
13 * Copyright (C) 2023 Sylvain Legrand <technique@infras.fr>
14 * Copyright (C) 2023 William Mead <william.mead@manchenumerique.fr>
15 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 3 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see <https://www.gnu.org/licenses/>.
29 */
30
37// Load Dolibarr environment
38require '../main.inc.php';
39require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
40require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
41require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
42require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
43
52// Load translation files required by the page
53$langs->loadLangs(array('companies', 'bills', 'banks', 'multicurrency'));
54
55$action = GETPOST('action', 'alpha');
56$confirm = GETPOST('confirm', 'alpha');
57
58$facid = GETPOSTINT('facid');
59$accountid = GETPOSTINT('accountid');
60$paymentnum = GETPOST('num_paiement', 'alpha');
61$socid = GETPOSTINT('socid');
62
63$sortfield = GETPOST('sortfield', 'aZ09comma');
64$sortorder = GETPOST('sortorder', 'aZ09comma');
65$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
66
67$amounts = array();
68$amountsresttopay = array();
69$addwarning = 0;
70
71$multicurrency_amounts = array();
72$multicurrency_amountsresttopay = array();
73
74// Security check
75if ($user->socid > 0) {
76 $socid = $user->socid;
77}
78
79$object = new Facture($db);
80
81// Load object
82if ($facid > 0) {
83 $ret = $object->fetch($facid);
84}
85
86// Initialize a technical object to manage hooks of paiements. Note that conf->hooks_modules contains array array
87$hookmanager->initHooks(array('paiementcard', 'globalcard'));
88
89$formquestion = array();
90
91$usercanissuepayment = $user->hasRight('facture', 'paiement');
92
93$fieldid = 'rowid';
94$isdraft = (($object->status == Facture::STATUS_DRAFT) ? 1 : 0);
95$result = restrictedArea($user, 'facture', $object->id, '', '', 'fk_soc', $fieldid, $isdraft);
96
97
98/*
99 * Actions
100 */
101$error = 0;
102
103$parameters = array('socid' => $socid);
104$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
105if ($reshook < 0) {
106 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
107}
108
109$paiement_id = 0;
110if (empty($reshook)) {
111 if (($action == 'add_paiement' || ($action == 'confirm_paiement' && $confirm == 'yes')) && $usercanissuepayment) {
112 $datepaye = dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
113 $totalpayment = 0;
114 $multicurrency_totalpayment = 0;
115 $atleastonepaymentnotnull = 0;
116 $formquestion = array();
117 $i = 0;
118
119 // Generate payment array and check if there is payment higher than invoice and payment date before invoice date
120 $tmpinvoice = new Facture($db);
121 foreach ($_POST as $key => $value) {
122 if (substr($key, 0, 7) == 'amount_' && GETPOST($key) != '') {
123 $cursorfacid = substr($key, 7);
124 $amounts[$cursorfacid] = price2num(GETPOST($key));
125 if (!empty($amounts[$cursorfacid])) {
126 $totalpayment += (float) $amounts[$cursorfacid];
127 $atleastonepaymentnotnull++;
128 }
129 $result = $tmpinvoice->fetch($cursorfacid);
130 if ($result <= 0) {
131 dol_print_error($db);
132 }
133 $amountsresttopay[$cursorfacid] = price2num($tmpinvoice->total_ttc - $tmpinvoice->getSommePaiement(0));
134 if ($amounts[$cursorfacid]) {
135 // Check amount
136 if ($amounts[$cursorfacid] && (abs((float) $amounts[$cursorfacid]) > abs((float) $amountsresttopay[$cursorfacid]))) {
137 $addwarning = 1;
138 $formquestion['text'] = img_warning($langs->trans("PaymentHigherThanReminderToPay")).' '.$langs->trans("HelpPaymentHigherThanReminderToPay");
139 }
140 // Check date
141 if ($datepaye && ($datepaye < $tmpinvoice->date)) {
142 $langs->load("errors");
143 //$error++;
144 setEventMessages($langs->transnoentities("WarningPaymentDateLowerThanInvoiceDate", dol_print_date($datepaye, 'day'), dol_print_date($tmpinvoice->date, 'day'), $tmpinvoice->ref), null, 'warnings');
145 }
146 }
147
148 $formquestion[$i++] = array('type' => 'hidden', 'name' => $key, 'value' => GETPOST($key));
149 } elseif (substr($key, 0, 21) == 'multicurrency_amount_') {
150 $cursorfacid = substr($key, 21);
151 $multicurrency_amounts[$cursorfacid] = price2num(GETPOST($key));
152 $multicurrency_totalpayment += (float) $multicurrency_amounts[$cursorfacid];
153 if (!empty($multicurrency_amounts[$cursorfacid])) {
154 $atleastonepaymentnotnull++;
155 }
156 $result = $tmpinvoice->fetch($cursorfacid);
157 if ($result <= 0) {
158 dol_print_error($db);
159 }
160 $multicurrency_amountsresttopay[$cursorfacid] = price2num($tmpinvoice->multicurrency_total_ttc - $tmpinvoice->getSommePaiement(1));
161 if ($multicurrency_amounts[$cursorfacid]) {
162 // Check amount
163 if ($multicurrency_amounts[$cursorfacid] && (abs((float) $multicurrency_amounts[$cursorfacid]) > abs((float) $multicurrency_amountsresttopay[$cursorfacid]))) {
164 $addwarning = 1;
165 $formquestion['text'] = img_warning($langs->trans("PaymentHigherThanReminderToPay")).' '.$langs->trans("HelpPaymentHigherThanReminderToPay");
166 }
167 // Check date
168 if ($datepaye && ($datepaye < $tmpinvoice->date)) {
169 $langs->load("errors");
170 //$error++;
171 setEventMessages($langs->transnoentities("WarningPaymentDateLowerThanInvoiceDate", dol_print_date($datepaye, 'day'), dol_print_date($tmpinvoice->date, 'day'), $tmpinvoice->ref), null, 'warnings');
172 }
173 }
174
175 $formquestion[$i++] = array('type' => 'hidden', 'name' => $key, 'value' => GETPOSTINT($key));
176 }
177 }
178
179 // Check parameters
180 if (!GETPOST('paiementcode')) {
181 setEventMessages($langs->transnoentities('ErrorFieldRequired', $langs->transnoentities('PaymentMode')), null, 'errors');
182 $error++;
183 }
184
185 if (isModEnabled("bank")) {
186 // If bank module is on, account is required to enter a payment
187 if (GETPOST('accountid') <= 0) {
188 setEventMessages($langs->transnoentities('ErrorFieldRequired', $langs->transnoentities('AccountToCredit')), null, 'errors');
189 $error++;
190 }
191 }
192
193 if (empty($totalpayment) && empty($multicurrency_totalpayment) && empty($atleastonepaymentnotnull)) {
194 setEventMessages($langs->transnoentities('ErrorFieldRequired', $langs->trans('PaymentAmount')), null, 'errors');
195 $error++;
196 }
197
198 if (empty($datepaye)) {
199 setEventMessages($langs->transnoentities('ErrorFieldRequired', $langs->transnoentities('Date')), null, 'errors');
200 $error++;
201 }
202
203 // Check if payments in both currency
204 if ($totalpayment > 0 && $multicurrency_totalpayment > 0) {
205 $langs->load("errors");
206 setEventMessages($langs->transnoentities('ErrorPaymentInBothCurrency'), null, 'errors');
207 $error++;
208 }
209 }
210
211 /*
212 * Action add_paiement
213 */
214 if ($action == 'add_paiement') {
215 if ($error) {
216 $action = 'create';
217 }
218 // The next of this action is displayed at the page's bottom.
219 }
220
221 /*
222 * Action confirm_paiement
223 */
224 if ($action == 'confirm_paiement' && $confirm == 'yes' && $usercanissuepayment) {
225 $datepaye = dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'), 'tzuser');
226
227 $db->begin();
228
229 $thirdparty = new Societe($db);
230 if ($socid > 0) {
231 $thirdparty->fetch($socid);
232 }
233
234 $multicurrency_code = array();
235 $multicurrency_tx = array();
236
237 // Clean parameters amount if payment is for a credit note
238 foreach ($amounts as $key => $value) { // How payment is dispatched
239 $tmpinvoice = new Facture($db);
240 $tmpinvoice->fetch($key);
241 if ($tmpinvoice->type == Facture::TYPE_CREDIT_NOTE) {
242 $newvalue = price2num($value, 'MT');
243 $amounts[$key] = - abs((float) $newvalue);
244 }
245 $multicurrency_code[$key] = $tmpinvoice->multicurrency_code;
246 $multicurrency_tx[$key] = $tmpinvoice->multicurrency_tx;
247 }
248
249 foreach ($multicurrency_amounts as $key => $value) { // How payment is dispatched
250 $tmpinvoice = new Facture($db);
251 $tmpinvoice->fetch($key);
252 if ($tmpinvoice->type == Facture::TYPE_CREDIT_NOTE) {
253 $newvalue = price2num($value, 'MT');
254 $multicurrency_amounts[$key] = - abs((float) $newvalue);
255 }
256 $multicurrency_code[$key] = $tmpinvoice->multicurrency_code;
257 $multicurrency_tx[$key] = $tmpinvoice->multicurrency_tx;
258 }
259
260 if (isModEnabled("bank")) {
261 // If the bank module is active, an account is required to input a payment
262 if (GETPOSTINT('accountid') <= 0) {
263 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('AccountToCredit')), null, 'errors');
264 $error++;
265 }
266 }
267
268 // Creation of payment line
269 $paiement = new Paiement($db);
270 $paiement->datepaye = $datepaye;
271 $paiement->amounts = $amounts; // Array with all payments dispatching with invoice id
272 $paiement->multicurrency_amounts = $multicurrency_amounts; // Array with all payments dispatching
273 $paiement->multicurrency_code = $multicurrency_code; // Array with all currency of payments dispatching
274 $paiement->multicurrency_tx = $multicurrency_tx; // Array with all currency tx of payments dispatching
275 $paiement->paiementid = dol_getIdFromCode($db, GETPOST('paiementcode'), 'c_paiement', 'code', 'id', 1);
276 $paiement->num_payment = GETPOST('num_paiement', 'alpha');
277 $paiement->note_private = GETPOST('comment', 'alpha');
278 $paiement->fk_account = GETPOSTINT('accountid');
279
280 $paiement_id = 0;
281 if (!$error) {
282 // Create payment and update this->multicurrency_amounts if this->amounts filled or
283 // this->amounts if this->multicurrency_amounts filled.
284 // This also set ->amount and ->multicurrency_amount
285 $paiement_id = $paiement->create($user, (GETPOST('closepaidinvoices') == 'on' ? 1 : 0), $thirdparty); // This include closing invoices and regenerating documents
286 if ($paiement_id < 0) {
287 setEventMessages($paiement->error, $paiement->errors, 'errors');
288 $error++;
289 }
290 }
291 /*
292 var_dump($paiement->amount);
293 var_dump($paiement->multicurrency_amount);
294 var_dump($paiement->multicurrency_currency);
295 */
296
297 if (!$error) {
298 $label = '(CustomerInvoicePayment)';
299 if (GETPOST('type') == Facture::TYPE_CREDIT_NOTE) {
300 $label = '(CustomerInvoicePaymentBack)'; // Refund of a credit note
301 }
302
303 $result = $paiement->addPaymentToBank($user, 'payment', $label, GETPOSTINT('accountid'), GETPOST('chqemetteur'), GETPOST('chqbank'));
304 if ($result < 0) {
305 setEventMessages($paiement->error, $paiement->errors, 'errors');
306 $error++;
307 }
308 }
309
310 if (!$error) {
311 $db->commit();
312
313 // If payment dispatching on more than one invoice, we stay on summary page, otherwise jump on invoice card
314 $invoiceid = 0;
315 foreach ($paiement->amounts as $key => $amount) {
316 $facid = $key;
317 if (is_numeric($amount) && $amount != 0) {
318 if ($invoiceid != 0) {
319 $invoiceid = -1; // There is more than one invoice paid by this payment
320 } else {
321 $invoiceid = $facid;
322 }
323 }
324 }
325 if ($invoiceid > 0) {
326 $loc = DOL_URL_ROOT.'/compta/facture/card.php?facid='.$invoiceid;
327 } else {
328 $loc = DOL_URL_ROOT.'/compta/paiement/card.php?id='.$paiement_id;
329 }
330 header('Location: '.$loc);
331 exit;
332 } else {
333 $db->rollback();
334 }
335 }
336}
337
338
339/*
340 * View
341 */
342
343$form = new Form($db);
344
345
346llxHeader('', $langs->trans("Payment"));
347
348
349 $facture = new Facture($db);
350 $result = $facture->fetch($facid);
351
352if ($result >= 0) {
353 $facture->fetch_thirdparty();
354
355 $title = '';
356 if ($facture->type != Facture::TYPE_CREDIT_NOTE) {
357 $title .= $langs->trans("EnterPaymentReceivedFromCustomer");
358 }
359 if ($facture->type == Facture::TYPE_CREDIT_NOTE) {
360 $title .= $langs->trans("EnterPaymentDueToCustomer");
361 }
362 print load_fiche_titre($title);
363
364 // Initialize data for confirmation (this is used because data can be change during confirmation)
365 if ($action == 'add_paiement') {
366 $i = 0;
367
368 $formquestion[$i++] = array('type' => 'hidden', 'name' => 'facid', 'value' => $facture->id);
369 $formquestion[$i++] = array('type' => 'hidden', 'name' => 'socid', 'value' => $facture->socid);
370 $formquestion[$i++] = array('type' => 'hidden', 'name' => 'type', 'value' => $facture->type);
371 }
372
373 // Invoice with Paypal transaction
374 // @TODO add hook here
375 if (isModEnabled('paypalplus') && getDolGlobalString('PAYPAL_ENABLE_TRANSACTION_MANAGEMENT') && !empty($facture->ref_ext)) {
376 if (getDolGlobalString('PAYPAL_BANK_ACCOUNT')) {
377 $accountid = getDolGlobalString('PAYPAL_BANK_ACCOUNT');
378 }
379 $paymentnum = $facture->ref_ext;
380 }
381
382 // Add realtime total information
383 if (!empty($conf->use_javascript_ajax)) {
384 print "\n".'<script type="text/javascript">';
385 print '$(document).ready(function () {
386 setPaiementCode();
387
388 $("#selectpaiementcode").change(function() {
389 setPaiementCode();
390 });
391
392 function setPaiementCode()
393 {
394 var code = $("#selectpaiementcode option:selected").val();
395 console.log("setPaiementCode code="+code);
396
397 if (code == \'CHQ\' || code == \'VIR\')
398 {
399 if (code == \'CHQ\')
400 {
401 $(\'.fieldrequireddyn\').addClass(\'fieldrequired\');
402 }
403 if ($(\'#fieldchqemetteur\').val() == \'\')
404 {
405 var emetteur = ('.$facture->type.' == '.Facture::TYPE_CREDIT_NOTE.') ? \''.dol_escape_js(dol_escape_htmltag(getDolGlobalString('MAIN_INFO_SOCIETE_NOM'))).'\' : jQuery(\'#thirdpartylabel\').val();
406 $(\'#fieldchqemetteur\').val(emetteur);
407 }
408 }
409 else
410 {
411 $(\'.fieldrequireddyn\').removeClass(\'fieldrequired\');
412 $(\'#fieldchqemetteur\').val(\'\');
413 }
414 }
415
416 function _elemToJson(selector)
417 {
418 var subJson = {};
419 $.map(selector.serializeArray(), function(n,i)
420 {
421 subJson[n["name"]] = n["value"];
422 });
423
424 return subJson;
425 }
426 function callForResult(imgId)
427 {
428 var json = {};
429 var form = $("#payment_form");
430
431 json["invoice_type"] = $("#invoice_type").val();
432 json["amountPayment"] = $("#amountpayment").attr("value");
433 json["amounts"] = _elemToJson(form.find("input.amount"));
434 json["remains"] = _elemToJson(form.find("input.remain"));
435 json["token"] = "'.currentToken().'";
436 if (imgId != null) {
437 json["imgClicked"] = imgId;
438 }
439
440 $.post("'.DOL_URL_ROOT.'/compta/ajaxpayment.php", json, function(data)
441 {
442 json = $.parseJSON(data);
443
444 form.data(json);
445
446 for (var key in json)
447 {
448 if (key == "result") {
449 if (json["makeRed"]) {
450 $("#"+key).addClass("error");
451 } else {
452 $("#"+key).removeClass("error");
453 }
454 json[key]=json["label"]+" "+json[key];
455 $("#"+key).text(json[key]);
456 } else {console.log(key);
457 form.find("input[name*=\""+key+"\"]").each(function() {
458 $(this).attr("value", json[key]);
459 });
460 }
461 }
462 });
463 }
464 $("#payment_form").find("input.amount").change(function() {
465 callForResult();
466 });
467 $("#payment_form").find("input.amount").keyup(function() {
468 callForResult();
469 });
470 ';
471
472 print ' });'."\n";
473
474 //Add js for AutoFill
475 print ' $(document).ready(function () {';
476 print ' $(".AutoFillAmount").on(\'click touchstart\', function(){
477 $("input[name="+$(this).data(\'rowname\')+"]").val($(this).data("value")).trigger("change");
478 });';
479 print ' });'."\n";
480
481 print ' </script>'."\n";
482 }
483
484 print '<form id="payment_form" name="add_paiement" action="'.$_SERVER["PHP_SELF"].'" method="POST">';
485 print '<input type="hidden" name="token" value="'.newToken().'">';
486 print '<input type="hidden" name="action" value="add_paiement">';
487 print '<input type="hidden" name="facid" value="'.$facture->id.'">';
488 print '<input type="hidden" name="socid" value="'.$facture->socid.'">';
489 print '<input type="hidden" name="type" id="invoice_type" value="'.$facture->type.'">';
490 print '<input type="hidden" name="thirdpartylabel" id="thirdpartylabel" value="'.dol_escape_htmltag($facture->thirdparty->name).'">';
491 print '<input type="hidden" name="page_y" value="">';
492
493 print dol_get_fiche_head();
494
495 print '<table class="border centpercent">';
496
497 // Third party
498 print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans('Company').'</span></td><td>'.$facture->thirdparty->getNomUrl(4)."</td></tr>\n";
499
500 // Date payment
501 print '<tr><td><span class="fieldrequired">'.$langs->trans('Date').'</span></td><td>';
502 $datepayment = dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
503 $datepayment = ($datepayment == '' ? (!getDolGlobalString('MAIN_AUTOFILL_DATE') ? -1 : '') : $datepayment);
504 print $form->selectDate($datepayment, '', 0, 0, 0, "add_paiement", 1, 1, 0, '', '', $facture->date);
505 print '</td></tr>';
506
507 // Payment mode
508 print '<tr><td><span class="fieldrequired">'.$langs->trans('PaymentMode').'</span></td><td>';
509 $form->select_types_paiements((GETPOST('paiementcode') ? GETPOST('paiementcode') : $facture->mode_reglement_code), 'paiementcode', '', 2);
510 print "</td>\n";
511 print '</tr>';
512
513 // Bank account
514 print '<tr>';
515 if (isModEnabled("bank")) {
516 if ($facture->type != 2) {
517 print '<td><span class="fieldrequired">'.$langs->trans('AccountToCredit').'</span></td>';
518 }
519 if ($facture->type == 2) {
520 print '<td><span class="fieldrequired">'.$langs->trans('AccountToDebit').'</span></td>';
521 }
522
523 print '<td>';
524 print img_picto('', 'bank_account', 'class="pictofixedwidth"');
525 print $form->select_comptes($accountid, 'accountid', 0, '', 2, '', (isModEnabled('multicurrency') ? 1 : 0), 'widthcentpercentminusx maxwidth500', 1);
526 print '</td>';
527 } else {
528 print '<td>&nbsp;</td>';
529 }
530 print "</tr>\n";
531
532 // Bank check number
533 print '<tr><td>'.$langs->trans('Numero');
534 print ' <em class="opacitymedium">('.$langs->trans("ChequeOrTransferNumber").')</em>';
535 print '</td>';
536 print '<td><input name="num_paiement" type="text" class="maxwidth200" value="'.$paymentnum.'"></td></tr>';
537
538 // Check transmitter
539 print '<tr><td class="'.(GETPOST('paiementcode') == 'CHQ' ? 'fieldrequired ' : '').'fieldrequireddyn">'.$langs->trans('CheckTransmitter');
540 print ' <em class="opacitymedium">('.$langs->trans("ChequeMaker").')</em>';
541 print '</td>';
542 print '<td><input id="fieldchqemetteur" class="maxwidth300" name="chqemetteur" type="text" value="'.GETPOST('chqemetteur', 'alphanohtml').'"></td></tr>';
543
544 // Bank name
545 print '<tr><td>'.$langs->trans('Bank');
546 print ' <em class="opacitymedium">('.$langs->trans("ChequeBank").')</em>';
547 print '</td>';
548 print '<td><input name="chqbank" class="maxwidth300" type="text" value="'.GETPOST('chqbank', 'alphanohtml').'"></td></tr>';
549
550 // Comments
551 print '<tr><td>'.$langs->trans('Comments').'</td>';
552 print '<td class="tdtop">';
553 print '<textarea name="comment" wrap="soft" class="quatrevingtpercent" rows="'.ROWS_3.'">'.GETPOST('comment', 'restricthtml').'</textarea>';
554 print '</td></tr>';
555
556 // Go Source Invoice (useful when there are many invoices)
557 if ($action != 'add_paiement' && getDolGlobalString('FACTURE_PAYMENTS_SHOW_LINK_TO_INPUT_ORIGIN_IS_MORE_THAN')) {
558 print '<tr><td></td>';
559 print '<td class="tdtop right">';
560 print '<a class="right" href="#amount_'.$facid.'">'.$langs->trans("GoSourceInvoice").'</a>';
561 print '</td></tr>';
562 }
563
564 print '</table>';
565
566 print dol_get_fiche_end();
567
568
569 /*
570 * List of unpaid invoices
571 */
572
573 $sql = 'SELECT f.rowid as facid, f.ref, f.total_ht, f.total_tva, f.total_ttc, f.multicurrency_code, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc, f.type,';
574 $sql .= ' f.datef as df, f.fk_soc as socid, f.date_lim_reglement as dlr';
575 $sql .= ' FROM '.MAIN_DB_PREFIX.'facture as f';
576 $sql .= ' WHERE f.entity IN ('.getEntity('facture').')';
577 $sql .= ' AND (f.fk_soc = '.((int) $facture->socid);
578 // Can pay invoices of all child of parent company
579 if (getDolGlobalString('FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS') && !empty($facture->thirdparty->parent)) {
580 $sql .= ' OR f.fk_soc IN (SELECT rowid FROM '.MAIN_DB_PREFIX.'societe WHERE parent = '.((int) $facture->thirdparty->parent).')';
581 }
582 // Can pay invoices of all child of myself
583 if (getDolGlobalString('FACTURE_PAYMENTS_ON_SUBSIDIARY_COMPANIES')) {
584 $sql .= ' OR f.fk_soc IN (SELECT rowid FROM '.MAIN_DB_PREFIX.'societe WHERE parent = '.((int) $facture->thirdparty->id).')';
585 }
586 $sql .= ') AND f.paye = 0';
587 $sql .= ' AND f.fk_statut = 1'; // Statut=0 => not validated, Statut=2 => canceled
588 if ($facture->type != Facture::TYPE_CREDIT_NOTE) {
589 $sql .= ' AND type IN (0,1,3,5)'; // Standard invoice, replacement, deposit, situation
590 } else {
591 $sql .= ' AND type = 2'; // If paying back a credit note, we show all credit notes
592 }
593 // Sort invoices by date and serial number: the older one comes first
594 $sql .= ' ORDER BY f.datef ASC, f.ref ASC';
595
596 $resql = $db->query($sql);
597 if ($resql) {
598 $num = $db->num_rows($resql);
599 if ($num > 0) {
600 $arraytitle = $langs->trans('Invoice');
601 if ($facture->type == 2) {
602 $arraytitle = $langs->trans("CreditNotes");
603 }
604 $alreadypayedlabel = $langs->trans('Received');
605 $multicurrencyalreadypayedlabel = $langs->trans('MulticurrencyReceived');
606 if ($facture->type == 2) {
607 $alreadypayedlabel = $langs->trans("PaidBack");
608 $multicurrencyalreadypayedlabel = $langs->trans("MulticurrencyPaidBack");
609 }
610 $remaindertopay = $langs->trans('RemainderToTake');
611 $multicurrencyremaindertopay = $langs->trans('MulticurrencyRemainderToTake');
612 if ($facture->type == 2) {
613 $remaindertopay = $langs->trans("RemainderToPayBack");
614 $multicurrencyremaindertopay = $langs->trans("MulticurrencyRemainderToPayBack");
615 }
616
617 $i = 0;
618 //print '<tr><td colspan="3">';
619 print '<br>';
620
621 print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
622 print '<table class="noborder centpercent">';
623
624 print '<tr class="liste_titre">';
625 print '<td>'.$arraytitle.'</td>';
626 print '<td class="center">'.$langs->trans('Date').'</td>';
627 print '<td class="center">'.$langs->trans('DateMaxPayment').'</td>';
628 if (isModEnabled('multicurrency')) {
629 print '<td>'.$langs->trans('Currency').'</td>';
630 print '<td class="right">'.$langs->trans('MulticurrencyAmountTTC').'</td>';
631 print '<td class="right">'.$multicurrencyalreadypayedlabel.'</td>';
632 print '<td class="right">'.$multicurrencyremaindertopay.'</td>';
633 print '<td class="right">'.$langs->trans('MulticurrencyPaymentAmount').'</td>';
634 }
635 print '<td class="right">'.$langs->trans('AmountTTC').'</td>';
636 print '<td class="right">'.$alreadypayedlabel.'</td>';
637 print '<td class="right">'.$remaindertopay.'</td>';
638 print '<td class="right">'.$langs->trans('PaymentAmount').'</td>';
639
640 $parameters = array();
641 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $facture, $action); // Note that $action and $object may have been modified by hook
642
643 print '<td align="right">&nbsp;</td>';
644 print "</tr>\n";
645
646 $total_ttc = 0;
647 $totalrecu = 0;
648 $totalrecucreditnote = 0;
649 $totalrecudeposits = 0;
650 $sign = 1;
651
652 while ($i < $num) {
653 $objp = $db->fetch_object($resql);
654
655 $sign = 1;
656 if ($facture->type == Facture::TYPE_CREDIT_NOTE) {
657 $sign = -1;
658 }
659
660 $soc = new Societe($db);
661 $soc->fetch($objp->socid);
662
663 $invoice = new Facture($db);
664 $invoice->fetch($objp->facid);
665 $paiement = $invoice->getSommePaiement();
666 $creditnotes = $invoice->getSumCreditNotesUsed();
667 $deposits = $invoice->getSumDepositsUsed();
668 $alreadypayed = price2num($paiement + $creditnotes + $deposits, 'MT');
669 $remaintopay = price2num($invoice->total_ttc - $paiement - $creditnotes - $deposits, 'MT');
670
671 // Multicurrency Price
672 $tooltiponmulticurrencyfullamount = '';
673 $multicurrency_remaintopay = '';
674 $multicurrency_payment = 0;
675 $multicurrency_creditnotes = 0;
676 $multicurrency_deposits = 0;
677 if (isModEnabled('multicurrency')) {
678 $multicurrency_payment = $invoice->getSommePaiement(1);
679 $multicurrency_creditnotes = $invoice->getSumCreditNotesUsed(1);
680 $multicurrency_deposits = $invoice->getSumDepositsUsed(1);
681 $multicurrency_alreadypayed = price2num($multicurrency_payment + $multicurrency_creditnotes + $multicurrency_deposits, 'MT');
682 $multicurrency_remaintopay = price2num($invoice->multicurrency_total_ttc - $multicurrency_payment - $multicurrency_creditnotes - $multicurrency_deposits, 'MT');
683 // Multicurrency full amount tooltip
684 $tooltiponmulticurrencyfullamount = $langs->trans('AmountHT') . ": " . price($objp->multicurrency_total_ht, 0, $langs, 0, -1, -1, $objp->multicurrency_code) . "<br>";
685 $tooltiponmulticurrencyfullamount .= $langs->trans('AmountVAT') . ": " . price($objp->multicurrency_total_tva, 0, $langs, 0, -1, -1, $objp->multicurrency_code) . "<br>";
686 $tooltiponmulticurrencyfullamount .= $langs->trans('AmountTTC') . ": " . price($objp->multicurrency_total_ttc, 0, $langs, 0, -1, -1, $objp->multicurrency_code) . "<br>";
687 }
688
689 // Full amount tooltip
690 $tooltiponfullamount = $langs->trans('AmountHT') . ": " . price($objp->total_ht, 0, $langs, 0, -1, -1, $conf->currency) . "<br>";
691 $tooltiponfullamount .= $langs->trans('AmountVAT') . ": " . price($objp->total_tva, 0, $langs, 0, -1, -1, $conf->currency) . "<br>";
692 $tooltiponfullamount .= $langs->trans('AmountTTC') . ": " . price($objp->total_ttc, 0, $langs, 0, -1, -1, $conf->currency) . "<br>";
693
694 print '<tr class="oddeven'.(($invoice->id == $facid) ? ' highlight' : '').'">';
695
696 print '<td class="nowraponall">';
697 print $invoice->getNomUrl(1, '');
698 if ($objp->socid != $facture->thirdparty->id) {
699 print ' - '.$soc->getNomUrl(1).' ';
700 }
701 print "</td>\n";
702
703 // Date
704 print '<td class="center">'.dol_print_date($db->jdate($objp->df), 'day')."</td>\n";
705
706 // Due date
707 if ($objp->dlr > 0) {
708 print '<td class="nowraponall center">';
709 print dol_print_date($db->jdate($objp->dlr), 'day');
710
711 if ($invoice->hasDelay()) {
712 print img_warning($langs->trans('Late'));
713 }
714
715 print '</td>';
716 } else {
717 print '<td align="center"></td>';
718 }
719
720 // Currency
721 if (isModEnabled('multicurrency')) {
722 print '<td class="center">'.$objp->multicurrency_code."</td>\n";
723 }
724
725 // Multicurrency full amount
726 if (isModEnabled('multicurrency')) {
727 print '<td class="right">';
728 if ($objp->multicurrency_code && $objp->multicurrency_code != $conf->currency) {
729 print '<span class="amount classfortooltip" title="'.$tooltiponmulticurrencyfullamount.'">' . price($sign * $objp->multicurrency_total_ttc);
730 }
731 print '</span></td>';
732
733 // Multicurrency Price
734 print '<td class="right">';
735 if ($objp->multicurrency_code && $objp->multicurrency_code != $conf->currency) {
736 print price($sign * $multicurrency_payment);
737 if ($multicurrency_creditnotes) {
738 print '+'.price($multicurrency_creditnotes);
739 }
740 if ($multicurrency_deposits) {
741 print '+'.price($multicurrency_deposits);
742 }
743 }
744 print '</td>';
745
746 // Multicurrency remain to pay
747 print '<td class="right">';
748 if ($objp->multicurrency_code && $objp->multicurrency_code != $conf->currency) {
749 print price($sign * (float) $multicurrency_remaintopay);
750 }
751 print '</td>';
752
753 print '<td class="right nowraponall">';
754
755 // Add remind multicurrency amount
756 $namef = 'multicurrency_amount_'.$objp->facid;
757 $nameRemain = 'multicurrency_remain_'.$objp->facid;
758
759 if ($objp->multicurrency_code && $objp->multicurrency_code != $conf->currency) {
760 if ($action != 'add_paiement') {
761 if (!empty($conf->use_javascript_ajax)) {
762 print img_picto("Auto fill", 'rightarrow', "class='AutoFillAmount' data-rowname='".$namef."' data-value='".($sign * (float) $multicurrency_remaintopay)."'");
763 }
764 print '<input type="text" class="maxwidth75 multicurrency_amount" name="'.$namef.'" value="'.(GETPOST($namef) != '0' ? GETPOST($namef) : '').'">';
765 print '<input type="hidden" class="multicurrency_remain" name="'.$nameRemain.'" value="'.$multicurrency_remaintopay.'">';
766 } else {
767 print '<input type="text" class="maxwidth75" name="'.$namef.'_disabled" value="'.(GETPOST($namef) != '0' ? GETPOST($namef) : '').'" disabled>';
768 print '<input type="hidden" name="'.$namef.'" value="'.GETPOST($namef).'">';
769 }
770 }
771 print "</td>";
772 }
773
774 // Full amount
775 print '<td class="right"><span class="amount classfortooltip" title="'.$tooltiponfullamount.'">'.price($sign * $objp->total_ttc).'</span></td>';
776
777 // Received + already paid
778 print '<td class="right"><span class="amount">'.price($sign * $paiement);
779 if ($creditnotes) {
780 print '<span class="opacitymedium">+'.price($creditnotes).'</span>';
781 }
782 if ($deposits) {
783 print '<span class="opacitymedium">+'.price($deposits).'</span>';
784 }
785 print '</span></td>';
786
787 // Remain to take or to pay back
788 print '<td class="right">';
789 print price($sign * (float) $remaintopay);
790 if (isModEnabled('prelevement')) {
791 $numdirectdebitopen = 0;
792 $totaldirectdebit = 0;
793 $sql = "SELECT COUNT(pfd.rowid) as nb, SUM(pfd.amount) as amount";
794 $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as pfd";
795 $sql .= " WHERE fk_facture = ".((int) $objp->facid);
796 $sql .= " AND pfd.traite = 0";
797 $sql .= " AND pfd.ext_payment_id IS NULL";
798
799 $result_sql = $db->query($sql);
800 if ($result_sql) {
801 $obj = $db->fetch_object($result_sql);
802 $numdirectdebitopen = $obj->nb;
803 $totaldirectdebit = $obj->amount;
804 } else {
805 dol_print_error($db);
806 }
807 if ($numdirectdebitopen) {
808 $langs->load("withdrawals");
809 print img_warning($langs->trans("WarningSomeDirectDebitOrdersAlreadyExists", $numdirectdebitopen, price(price2num($totaldirectdebit, 'MT'), 0, $langs, 1, -1, -1, $conf->currency)), '', 'classfortooltip');
810 }
811 }
812 print '</td>';
813 //$test= price(price2num($objp->total_ttc - $paiement - $creditnotes - $deposits));
814
815 // Amount
816 print '<td class="right nowraponall">';
817
818 // Add remind amount
819 $namef = 'amount_'.$objp->facid;
820 $nameRemain = 'remain_'.$objp->facid;
821
822 if ($action != 'add_paiement') {
823 if (!empty($conf->use_javascript_ajax)) {
824 print img_picto("Auto fill", 'rightarrow', "class='AutoFillAmount' data-rowname='".$namef."' data-value='".($sign * (float) $remaintopay)."'");
825 }
826 print '<input type="text" class="maxwidth75 amount" id="'.$namef.'" name="'.$namef.'" value="'.dol_escape_htmltag(GETPOST($namef)).'">';
827 print '<input type="hidden" class="remain" name="'.$nameRemain.'" value="'.$remaintopay.'">';
828 } else {
829 print '<input type="text" class="maxwidth75" name="'.$namef.'_disabled" value="'.dol_escape_htmltag(GETPOST($namef)).'" disabled>';
830 print '<input type="hidden" name="'.$namef.'" value="'.dol_escape_htmltag(GETPOST($namef)).'">';
831 }
832 print "</td>";
833
834 $parameters = array();
835 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $objp, $action); // Note that $action and $object may have been modified by hook
836
837 // Warning
838 print '<td align="center" width="16">';
839 //print "xx".$amounts[$invoice->id]."-".$amountsresttopay[$invoice->id]."<br>";
840 if (!empty($amounts[$invoice->id]) && (abs((float) $amounts[$invoice->id]) > abs((float) $amountsresttopay[$invoice->id]))
841 || !empty($multicurrency_amounts[$invoice->id]) && (abs((float) $multicurrency_amounts[$invoice->id]) > abs((float) $multicurrency_amountsresttopay[$invoice->id]))) {
842 print ' '.img_warning($langs->trans("PaymentHigherThanReminderToPay"));
843 }
844 print '</td>';
845
846 print "</tr>\n";
847
848 $total_ttc += $objp->total_ttc;
849 $totalrecu += $paiement;
850 $totalrecucreditnote += $creditnotes;
851 $totalrecudeposits += $deposits;
852 $i++;
853 }
854
855 if ($i > 1) {
856 // Print total
857 print '<tr class="liste_total">';
858 print '<td colspan="3" class="left">'.$langs->trans('TotalTTC').'</td>';
859 if (isModEnabled('multicurrency')) {
860 print '<td></td>';
861 print '<td></td>';
862 print '<td></td>';
863 print '<td></td>';
864 print '<td class="right" id="multicurrency_result" style="font-weight: bold;"></td>';
865 }
866 print '<td class="right"><b>'.price($sign * $total_ttc).'</b></td>';
867 print '<td class="right"><b>'.price($sign * $totalrecu);
868 if ($totalrecucreditnote) {
869 print '+'.price($totalrecucreditnote);
870 }
871 if ($totalrecudeposits) {
872 print '+'.price($totalrecudeposits);
873 }
874 print '</b></td>';
875 print '<td class="right"><b>'.price($sign * (float) price2num($total_ttc - $totalrecu - $totalrecucreditnote - $totalrecudeposits, 'MT')).'</b></td>';
876 print '<td class="right" id="result" style="font-weight: bold;"></td>'; // Autofilled
877 print '<td align="center">&nbsp;</td>';
878 print "</tr>\n";
879 }
880 print "</table>";
881 print "</div>\n";
882 }
883 $db->free($resql);
884 } else {
885 dol_print_error($db);
886 }
887
888 $formconfirm = '';
889
890 // Save button
891 if ($action != 'add_paiement') {
892 $checkboxlabel = $langs->trans("ClosePaidInvoicesAutomatically");
893 if ($facture->type == Facture::TYPE_CREDIT_NOTE) {
894 $checkboxlabel = $langs->trans("ClosePaidCreditNotesAutomatically");
895 }
896 $buttontitle = $langs->trans('ToMakePayment');
897 if ($facture->type == Facture::TYPE_CREDIT_NOTE) {
898 $buttontitle = $langs->trans('ToMakePaymentBack');
899 }
900
901 print '<br><div class="center">';
902 print '<input type="checkbox" checked name="closepaidinvoices" id="closepaidinvoices"><label for="closepaidinvoices"> '.$checkboxlabel.'</label>';
903 /*if (isModEnabled('prelevement')) {
904 $langs->load("withdrawals");
905 if (getDolGlobalString('WITHDRAW_DISABLE_AUTOCREATE_ONPAYMENTS')) {
906 print '<br>'.$langs->trans("IfInvoiceNeedOnWithdrawPaymentWontBeClosed");
907 }
908 }*/
909 print '<br><input type="submit" class="button reposition" value="'.dol_escape_htmltag($buttontitle).'"><br><br>';
910 print '</div>';
911 }
912
913 // Form to confirm payment
914 if ($action == 'add_paiement') {
915 $preselectedchoice = $addwarning ? 'no' : 'yes';
916
917 print '<br>';
918 $text = '';
919 if (!empty($totalpayment)) {
920 $text = $langs->trans('ConfirmCustomerPayment', $totalpayment, $langs->transnoentitiesnoconv("Currency".$conf->currency));
921 }
922 if (!empty($multicurrency_totalpayment)) {
923 $text .= '<br>'.$langs->trans('ConfirmCustomerPayment', $multicurrency_totalpayment, $langs->transnoentitiesnoconv("paymentInInvoiceCurrency"));
924 }
925 if (GETPOST('closepaidinvoices')) {
926 $text .= '<br>'.$langs->trans("AllCompletelyPayedInvoiceWillBeClosed");
927 print '<input type="hidden" name="closepaidinvoices" value="'.GETPOST('closepaidinvoices').'">';
928 }
929 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?facid='.$facture->id.'&socid='.$facture->socid.'&type='.$facture->type, $langs->trans('ReceivedCustomersPayments'), $text, 'confirm_paiement', $formquestion, $preselectedchoice);
930 }
931
932 // Call Hook formConfirm
933 $parameters = array('formConfirm' => $formconfirm);
934 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
935 if (empty($reshook)) {
936 $formconfirm .= $hookmanager->resPrint;
937 } elseif ($reshook > 0) {
938 $formconfirm = $hookmanager->resPrint;
939 }
940
941 // Print form confirm
942 print $formconfirm;
943
944 print "</form>\n";
945}
946
947
948llxFooter();
949
950$db->close();
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:87
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:71
Class to manage invoices.
const STATUS_DRAFT
Draft status.
const TYPE_CREDIT_NOTE
Credit note invoice.
Class to manage generation of HTML components Only common components must be here.
Class to manage payments of customer 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...
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
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.
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)
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
currentToken()
Return the value of token currently saved into session with name 'token'.
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.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
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.
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
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.