Project: Wettelijke rente berekenen
Ik ben bezig met een script om de wettelijke rente te berekenen. Op internet kom je dit al wel tegen in javascript maar aangezien ik daar geen verstand van heb probeer ik het voor mijn site (www.rechtenstudent.net) - die binnenkort geheel vernieuwd zal worden - in PHP te scripten.
Ik zal hierbij hoogstwaarschijnlijk meerdere malen genoodzaakt zijn jullie hulp in te schakelen vandaar deze intro! Ik zal proberen deze intro steeds verder te updaten zodat ook de nieuwste vraag hierin te vinden zal zijn.
Het script zal als volgt moeten gaan werken:
- Men voert een begindatum, einddatum en hoofdsom in en drukt op verzenden;
- Berekenen aantal dagen tussen start_date en end_date;
- Berekenen specifieke rentepercentages per periode (rente verschilt per periode);
- Opslag berekenen (eens per jaar wordt de rente bij de hoofdsom opgeteld en wordt vervolgens met die gemuteerde hoofdsom verder gerekend);
- De totale rente, totale opslag (mutatie) en totale hoofdsom incl mutatie wordt weergegeven;
Dit is het script tot nu toe:
VERSIE 1.1.5
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<form method="post" action="wettelijkerente.php?action=bereken_rente">
<p>Startdatum:</p>
<select name="start_day" style="width:50px;">
<option value="01">01</option>
<option value="01">31</option>
</select>
<select name="start_month" style="width:200px;">
<option value="01">Januari</option>
<option value="12">December</option>
</select>
<select name="start_year" style="width:100px;">
<option value="2002">2002</option>
<option value="2009">2009</option>
</select>
<br />
<p>Einddatum:</p>
<select name="end_day" style="width:50px;">
<option value="01">01</option>
<option value="01">31</option>
</select>
<select name="end_month" style="width:200px;">
<option value="01">Januari</option>
<option value="12">December</option>
</select>
<select name="end_year" style="width:100px;">
<option value="2002">2002</option>
<option value="2009">2009</option>
</select>
<br />
<p>Hoofdsom:</p>
<input type="text" name="hoofdsom" value="00,00" />
<br />
<input type="submit" value="Bereken" />
</form>
<br />
<br />
<?php
if($_SERVER['REQUEST_METHOD'] == 'POST' && $_GET['action'] == 'bereken_rente'){
// Startdag berekenen:
$start_day = $_POST['start_day'];
$start_month = $_POST['start_month'];
$start_year = $_POST['start_year'];
if(checkdate($start_month,$start_day,$start_year) == 'TRUE'){
$start_date = $start_year . '-' . $start_month . '-' . $start_day;
}else{
$error .= "De ingegeven startdatum is niet juist.<br />";
}
$startdag = date('z', strtotime($start_date)) + 1;
// Einddag berekenen:
$end_day = $_POST['end_day'];
$end_month = $_POST['end_month'];
$end_year = $_POST['end_year'];
if(checkdate($end_month,$end_day,$end_year) == 'TRUE'){
$end_date = $end_year . '-' . $end_month . '-' . $end_day;
}else{
$error .= "De ingegeven einddatum is niet juist.<br />";
}
$einddag = date('z', strtotime($end_date)) + 1;
// Verschil in dagen berekenen:
$dagen = (strtotime($end_date) - strtotime($start_date)) / (60 * 60 * 24);
// Invoerdata vergelijken met data rentepercentages uit db:
// Uitvoer:
echo 'Start date: ' . $start_date . '<br />';
echo 'End date: ' . $end_date . '<br />';
echo 'Startdag: ' . $startdag . '<br />';
echo 'Einddag: ' . $einddag . '<br />';
echo 'Aantal dagen verschil: ' . $dagen . '<br />';
if(!empty($error)){
echo '<br /><br />Fout:<br />' . $error;
}
}
?>
<p>Startdatum:</p>
<select name="start_day" style="width:50px;">
<option value="01">01</option>
<option value="01">31</option>
</select>
<select name="start_month" style="width:200px;">
<option value="01">Januari</option>
<option value="12">December</option>
</select>
<select name="start_year" style="width:100px;">
<option value="2002">2002</option>
<option value="2009">2009</option>
</select>
<br />
<p>Einddatum:</p>
<select name="end_day" style="width:50px;">
<option value="01">01</option>
<option value="01">31</option>
</select>
<select name="end_month" style="width:200px;">
<option value="01">Januari</option>
<option value="12">December</option>
</select>
<select name="end_year" style="width:100px;">
<option value="2002">2002</option>
<option value="2009">2009</option>
</select>
<br />
<p>Hoofdsom:</p>
<input type="text" name="hoofdsom" value="00,00" />
<br />
<input type="submit" value="Bereken" />
</form>
<br />
<br />
<?php
if($_SERVER['REQUEST_METHOD'] == 'POST' && $_GET['action'] == 'bereken_rente'){
// Startdag berekenen:
$start_day = $_POST['start_day'];
$start_month = $_POST['start_month'];
$start_year = $_POST['start_year'];
if(checkdate($start_month,$start_day,$start_year) == 'TRUE'){
$start_date = $start_year . '-' . $start_month . '-' . $start_day;
}else{
$error .= "De ingegeven startdatum is niet juist.<br />";
}
$startdag = date('z', strtotime($start_date)) + 1;
// Einddag berekenen:
$end_day = $_POST['end_day'];
$end_month = $_POST['end_month'];
$end_year = $_POST['end_year'];
if(checkdate($end_month,$end_day,$end_year) == 'TRUE'){
$end_date = $end_year . '-' . $end_month . '-' . $end_day;
}else{
$error .= "De ingegeven einddatum is niet juist.<br />";
}
$einddag = date('z', strtotime($end_date)) + 1;
// Verschil in dagen berekenen:
$dagen = (strtotime($end_date) - strtotime($start_date)) / (60 * 60 * 24);
// Invoerdata vergelijken met data rentepercentages uit db:
// Uitvoer:
echo 'Start date: ' . $start_date . '<br />';
echo 'End date: ' . $end_date . '<br />';
echo 'Startdag: ' . $startdag . '<br />';
echo 'Einddag: ' . $einddag . '<br />';
echo 'Aantal dagen verschil: ' . $dagen . '<br />';
if(!empty($error)){
echo '<br /><br />Fout:<br />' . $error;
}
}
?>
Log:
29-01-2009 15u16m - aantal dagen verschil toegevoegd.
29-01-2009 17u10m - <form> aangepast.
29-01-2009 17u12m - php-script aangepast.
HUIDIG PROBLEEM:
Het bepalen welke dagen van de ingegeven start en end date in welke rente periode vallen en het berekenen van de bijbehorende rente per periode.
Gewijzigd op 01/01/1970 01:00:00 door The Ultimate
En mbt tot wat mogelijk is met PHP, ik denk dat we zelfs het ISS op PHP kunnen laten lopen als we maar genoeg tijd krijgen ;).
Bart schreef op 29.01.2009 14:14:
Dag forumleden
klinkt mij vrij complex in de oren want je hebt het over verschillende rentes en verschillende periodes.
dus je ken ook met 2 rente tarieven te maken krijgen.
het eerste wat ik me afvroeg ga je die rentes per periode op slaan ?
hoe had je dat in gedachten te gaan doen ?
Wellicht is dat een goed idee. Dan kan er ook niets fout gaan met de invoer, behalve dat men bijvoorbeeld in februari kiest voor 31 dagen.....heb jij daar een oplossing voor?
@rvw:
Er zijn inderdaad meerdere renteperiodes. Deze veranderen zo'n 2 keer per jaar. Mijn idee was om deze per periode op te slaan in een databasetable (dus: start_date, end_date en rentepercentage). Lijkt dit wat?
En voor wat betreft je tweede vraag sluit ik me aan bij Arjan. Gebruik select boxen voor het invoeren van de datum, dat beperkt de mogelijkheid tot foute invoer en scheelt jou weer een aantal stappen in PHP.
ps. Gebruik checkdate() om te controleren of een datum wel klopt..
Gewijzigd op 01/01/1970 01:00:00 door Joren de Wit
Of je checked het achteraf met de checkdate() en geeft daar een melding van terug.
- checkdate() toegevoegd.
- versienr erboven geplaatst, zodat men in de gaten kan houden of het script is gewijzigd. Ik blijf namelijk in het origineel wijzigingen aanbrengen.
- onderaan originele topic zal het HUIDIGE PROBLEEM worden weergegeven waar ik op dat moment mee worstel.
Gewijzigd op 01/01/1970 01:00:00 door The Ultimate
Code (php)
Maar er zullen ongetwijfeld meerdere oplossingen voor te verzinnen zijn.
Jouw dagen verschil berekening is toegevoegd.
Volgende probleem is het opzetten van een databasetable met daarin de rentepercentages per periode zodat we deze vervolgens naar de ingegeven start_date en end_date kunnen leggen.
- dag 1 t/m 5 = 4%
- dag 6 t/m 12 = 4,2%
etc etc
Goed dat je het vraagt want die rentepercentages zijn anders opgebouwd:
Per 2002-08-08 7.00 %
Per 2002-12-01 10.35 %
Per 2003-01-01 9.85 %
Per 2003-07-01 9.10 %
Per 2004-01-01 9.02 %
Per 2004-07-01 9.01 %
Per 2005-01-01 9.09 %
Per 2005-07-01 9.05 %
Per 2006-01-01 9.25 %
Per 2006-07-01 9.83 %
Per 2007-01-01 10.58 %
Per 2007-07-01 11.07 %
Per 2008-01-01 11.20 %
Per 2008-07-01 11.07 %
Per 2009-01-01 9.50 %
Hoe zet je dit nu het best in een databasetable?
Zoiets denk ik:
CREATE TABLE rente (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
percentage VARCHAR(10),
start DATE,
end DATE
);
Alleen weet ik niet of percentage VARCHAR wel handig is. Kan dit niet beter INT of DOUBLE zijn?
Gewijzigd op 01/01/1970 01:00:00 door The Ultimate
Om te beginnen is een percentage een decimaal getal, dus dat zou een DECIMAL worden. Verder zit je met je begin- en einddatum wel goed...
CREATE TABLE `rente` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`percentage` DECIMAL NOT NULL ,
`start_date` DATE NOT NULL ,
`time_secs` INT( 255 ) NOT NULL COMMENT 'the number of seconds since January 1 1970 00:00:00 UTC'
) ENGINE = MYISAM ;
@Blanche:
Ik heb er DECIMAL van gemaakt. Overigens heb ik niet gekozen voor een einddatum, dit omdat het voor problemen kan zorgen met het rekenen ermee. Ik denk namelijk dat de beste manier is om te kijken of een bepaalde datum via strtotime() groter is dan time_secs in de ene row en kleiner dan een time_secs uit een andere row. Eigenlijk heb je dan dus ook de 'start_date' niet nodig, maar ja....
Als jij hier anders over denkt dan hoor ik dat uiteraard ZEER graag...!!
Maar de kolom time_secs zou ik wel overboord kieperen. Het lijkt misschien leuk om die waarde in je tabel te hebben staan, maar je kunt dit net zo goed berekenen op het moment dat je hem nodig hebt.
Verder zou ik de meeste van je berekeningen wat betreft datums, verplaatsen naar je sql queries. Rekenen met data en tijdens is nu eenmaal veel eenvoudiger in de database dan in PHP. Om nu verder te gaan, zou de volgende tabel dus voldoen:
rente
------
id
percentage DECIMAL
start_date DATE
Als je nu enkel on-the-fly berekeningen wilt uitvoeren is het nog niet nodig om de ingevoerde perioden (en hoofdsommen) op te slaan. Maar het zou kunnen dat je later besluit om deze gegevens toch op te slaan, al is het maar voor de statistiek. Vanuit dat oogpunt zou ik dan ook voor de InnoDB engine kiezen ipv MyISAM, dan ben je later in staat om er een relationele database van te maken.
Tenslotte nog een punt. Je geeft wel een lijst met percentages per periode, maar hoe worden die rentes toegepast? Is dat het rentepercentage per dag in die periode of is dat het percentage over de gehele periode. En verder, zoals ik ook al opmerkte in mijn vorige post, denk ik dat het verstandiger is om eerst de effectieve rente op jaarbasis te berekenen voordat je met de hoofdsom gaat rekenen.
Bart schreef op 29.01.2009 16:03:
Dit is de table voorlopig:
ik dacht juist precies anders om je hebt geen eind tijd nodig....
want starttijd heb je juist wel nodig!
want het is namelijk van af en bepaalde datum tot NOW()
rvw schreef op 29.01.2009 16:25:
Niet noodzakelijk, zie ook de operking daarover in mijn vorige post ;-)want het is namelijk van af en bepaalde datum tot NOW()
Heb de table naar jouw advies gemaakt. Ik heb de ENGINE veranderd (weet hier zelf weinig vanaf, maar geloof je direct).
Wat betreft de rentepercentages: daar ben ik nog niet helemaal zeker van hoe deze dienen te worden berekend. Ik ben geen wiskundige en hoop dat iemand weet wat de juiste manier daartoe is.
Zelf zit ik aan zoiets te denken:
(aantal dagen / 365) * percentage = rente tot aan einde renteperiode
+
(aantal dagen / 365) * percentage = rente tot aan einde renteperiode
+
(aantal dagen / 365) * percentage = rente tot aan end_date
Gewijzigd op 01/01/1970 01:00:00 door The Ultimate
En bovendien hangt het er ook zeker vanaf welk bedrag je als basis voor de geldende rente percentages neemt. Verreken je de verkregen rente direct in het basisbedrag of doe je dat slechts op 1 moment en gebruik je dus hetzelfde basisbedrag.
Een aantal kleine voorbeeldjes om de verschillen aan te duiden (2 perioden met percentages van resp. 4% en 5%, basisbedrag 1000):
- Rentepercentage geldt per periode, basisbedrag wordt telkens bijgesteld:
Effectieve rente: 1.04 * 1.05 = 1.092 (= 9.2%)
Uiteindelijke som: 1.092 * 1000 = 1092 (= +92)
- Rentepercentage per periode, basisbedrag niet bijgesteld maar pas aan einde verwerkt:
Effectieve rente: 4% + 5% = 9%
Uiteindelijke som: 1.09 * 1000 = 1090 (= +90)
En zo kun je nog wel even door gaan met voorbeelden van als de rente bijvoorbeeld per dag zou gelden. En je kunt je ook wel voorstellen wat voor invloed dat kan hebben op de uitkomst. Het lijkt me dus wel slim om voor jezelf vast te stellen hoe die rente nu precies berekend moet worden ;-)
De renteopslag (zoals ik dat noem) die vindt eens per jaar plaats en wel precies 1 jaar na de start_date, dus:
hoofdsom = 200.00
start_date = 25-11-1981
renteopslag = 25-11-1982
bij een rentepercentage van 7% reken je dus vanaf 25-11-1982 met een hoofdsom van 214.00 lijkt mij.
Gewijzigd op 01/01/1970 01:00:00 door The Ultimate
Ik ben nu op zoek naar hetzelfde script. Is er al ergens een script verschenen? Ben benieuwd!
Zelf ben ik ook bezig met een scrip hiervoor.
Helaas kan ik dit niet tonen omdat deze gekoppeld word met ons systeem.
Wel heb ik onderaan een stukje toegevoegd om een csv bestand uit te lezen.
Dit kan je gebruiken om de wettelijke rente van wettelijkerente.net af te halen.
startbedrag: 1000,-
Jaarrente: 7.75%
Aantal dagen te laat betaald: 31 dagen
31 / 365 X (0.0775 X 1000) = 6.58
!--0,0849315068493151 X 77.5 = 6,582191780821918--!
onderste berekening is wat werkelijk gebeurd.
Het bedrag wordt afgerond.
wanneer aantal dagen te laat groter is dan 365 dan:
aantal dagen te laat betaald: 380
Jaarrente jaar 2011: 7.75%
Jaarrente jaar 2012: 5.25%
----------------------------2011---------------------------------
365 X (0.0775 X 1000) = 77.5
77.5 + 1000 = 1077.5
----------------------------2012--------------------------------- 15 / 365 X (0.0525 X 1077.5) = 2.33
!--0,0410958904109589 X 56,56875 = 2,324743150684932--!
Waarbij het eindbedrag komt op:
1077.5 + 2.33 = 1079,83
2012 is een schrikkeljaar dus bovenstaande berekening klopt niet.
Als schrikkeljaar 1 is dan is een jaar: 366
Met gevolgen dat de berekening er zo uit ziet:
----------------------------2011---------------------------------
365 X (0.0775 X 1000) = 77.5
77.5 + 1000 = 1077.5
----------------------------2012---------------------------------
15 / 366 X (0.0525 X 1077.5) = 2.32
!--0,040983606557377 X 56,56875 = 2,318391393442623--!
Waarbij het eindbedrag komt op:
1077.5 + 2.32 = 1079,82
------ Het stukje script ----
$fp = fopen("$filename","r");
$rente = array();
$x = 0;
while(! feof($fp))
{
$rente[$x] = fgetcsv($fp,"0",";");
$x++;
}
fclose($fp);