dolibarr 19.0.3
loanschedule.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017 Florian HENRY <florian.henry@atm-consulting.fr>
3 * Copyright (C) 2018-2023 Frédéric France <frederic.france@netlogic.fr>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
25require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
26
27
32{
36 public $element = 'loan_schedule';
37
41 public $table_element = 'loan_schedule';
42
46 public $fk_loan;
47
48 public $bank_account;
49 public $bank_line;
53 public $datec;
54 public $tms;
55
59 public $datep;
60
61 public $amounts = array(); // Array of amounts
62 public $amount_capital; // Total amount of payment
63 public $amount_insurance;
64 public $amount_interest;
65
69 public $fk_typepayment;
70
74 public $num_payment;
75
79 public $fk_bank;
80
84 public $fk_payment_loan;
85
89 public $fk_user_creat;
90
94 public $fk_user_modif;
95
100 public $lines = array();
101
106 public $total;
107
108 public $type_code;
109 public $type_label;
110
111
117 public function __construct($db)
118 {
119 $this->db = $db;
120 }
121
129 public function create($user)
130 {
131 global $conf, $langs;
132
133 $error = 0;
134
135 $now = dol_now();
136
137 // Validate parameters
138 if (!$this->datep) {
139 $this->error = 'ErrorBadValueForParameter';
140 return -1;
141 }
142
143 // Clean parameters
144 if (isset($this->fk_loan)) {
145 $this->fk_loan = (int) $this->fk_loan;
146 }
147 if (isset($this->amount_capital)) {
148 $this->amount_capital = trim($this->amount_capital ? $this->amount_capital : 0);
149 }
150 if (isset($this->amount_insurance)) {
151 $this->amount_insurance = trim($this->amount_insurance ? $this->amount_insurance : 0);
152 }
153 if (isset($this->amount_interest)) {
154 $this->amount_interest = trim($this->amount_interest ? $this->amount_interest : 0);
155 }
156 if (isset($this->fk_typepayment)) {
157 $this->fk_typepayment = (int) $this->fk_typepayment;
158 }
159 if (isset($this->fk_bank)) {
160 $this->fk_bank = (int) $this->fk_bank;
161 }
162 if (isset($this->fk_user_creat)) {
163 $this->fk_user_creat = (int) $this->fk_user_creat;
164 }
165 if (isset($this->fk_user_modif)) {
166 $this->fk_user_modif = (int) $this->fk_user_modif;
167 }
168
169 $totalamount = $this->amount_capital + $this->amount_insurance + $this->amount_interest;
170 $totalamount = price2num($totalamount);
171
172 // Check parameters
173 if ($totalamount == 0) {
174 $this->errors[] = 'Amount must not be "0".';
175 return -1; // Negative amounts are accepted for reject prelevement but not null
176 }
177
178
179 $this->db->begin();
180
181 if ($totalamount != 0) {
182 $sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (fk_loan, datec, datep, amount_capital, amount_insurance, amount_interest,";
183 $sql .= " fk_typepayment, fk_user_creat, fk_bank)";
184 $sql .= " VALUES (".$this->fk_loan.", '".$this->db->idate($now)."',";
185 $sql .= " '".$this->db->idate($this->datep)."',";
186 $sql .= " ".price2num($this->amount_capital).",";
187 $sql .= " ".price2num($this->amount_insurance).",";
188 $sql .= " ".price2num($this->amount_interest).",";
189 $sql .= " ".price2num($this->fk_typepayment).", ";
190 $sql .= " ".((int) $user->id).",";
191 $sql .= " ".((int) $this->fk_bank).")";
192
193 dol_syslog(get_class($this)."::create", LOG_DEBUG);
194 $resql = $this->db->query($sql);
195 if ($resql) {
196 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."payment_loan");
197 } else {
198 $this->error = $this->db->lasterror();
199 $error++;
200 }
201 }
202
203 if ($totalamount != 0 && !$error) {
204 $this->amount_capital = $totalamount;
205 $this->db->commit();
206 return $this->id;
207 } else {
208 $this->errors[] = $this->db->lasterror();
209 $this->db->rollback();
210 return -1;
211 }
212 }
213
220 public function fetch($id)
221 {
222 global $langs;
223 $sql = "SELECT";
224 $sql .= " t.rowid,";
225 $sql .= " t.fk_loan,";
226 $sql .= " t.datec,";
227 $sql .= " t.tms,";
228 $sql .= " t.datep,";
229 $sql .= " t.amount_capital,";
230 $sql .= " t.amount_insurance,";
231 $sql .= " t.amount_interest,";
232 $sql .= " t.fk_typepayment,";
233 $sql .= " t.num_payment,";
234 $sql .= " t.note_private,";
235 $sql .= " t.note_public,";
236 $sql .= " t.fk_bank,";
237 $sql .= " t.fk_payment_loan,";
238 $sql .= " t.fk_user_creat,";
239 $sql .= " t.fk_user_modif,";
240 $sql .= " pt.code as type_code, pt.libelle as type_label,";
241 $sql .= ' b.fk_account';
242 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t";
243 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as pt ON t.fk_typepayment = pt.id";
244 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank as b ON t.fk_bank = b.rowid';
245 $sql .= " WHERE t.rowid = ".((int) $id);
246
247 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
248 $resql = $this->db->query($sql);
249 if ($resql) {
250 if ($this->db->num_rows($resql)) {
251 $obj = $this->db->fetch_object($resql);
252
253 $this->id = $obj->rowid;
254 $this->ref = $obj->rowid;
255
256 $this->fk_loan = $obj->fk_loan;
257 $this->datec = $this->db->jdate($obj->datec);
258 $this->tms = $this->db->jdate($obj->tms);
259 $this->datep = $this->db->jdate($obj->datep);
260 $this->amount_capital = $obj->amount_capital;
261 $this->amount_insurance = $obj->amount_insurance;
262 $this->amount_interest = $obj->amount_interest;
263 $this->fk_typepayment = $obj->fk_typepayment;
264 $this->num_payment = $obj->num_payment;
265 $this->note_private = $obj->note_private;
266 $this->note_public = $obj->note_public;
267 $this->fk_bank = $obj->fk_bank;
268 $this->fk_payment_loan = $obj->fk_payment_loan;
269 $this->fk_user_creat = $obj->fk_user_creat;
270 $this->fk_user_modif = $obj->fk_user_modif;
271
272 $this->type_code = $obj->type_code;
273 $this->type_label = $obj->type_label;
274
275 $this->bank_account = $obj->fk_account;
276 $this->bank_line = $obj->fk_bank;
277 }
278 $this->db->free($resql);
279
280 return 1;
281 } else {
282 $this->error = "Error ".$this->db->lasterror();
283 return -1;
284 }
285 }
286
287
295 public function update($user = 0, $notrigger = 0)
296 {
297 global $conf, $langs;
298 $error = 0;
299
300 // Clean parameters
301 if (isset($this->amount_capital)) {
302 $this->amount_capital = trim($this->amount_capital);
303 }
304 if (isset($this->amount_insurance)) {
305 $this->amount_insurance = trim($this->amount_insurance);
306 }
307 if (isset($this->amount_interest)) {
308 $this->amount_interest = trim($this->amount_interest);
309 }
310 if (isset($this->num_payment)) {
311 $this->num_payment = trim($this->num_payment);
312 }
313 if (isset($this->note_private)) {
314 $this->note_private = trim($this->note_private);
315 }
316 if (isset($this->note_public)) {
317 $this->note_public = trim($this->note_public);
318 }
319 if (isset($this->fk_bank)) {
320 $this->fk_bank = trim($this->fk_bank);
321 }
322 if (isset($this->fk_payment_loan)) {
323 $this->fk_payment_loan = (int) $this->fk_payment_loan;
324 }
325
326 // Check parameters
327 // Put here code to add control on parameters values
328
329 // Update request
330 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
331
332 $sql .= " fk_loan=".(isset($this->fk_loan) ? $this->fk_loan : "null").",";
333 $sql .= " datec=".(dol_strlen($this->datec) != 0 ? "'".$this->db->idate($this->datec)."'" : 'null').",";
334 $sql .= " tms=".(dol_strlen($this->tms) != 0 ? "'".$this->db->idate($this->tms)."'" : 'null').",";
335 $sql .= " datep=".(dol_strlen($this->datep) != 0 ? "'".$this->db->idate($this->datep)."'" : 'null').",";
336 $sql .= " amount_capital=".(isset($this->amount_capital) ? $this->amount_capital : "null").",";
337 $sql .= " amount_insurance=".(isset($this->amount_insurance) ? $this->amount_insurance : "null").",";
338 $sql .= " amount_interest=".(isset($this->amount_interest) ? $this->amount_interest : "null").",";
339 $sql .= " fk_typepayment=".(isset($this->fk_typepayment) ? $this->fk_typepayment : "null").",";
340 $sql .= " num_payment=".(isset($this->num_payment) ? "'".$this->db->escape($this->num_payment)."'" : "null").",";
341 $sql .= " note_private=".(isset($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null").",";
342 $sql .= " note_public=".(isset($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : "null").",";
343 $sql .= " fk_bank=".(isset($this->fk_bank) ? ((int) $this->fk_bank) : "null").",";
344 $sql .= " fk_payment_loan=".(isset($this->fk_payment_loan) ? ((int) $this->fk_payment_loan) : "null").",";
345 $sql .= " fk_user_creat=".(isset($this->fk_user_creat) ? ((int) $this->fk_user_creat) : "null").",";
346 $sql .= " fk_user_modif=".(isset($this->fk_user_modif) ? ((int) $this->fk_user_modif) : "null");
347
348 $sql .= " WHERE rowid=".((int) $this->id);
349
350 $this->db->begin();
351
352 dol_syslog(get_class($this)."::update", LOG_DEBUG);
353 $resql = $this->db->query($sql);
354 if (!$resql) {
355 $error++;
356 $this->errors[] = "Error ".$this->db->lasterror();
357 }
358
359 // Commit or rollback
360 if ($error) {
361 $this->db->rollback();
362 return -1 * $error;
363 } else {
364 $this->db->commit();
365 return 1;
366 }
367 }
368
369
377 public function delete($user, $notrigger = 0)
378 {
379 global $conf, $langs;
380 $error = 0;
381
382 $this->db->begin();
383
384 if (!$error) {
385 $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element;
386 $sql .= " WHERE rowid=".((int) $this->id);
387
388 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
389 $resql = $this->db->query($sql);
390 if (!$resql) {
391 $error++;
392 $this->errors[] = "Error ".$this->db->lasterror();
393 }
394 }
395
396 // Commit or rollback
397 if ($error) {
398 foreach ($this->errors as $errmsg) {
399 dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
400 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
401 }
402 $this->db->rollback();
403 return -1 * $error;
404 } else {
405 $this->db->commit();
406 return 1;
407 }
408 }
409
418 public function calcMonthlyPayments($capital, $rate, $nbterm)
419 {
420 $result = '';
421
422 if (!empty($capital) && !empty($nbterm)) {
423 if (!empty($rate)) {
424 $result = ($capital * ($rate / 12)) / (1 - pow((1 + ($rate / 12)), ($nbterm * -1)));
425 } else {
426 $result = $capital / $nbterm;
427 }
428 }
429
430 return $result;
431 }
432
433
440 public function fetchAll($loanid)
441 {
442 global $langs;
443
444 $sql = "SELECT";
445 $sql .= " t.rowid,";
446 $sql .= " t.fk_loan,";
447 $sql .= " t.datec,";
448 $sql .= " t.tms,";
449 $sql .= " t.datep,";
450 $sql .= " t.amount_capital,";
451 $sql .= " t.amount_insurance,";
452 $sql .= " t.amount_interest,";
453 $sql .= " t.fk_typepayment,";
454 $sql .= " t.num_payment,";
455 $sql .= " t.note_private,";
456 $sql .= " t.note_public,";
457 $sql .= " t.fk_bank,";
458 $sql .= " t.fk_payment_loan,";
459 $sql .= " t.fk_user_creat,";
460 $sql .= " t.fk_user_modif";
461 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t";
462 $sql .= " WHERE t.fk_loan = ".((int) $loanid);
463
464 dol_syslog(get_class($this)."::fetchAll", LOG_DEBUG);
465 $resql = $this->db->query($sql);
466
467 if ($resql) {
468 while ($obj = $this->db->fetch_object($resql)) {
469 $line = new LoanSchedule($this->db);
470 $line->id = $obj->rowid;
471 $line->ref = $obj->rowid;
472
473 $line->fk_loan = $obj->fk_loan;
474 $line->datec = $this->db->jdate($obj->datec);
475 $line->tms = $this->db->jdate($obj->tms);
476 $line->datep = $this->db->jdate($obj->datep);
477 $line->amount_capital = $obj->amount_capital;
478 $line->amount_insurance = $obj->amount_insurance;
479 $line->amount_interest = $obj->amount_interest;
480 $line->fk_typepayment = $obj->fk_typepayment;
481 $line->num_payment = $obj->num_payment;
482 $line->note_private = $obj->note_private;
483 $line->note_public = $obj->note_public;
484 $line->fk_bank = $obj->fk_bank;
485 $line->fk_payment_loan = $obj->fk_payment_loan;
486 $line->fk_user_creat = $obj->fk_user_creat;
487 $line->fk_user_modif = $obj->fk_user_modif;
488
489 $this->lines[] = $line;
490 }
491 $this->db->free($resql);
492 return 1;
493 } else {
494 $this->error = "Error ".$this->db->lasterror();
495 return -1;
496 }
497 }
498
504 private function transPayment()
505 {
506 require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php';
507 require_once DOL_DOCUMENT_ROOT.'/core/lib/loan.lib.php';
508 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
509
510 $toinsert = array();
511
512 $sql = "SELECT l.rowid";
513 $sql .= " FROM ".MAIN_DB_PREFIX."loan as l";
514 $sql .= " WHERE l.paid = 0";
515 $resql = $this->db->query($sql);
516
517 if ($resql) {
518 while ($obj = $this->db->fetch_object($resql)) {
519 $lastrecorded = $this->lastPayment($obj->rowid);
520 $toinsert = $this->paimenttorecord($obj->rowid, $lastrecorded);
521 if (count($toinsert) > 0) {
522 foreach ($toinsert as $echid) {
523 $this->db->begin();
524 $sql = "INSERT INTO ".MAIN_DB_PREFIX."payment_loan ";
525 $sql .= "(fk_loan,datec,tms,datep,amount_capital,amount_insurance,amount_interest,fk_typepayment,num_payment,note_private,note_public,fk_bank,fk_user_creat,fk_user_modif) ";
526 $sql .= "SELECT fk_loan,datec,tms,datep,amount_capital,amount_insurance,amount_interest,fk_typepayment,num_payment,note_private,note_public,fk_bank,fk_user_creat,fk_user_modif";
527 $sql .= " FROM ".MAIN_DB_PREFIX."loan_schedule WHERE rowid =".((int) $echid);
528 $res = $this->db->query($sql);
529 if ($res) {
530 $this->db->commit();
531 } else {
532 $this->db->rollback();
533 }
534 }
535 }
536 }
537 }
538 }
539
540
547 private function lastPayment($loanid)
548 {
549 $sql = "SELECT p.datep";
550 $sql .= " FROM ".MAIN_DB_PREFIX."payment_loan as p ";
551 $sql .= " WHERE p.fk_loan = ".((int) $loanid);
552 $sql .= " ORDER BY p.datep DESC ";
553 $sql .= " LIMIT 1 ";
554
555 $resql = $this->db->query($sql);
556
557 if ($resql) {
558 $obj = $this->db->fetch_object($resql);
559 return $this->db->jdate($obj->datep);
560 } else {
561 return -1;
562 }
563 }
564
572 public function paimenttorecord($loanid, $datemax)
573 {
574 $result = array();
575
576 $sql = "SELECT p.rowid";
577 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as p ";
578 $sql .= " WHERE p.fk_loan = ".((int) $loanid);
579 if (!empty($datemax)) {
580 $sql .= " AND p.datep > '".$this->db->idate($datemax)."'";
581 }
582 $sql .= " AND p.datep <= '".$this->db->idate(dol_now())."'";
583
584 $resql = $this->db->query($sql);
585
586 if ($resql) {
587 while ($obj = $this->db->fetch_object($resql)) {
588 $result[] = $obj->rowid;
589 }
590 }
591
592 return $result;
593 }
594}
$object ref
Definition info.php:79
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Class to manage Schedule of loans.
__construct($db)
Constructor.
fetchAll($loanid)
Load all object in memory from database.
calcMonthlyPayments($capital, $rate, $nbterm)
Calculate Monthly Payments.
create($user)
Create payment of loan into database.
fetch($id)
Load object in memory from database.
paimenttorecord($loanid, $datemax)
paimenttorecord
lastPayment($loanid)
lastpayment
update($user=0, $notrigger=0)
Update database.
transPayment()
transPayment
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_now($mode='auto')
Return date for now.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.