dolibarr 24.0.0-beta
schedule.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017 Franck Moreau <franck.moreau@theobald.com>
3 * Copyright (C) 2018-2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
4 * Copyright (C) 2020 Maxime DEMAREST <maxime@indelog.fr>
5 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
6 * Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
28// Load Dolibarr environment
29require '../main.inc.php';
37require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/loan.lib.php';
39require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
40require_once DOL_DOCUMENT_ROOT.'/loan/class/loanschedule.class.php';
41require_once DOL_DOCUMENT_ROOT.'/loan/class/paymentloan.class.php';
42require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
43if (isModEnabled('project')) {
44 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
45}
46
47$loanid = GETPOSTINT('loanid');
48$action = GETPOST('action', 'aZ09');
49
50// Security check
51$socid = 0;
52if (GETPOSTISSET('socid')) {
53 $socid = GETPOSTINT('socid');
54}
55if ($user->socid) {
56 $socid = $user->socid;
57}
58if (!$user->hasRight('loan', 'calc')) {
60}
61
62// Load translation files required by the page
63$langs->loadLangs(array("compta", "bills", "loan"));
64
65$object = new Loan($db);
66$object->fetch($loanid);
67
68$echeances = new LoanSchedule($db);
69$echeances->fetchAll($object->id);
70
71if ($object->paid > 0 && count($echeances->lines) == 0) {
72 $pay_without_schedule = 1;
73} else {
74 $pay_without_schedule = 0;
75}
76
77$permissiontoadd = $user->hasRight('loan', 'write');
78
79
80/*
81 * Actions
82 */
83
84if ($action == 'createecheancier' && empty($pay_without_schedule) && $permissiontoadd) {
85 $result = -1;
86 $db->begin();
87 $i = 1;
88 while ($i < $object->nbterm + 1) {
89 $date = GETPOSTINT('hi_date'.$i);
90 $mens = price2num(GETPOST('mens'.$i));
91 $int = price2num(GETPOST('hi_interets'.$i));
92 $insurance = price2num(GETPOST('hi_insurance'.$i));
93
94 $new_echeance = new LoanSchedule($db);
95
96 $new_echeance->fk_loan = $object->id;
97 $new_echeance->datec = dol_now();
98 $new_echeance->tms = dol_now();
99 $new_echeance->datep = $date;
100 $new_echeance->amount_capital = (float) $mens - (float) $int;
101 $new_echeance->amount_insurance = $insurance;
102 $new_echeance->amount_interest = $int;
103 $new_echeance->fk_typepayment = 3;
104 $new_echeance->fk_bank = 0;
105 $new_echeance->fk_user_creat = $user->id;
106 $new_echeance->fk_user_modif = $user->id;
107 $result = $new_echeance->create($user);
108 if ($result < 0) {
109 setEventMessages($new_echeance->error, $new_echeance->errors, 'errors');
110 $db->rollback();
111 $echeances->lines = [];
112 break;
113 }
114 $echeances->lines[] = $new_echeance;
115 $i++;
116 }
117 if ($result > 0) {
118 $db->commit();
119 }
120}
121
122if ($action == 'updateecheancier' && empty($pay_without_schedule) && $permissiontoadd) {
123 $result = -1;
124 $db->begin();
125 $i = 1;
126 while ($i < $object->nbterm + 1) {
127 $mens = price2num(GETPOST('mens'.$i));
128 $int = price2num(GETPOST('hi_interets'.$i));
129 $id = GETPOSTINT('hi_rowid'.$i);
130 $insurance = price2num(GETPOST('hi_insurance'.$i));
131
132 $new_echeance = new LoanSchedule($db);
133 $new_echeance->fetch($id);
134 $new_echeance->tms = dol_now();
135 $new_echeance->amount_capital = (float) $mens - (float) $int;
136 $new_echeance->amount_insurance = $insurance;
137 $new_echeance->amount_interest = $int;
138 $new_echeance->fk_user_modif = $user->id;
139 $result = $new_echeance->update($user, 0);
140 if ($result < 0) {
141 setEventMessages(null, $new_echeance->errors, 'errors');
142 $db->rollback();
143 $echeances->fetchAll($object->id);
144 break;
145 }
146
147 $echeances->lines[$i - 1] = $new_echeance;
148 $i++;
149 }
150 if ($result > 0) {
151 $db->commit();
152 }
153}
154
155
156/*
157 * View
158 */
159
160$form = new Form($db);
161$formproject = new FormProjets($db);
162
163$title = $langs->trans("Loan").' - '.$langs->trans("FinancialCommitment");
164$help_url = 'EN:Module_Loan|FR:Module_Emprunt';
165
166llxHeader("", $title, $help_url, '', 0, 0, '', '', '', 'mod-loan page-card_schedule');
167
168$head = loan_prepare_head($object);
169print dol_get_fiche_head($head, 'FinancialCommitment', $langs->trans("Loan"), -1, 'money-bill-alt');
170
171$linkback = '<a href="'.DOL_URL_ROOT.'/loan/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
172
173$morehtmlref = '<div class="refidno">';
174// Ref loan
175$morehtmlref .= $form->editfieldkey("Label", 'label', $object->label, $object, 0, 'string', '', 0, 1);
176$morehtmlref .= $form->editfieldval("Label", 'label', $object->label, $object, 0, 'string', '', null, null, '', 1);
177// Project
178if (isModEnabled('project')) {
179 $langs->loadLangs(array("projects"));
180 $morehtmlref .= '<br>'.$langs->trans('Project').' : ';
181 if ($user->hasRight('loan', 'write')) {
182 if ($action != 'classify') {
183 //$morehtmlref .= '<a class="editfielda" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'classify', 'id' => $object->id], true).'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> : ';
184 if ($action == 'classify') {
185 //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
186 $morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
187 $morehtmlref .= '<input type="hidden" name="action" value="classin">';
188 $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
189 $morehtmlref .= $formproject->select_projects(-1, (string) $object->fk_project, 'projectid', 16, 0, 1, 0, 1, 0, 0, '', 1);
190 $morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
191 $morehtmlref .= '</form>';
192 } else {
193 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, -1, (string) $object->fk_project, 'none', 0, 0, 0, 1, '', 'maxwidth300');
194 }
195 }
196 } else {
197 if (!empty($object->fk_project)) {
198 $proj = new Project($db);
199 $proj->fetch($object->fk_project);
200 $morehtmlref .= ' : '.$proj->getNomUrl(1);
201 if ($proj->title) {
202 $morehtmlref .= ' - '.$proj->title;
203 }
204 } else {
205 $morehtmlref .= '';
206 }
207 }
208}
209$morehtmlref .= '</div>';
210
211$morehtmlstatus = '';
212
213dol_banner_tab($object, 'loanid', $linkback, 1, 'rowid', 'ref', $morehtmlref, '', 0, '', $morehtmlstatus);
214
215?>
216<script type="text/javascript">
217$(document).ready(function() {
218 var timeout = null;
219 var delay = 750; // 0.75 seconds
220 $('[name^="mens"]').keyup(function() {
221 clearTimeout(timeout);
222 timeout = setTimeout(() => {
223 var echeance = $(this).attr('ech');
224 var mens = $(this).val();
225 calculateMens(echeance, mens);
226 }, delay);
227 });
228 function calculateMens(echeance, mens) {
229 var table = $('[name^="mens"]');
230 var idcap = echeance-1;
231 idcap = '#hi_capital'+idcap;
232 var capital = price2numjs($(idcap).val());
233 console.log("Change monthly amount echeance="+echeance+" idcap="+idcap+" capital="+capital);
234 $.ajax({
235 method: "GET",
236 dataType: 'json',
237 url: 'calcmens.php',
238 data: {
239 echeance: echeance,
240 mens: price2numjs(mens),
241 capital: capital,
242 rate: <?php echo $object->rate / 100; ?>,
243 nbterm: <?php echo $object->nbterm; ?>,
244 token: '<?php echo currentToken(); ?>'
245 },
246 success: function(data) {
247 $.each(data, function(index, element) {
248 $('#hi_capital'+index).val(element.cap_rest);
249 $('#capital'+index).text(element.cap_rest_str);
250 $('#hi_interets'+index).val(element.interet);
251 $('#interets'+index).text(element.interet_str);
252 $('#mens'+index).val(element.mens);
253 });
254 }
255 });
256 }
257});
258</script>
259<?php
260
261if ($pay_without_schedule == 1) {
262 print '<div class="warning">'.$langs->trans('CantUseScheduleWithLoanStartedToPaid').'</div>'."\n";
263}
264
265print '<form name="createecheancier" action="'.$_SERVER["PHP_SELF"].'" method="POST">';
266print '<input type="hidden" name="token" value="'.newToken().'">';
267print '<input type="hidden" name="loanid" value="'.$loanid.'">';
268if (count($echeances->lines) > 0) {
269 print '<input type="hidden" name="action" value="updateecheancier">';
270} else {
271 print '<input type="hidden" name="action" value="createecheancier">';
272}
273
274print '<br>';
275
276print '<div class="div-table-responsive-no-min">';
277print '<table class="border centpercent">';
278
279$colspan = 6;
280if (count($echeances->lines) > 0) {
281 $colspan++;
282}
283
284print '<tr class="liste_titre">';
285print '<th class="center">'.$langs->trans("Term").'</th>';
286print '<th class="center">'.$langs->trans("Date").'</th>';
287print '<th class="center">'.$langs->trans("Insurance");
288print '<th class="center">'.$langs->trans("InterestAmount").'</th>';
289print '<th class="center">'.$langs->trans("Amount").'</th>';
290print '<th class="center">'.$langs->trans("CapitalRemain");
291print '<br>('.price($object->capital, 0, '', 1, -1, -1, $conf->currency).')';
292print '<input type="hidden" name="hi_capital0" id ="hi_capital0" value="'.$object->capital.'">';
293print '</th>';
294if (count($echeances->lines) > 0) {
295 print '<th class="center">'.$langs->trans('DoPayment').'</th>';
296}
297print '</tr>'."\n";
298
299if ($object->nbterm > 0 && count($echeances->lines) == 0) {
300 $i = 1;
301 $capital = $object->capital;
302 $insurance = (float) $object->insurance_amount / $object->nbterm;
303 $insurance = price2num($insurance, 'MT');
304 $regulInsurance = price2num((float) $object->insurance_amount - ((float) $insurance * $object->nbterm));
305 while ($i < $object->nbterm + 1) {
306 $mens = price2num($echeances->calcMonthlyPayments($capital, $object->rate / 100, $object->nbterm - $i + 1), 'MT');
307 $int = ($capital * ($object->rate / 12)) / 100;
308 $int = price2num($int, 'MT');
309 $insu = ((float) $insurance + (($i == 1) ? (float) $regulInsurance : 0));
310 $cap_rest = price2num((float) $capital - ((float) $mens - (float) $int), 'MT');
311 print '<tr>';
312 print '<td class="center" id="n'.$i.'">'.$i.'</td>';
313 print '<td class="center" id ="date'.$i.'"><input type="hidden" name="hi_date'.$i.'" id ="hi_date'.$i.'" value="'.dol_time_plus_duree($object->datestart, $i - 1, 'm').'">'.dol_print_date(dol_time_plus_duree($object->datestart, $i - 1, 'm'), 'day').'</td>';
314 print '<td class="center amount" id="insurance'.$i.'">'.price($insu, 0, '', 1, -1, -1, $conf->currency).'</td><input type="hidden" name="hi_insurance'.$i.'" id ="hi_insurance'.$i.'" value="'.$insu.'">';
315 print '<td class="center amount" id="interets'.$i.'">'.price($int, 0, '', 1, -1, -1, $conf->currency).'</td><input type="hidden" name="hi_interets'.$i.'" id ="hi_interets'.$i.'" value="'.$int.'">';
316 print '<td class="center"><input class="width75 right" name="mens'.$i.'" id="mens'.$i.'" value="'.price($mens).'" ech="'.$i.'"></td>';
317 print '<td class="center amount" id="capital'.$i.'">'.price($cap_rest).'</td><input type="hidden" name="hi_capital'.$i.'" id ="hi_capital'.$i.'" value="'.$cap_rest.'">';
318 print '</tr>'."\n";
319 $i++;
320 $capital = $cap_rest;
321 }
322} elseif (count($echeances->lines) > 0) {
323 $i = 1;
324 $capital = $object->capital;
325 $insurance = (float) $object->insurance_amount / $object->nbterm;
326 $insurance = price2num($insurance, 'MT');
327 $regulInsurance = price2num((float) $object->insurance_amount - ((float) $insurance * $object->nbterm));
328 $printed = false;
329 foreach ($echeances->lines as $line) {
330 $mens = $line->amount_capital + $line->amount_interest;
331 $int = $line->amount_interest;
332 $insu = ((float) $insurance + (($i == 1) ? (float) $regulInsurance : 0));
333 $cap_rest = price2num($capital - ($mens - $int), 'MT');
334
335 print '<tr>';
336 print '<td class="center" id="n'.$i.'"><input type="hidden" name="hi_rowid'.$i.'" id ="hi_rowid'.$i.'" value="'.$line->id.'">'.$i.'</td>';
337 print '<td class="center" id ="date'.$i.'"><input type="hidden" name="hi_date'.$i.'" id ="hi_date'.$i.'" value="'.$line->datep.'">'.dol_print_date($line->datep, 'day').'</td>';
338 print '<td class="center amount" id="insurance'.$i.'">'.price($insu, 0, '', 1, -1, -1, $conf->currency).'</td><input type="hidden" name="hi_insurance'.$i.'" id ="hi_insurance'.$i.'" value="'.$insu.'">';
339 print '<td class="center amount" id="interets'.$i.'">'.price($int, 0, '', 1, -1, -1, $conf->currency).'</td><input type="hidden" name="hi_interets'.$i.'" id ="hi_interets'.$i.'" value="'.$int.'">';
340 if (empty($line->fk_bank)) {
341 print '<td class="center"><input class="right width75" name="mens'.$i.'" id="mens'.$i.'" value="'.price($mens).'" ech="'.$i.'"></td>';
342 } else {
343 print '<td class="center amount">'.price($mens, 0, '', 1, -1, -1, $conf->currency).'</td><input type="hidden" name="mens'.$i.'" id ="mens'.$i.'" value="'.$mens.'">';
344 }
345
346 print '<td class="center amount" id="capital'.$i.'">'.price($cap_rest, 0, '', 1, -1, -1, $conf->currency).'</td><input type="hidden" name="hi_capital'.$i.'" id ="hi_capital'.$i.'" value="'.$cap_rest.'">';
347 print '<td class="center">';
348 if (!empty($line->fk_bank)) {
349 print $langs->trans('Paid');
350 if (!empty($line->fk_payment_loan)) {
351 print '&nbsp;<a href="'.DOL_URL_ROOT.'/loan/payment/card.php?id='.$line->fk_payment_loan.'">('.img_object($langs->trans("Payment"), "payment").' '.$line->fk_payment_loan.')</a>';
352 }
353 } elseif (!$printed) {
354 print '<a class="butAction smallpaddingimp" href="'.DOL_URL_ROOT.'/loan/payment/payment.php?id='.$object->id.'&action=create">'.$langs->trans('DoPayment').'</a>';
355 $printed = true;
356 }
357 print '</td>';
358 print '</tr>'."\n";
359 $i++;
360 $capital = $cap_rest;
361 }
362}
363
364print '</table>';
365print '</div>';
366
367print '</br>';
368
369if (count($echeances->lines) == 0) {
370 $label = $langs->trans("Create");
371} else {
372 $label = $langs->trans("Save");
373}
374print '<div class="center"><input type="submit" class="button button-add" value="'.$label.'" '.(($pay_without_schedule == 1) ? 'disabled title="'.$langs->trans('CantUseScheduleWithLoanStartedToPaid').'"' : '').'title=""></div>';
375print '</form>';
376
377// End of page
378llxFooter();
379$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage generation of HTML components Only common components must be here.
Class to manage building of HTML components.
Loan.
Class to manage Schedule of loans.
Class to manage projects.
price2numjs(amount)
Function similar to PHP price2num()
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:126
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
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 '.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
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.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
isModEnabled($module)
Is Dolibarr module enabled.
treeview li table
No Email.
loan_prepare_head($object)
Prepare array with list of tabs.
Definition loan.lib.php:34
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition repair.php:130
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.