Hallo mede Php-ers,
Sinds enkele dagen ben ik bezig met een ingewikkelde (althans ik vind het ingewikkeld) renteberekeningsclass. De berekeningen zijn redelijk nauwkeurig en komen voor wat betreft de enkelvoudige rente en meervoudige contractuele rente exact overeen met de online tool die meestal voor dergelijke renteberekeningen wordt gebruikt: http://www.wettelijkerente.net/renteberekening.aspx
De wettelijke handelsrente komt nog niet helemaal overeen met voornoemde online bereken tool en dat betekent dat OF mijn formule onjuist is OF de online rekentool. Uiteraard zou ik graag willen weten of jullie zien waar dit aan ligt en of er verbeterpunten zijn (ongetwijfeld).
Hieronder de 2 classes:
<?php
public function checkJaarGrens($vervalDatum,$beginDatum,$eindDatum,$numOfYears){
// Controleer of de periode jaargrens bevat
for($i = 1; $i < $numOfYears + 1; $i++)
{
if(
($beginDatum < ($vervalDatum + ($i*60*60*24*365))) &&
($eindDatum > ($vervalDatum + ($i*60*60*24*365))) )
{
return $vervalDatum + ($i*60*60*24*365);
}
}
}
// Bereken rente
public function calcRente($renteSoort,$samengesteld){
// Gegevens factuur ophalen
$db = new PDO('mysql:host=localhost;port=3307;dbname=****','****','****');
$sql = "SELECT
UNIX_TIMESTAMP(factuurDatum) AS factuurDatum,
factuurBedrag,betaalTermijn,renteSamengesteld, rentePercentage
FROM Invoice WHERE id = '".$this->_id."'";
$result = $db->query($sql);
foreach($result as $row)
{
// Gegevens verzamelen
$heden = time();
$factuurBedrag = $row['factuurBedrag'];
$rentePercentage = $row['rentePercentage'];
$samengesteld = $row['renteSamengesteld'];
$factuurDatum = $row['factuurDatum']; // Datum in seconden
$vervalDatum = $factuurDatum + ($row['betaalTermijn']*24*60*60) + (60*60*24);
$rentePeriode = $heden - $vervalDatum;
$subtotaal = $factuurBedrag;
$subtotaalRente = 0;
echo '<br /><br />';
echo 'De begindatum van de factuur is '.$row['factuurDatum'].'<br />';
echo 'De betaaltermijn is '.$row['betaalTermijn'].' dagen.<br />';
echo 'Dit zijn '.$row['betaalTermijn']*24*60*60 .' seconden.<br />';
echo 'Dit betekent een vervalDatum per '.$vervalDatum.'<br />';
echo 'Dit betekent een vervalDatum per '.date('Y-m-d',$vervalDatum).' tot aan
'.date('Y-m-d',$heden).'<br />';
echo 'De rentePeriode is dus '.$rentePeriode.' seconden of '.ceil($rentePeriode/24/60/60) .' dagen';
echo '<br /><br />';
}
if($renteSoort == 1) // == Wettelijke handelsrente
{
if($samengesteld == 1)
{
// Bereken wettelijke rente (samengesteld)
echo 'De wettelijke rente (samengesteld) wordt berekend.<br />';
$db = new PDO('mysql:host=localhost;port=3307;dbname=****','****','****');
$sql = "SELECT
UNIX_TIMESTAMP(eindDatum) AS eindDatum,
UNIX_TIMESTAMP(beginDatum) AS beginDatum,
rentePercentage
FROM wettelijkerente
WHERE renteSoort = 1
ORDER BY beginDatum ASC;
";
$result = $db->query($sql);
$aantalJaar = floor(($heden - $vervalDatum)/60/60/24/365);
echo 'Er zijn '.$aantalJaar.' jaren<br />';
foreach($result as $row){
$beginDatum = $row['beginDatum'];
$eindDatum = $row['eindDatum'];
$rentePercentage = $row['rentePercentage'];
// Periodes afbakenen
if(
($beginDatum < $vervalDatum) && ($eindDatum > $vervalDatum) && ($eindDatum <= $heden) ||
($beginDatum < $vervalDatum) && ($eindDatum > $vervalDatum) && ($eindDatum >= $heden) ||
($beginDatum > $vervalDatum) && ($eindDatum > $vervalDatum) && ($eindDatum <= $heden) ||
($beginDatum > $vervalDatum) && ($eindDatum > $vervalDatum) && ($eindDatum >= $heden)
)
{
echo 'De begindatum: '.date('d-m-Y',$beginDatum).'<br />';
echo 'De einddatum: '.date('d-m-Y',$eindDatum).'<br />';
echo 'Het rentepercentage: '.$rentePercentage.'<br />';
// ==> Eerste periode
if( ($beginDatum < $vervalDatum) && ($eindDatum > $vervalDatum) && ($eindDatum < $heden) )
{
echo 'Deze periode is gebroken aan het begin.<br />';
// Controleer of de periode jaargrens bevat
if($this->checkJaarGrens($vervalDatum,$beginDatum,$eindDatum,$aantalJaar) > 0)
{
// Ja, er is een jaargrens binnen deze periode
echo 'Deze periode bevat een jaargrens<br />';
$jaarGrens = $this->checkJaarGrens($vervalDatum,$vervalDatum,$eindDatum,$aantalJaar);
echo 'Deze periode heeft '. ceil(($eindDatum-$vervalDatum)/60/60/24) .' dagen<br />';
// ==> Eerste gedeelte rente
// Aantal dagen voor de jaargrens
$aantalDagen = ceil(($jaarGrens - $vervalDatum)/60/60/24);
echo 'Aantal dagen in de periode voor de jaargrens: '.$aantalDagen.'<br />';
// Rente voor de jaargrens berekenen
$renteBedrag = ($subtotaal * ($rentePercentage/100))/365*$aantalDagen;
echo 'Oud subtotaal = '.$subtotaal.'<br />';
echo 'Rente deze periode: '.$renteBedrag.'<br />';
echo 'Rente vorige periodes: '.$subtotaalRente.'<br />';
echo 'Subtotaal rente: '.$renteBedrag + $subtotaalRente.'<br />';
// Oude rente (vorige periodes) en nieuwe rente bij elkaar optellen
$subtotaalRente = $subtotaalRente + $renteBedrag;
echo 'Subtotaal rente: '.$subtotaalRente.'<br />';
// ==> Nieuw subtotaal berekenen
// Nieuwe rente tot nu toe optellen bij subtotaal
$subtotaal = $subtotaal + $subtotaalRente;
echo 'Nieuw subtotaal = '.$subtotaal.'<br />';
// subtotaalRente resetten (want reeds bij subtotaal opgeteld)
$subtotaalRente = 0;
// ==> Twee gedeelte rente
// Aantal dagen voor de jaargrens
$aantalDagen = ceil(($eindDatum - $jaarGrens)/60/60/24);
echo 'Aantal dagen in de periode na de jaargrens: '.$aantalDagen.'<br />';
// Rente na de jaargrens berekenen
$renteBedrag = ($subtotaal * ($rentePercentage/100))/365*$aantalDagen;
$subtotaalRente = $subtotaalRente + $renteBedrag;
echo 'Nieuwe rente deze periode: '.$renteBedrag.'<br />';
echo 'Rente subtotaal: '.$subtotaalRente.'<br />';
}else{
// Nee, er is geen jaargrens binnen deze periode
echo 'Deze periode bevat geen jaargrens.<br />';
// Aantal dagen berekenen
$aantalDagen = ceil(($eindDatum - $vervalDatum)/60/60/24);
echo 'Aantal dagen in deze periode: '.$aantalDagen.'<br />';
echo 'Subtotaal: '.$subtotaal.'<br />';
// Rente berekenen en toevoegen aan renteSubtotaal
$renteBedrag = ($subtotaal * ($rentePercentage/100))/365*$aantalDagen;
echo 'Rentebedrag deze periode: '.$renteBedrag.'<br />';
$subtotaalRente = $subtotaalRente + $renteBedrag;
echo 'Rente subtotaal: '.$subtotaalRente.'<br />';
}
}
// ==> Laatste periode
elseif( (($beginDatum < $vervalDatum) && ($eindDatum > $heden)) ||
(($beginDatum > $vervalDatum) && ($eindDatum > $heden)) )
{
echo 'Deze periode is gebroken aan het einde<br />';
// Controleer of de periode jaargrens bevat
if($this->checkJaarGrens($vervalDatum,$beginDatum,$heden,$aantalJaar) > 0)
{
// Ja, er is een jaargrens binnen deze periode
echo 'Deze periode bevat een jaargrens<br />';
$jaarGrens = $this->checkJaarGrens($vervalDatum,$beginDatum,$heden,$aantalJaar);
echo 'Deze periode heeft '. ceil(($eindDatum-$vervalDatum)/60/60/24) .' dagen<br />';
// ==> Eerste gedeelte rente
// Aantal dagen voor de jaargrens
$aantalDagen = ceil(($jaarGrens - $vervalDatum)/60/60/24);
echo 'Aantal dagen in de periode voor de jaargrens: '.$aantalDagen.'<br />';
// Rente voor de jaargrens berekenen
$renteBedrag = ($subtotaal * ($rentePercentage/100))/365*$aantalDagen;
echo 'Oud subtotaal = '.$subtotaal.'<br />';
echo 'Rente deze periode: '.$renteBedrag.'<br />';
echo 'Rente vorige periodes: '.$subtotaalRente.'<br />';
echo 'Subtotaal rente: '.$renteBedrag + $subtotaalRente.'<br />';
// Oude rente (vorige periodes) en nieuwe rente bij elkaar optellen
$subtotaalRente = $subtotaalRente + $renteBedrag;
echo 'Subtotaal rente: '.$subtotaalRente.'<br />';
// ==> Nieuw subtotaal berekenen
// Nieuwe rente tot nu toe optellen bij subtotaal
$subtotaal = $subtotaal + $subtotaalRente;
echo 'Nieuw subtotaal = '.$subtotaal.'<br />';
// subtotaalRente resetten (want reeds bij subtotaal opgeteld)
$subtotaalRente = 0;
// ==> Twee gedeelte rente
// Aantal dagen voor de jaargrens
$aantalDagen = ceil(($heden - $jaarGrens)/60/60/24);
echo 'Aantal dagen in de periode na de jaargrens: '.$aantalDagen.'<br />';
// Rente na de jaargrens berekenen
$renteBedrag = ($subtotaal * ($rentePercentage/100))/365*$aantalDagen;
$subtotaalRente = $subtotaalRente + $renteBedrag;
echo 'Nieuwe rente deze periode: '.$renteBedrag.'<br />';
echo 'Rente subtotaal: '.$subtotaalRente.'<br />';
}else{
// Nee, er is geen jaargrens binnen deze periode
echo 'Deze periode bevat geen jaargrens.<br />';
if($vervalDatum > $heden)
{
// Aantal dagen berekenen
$aantalDagen = ceil(($heden - $vervalDatum)/60/60/24);
}
else
{
// Aantal dagen berekenen
$aantalDagen = ceil(($heden - $beginDatum)/60/60/24);
}
echo 'Aantal dagen in deze laatste periode: '.$aantalDagen.'<br />';
echo 'Subtotaal voor rente: '.$subtotaal.'<br />';
echo 'Rente subtotaal vorige periodes: '.$subtotaalRente.'<br />';
// Rente berekenen en toevoegen aan renteSubtotaal
$renteBedrag = ($subtotaal * ($rentePercentage/100))/365*$aantalDagen;
$subtotaalRente = $subtotaalRente + $renteBedrag;
echo 'Nieuwe rente deze periode: '.$renteBedrag.'<br />';
echo 'Rente subtotaal: '.$subtotaalRente.'<br />';
// Totaalbedrag berekenen
$subtotaal = $subtotaal + $subtotaalRente;
echo 'Totaalbedrag: '.$subtotaal.'<br />';
}
}
// ==> Tussenperiode
else
{
echo 'Deze periode is niet gebroken maar heel<br />';
// Controleer of de periode jaargrens bevat
if($this->checkJaarGrens($vervalDatum,$beginDatum,$eindDatum,$aantalJaar) > 0)
{
// Ja, er is een jaargrens binnen deze periode
echo 'Deze periode bevat een jaargrens<br />';
$jaarGrens = $this->checkJaarGrens($vervalDatum,$beginDatum,$eindDatum,$aantalJaar);
echo 'Deze periode heeft '. ceil(($eindDatum-$beginDatum)/60/60/24) .' dagen<br />';
// ==> Eerste gedeelte rente
// Aantal dagen voor de jaargrens
$aantalDagen = ceil(($jaarGrens - $beginDatum)/60/60/24);
echo 'Aantal dagen in de periode voor de jaargrens: '.$aantalDagen.'<br />';
// Rente voor de jaargrens berekenen
$renteBedrag = ($subtotaal * ($rentePercentage/100))/365*$aantalDagen;
echo 'Oud subtotaal = '.$subtotaal.'<br />';
echo 'Rente deze periode: '.$renteBedrag.'<br />';
echo 'Rente vorige periodes: '.$subtotaalRente.'<br />';
echo 'Subtotaal rente: '.$renteBedrag + $subtotaalRente.'<br />';
// Oude rente (vorige periodes) en nieuwe rente bij elkaar optellen
$subtotaalRente = $subtotaalRente + $renteBedrag;
echo 'Subtotaal rente: '.$subtotaalRente.'<br />';
// ==> Nieuw subtotaal berekenen
// Nieuwe rente tot nu toe optellen bij subtotaal
$subtotaal = $subtotaal + $subtotaalRente;
echo 'Nieuw subtotaal = '.$subtotaal.'<br />';
// subtotaalRente resetten (want reeds bij subtotaal opgeteld)
$subtotaalRente = 0;
// ==> Twee gedeelte rente
// Aantal dagen voor de jaargrens
$aantalDagen = ceil(($eindDatum - $jaarGrens)/60/60/24);
echo 'Aantal dagen in de periode na de jaargrens: '.$aantalDagen.'<br />';
// Rente na de jaargrens berekenen
$renteBedrag = ($subtotaal * ($rentePercentage/100))/365*$aantalDagen;
$subtotaalRente = $subtotaalRente + $renteBedrag;
echo 'Nieuwe rente deze periode: '.$renteBedrag.'<br />';
echo 'Rente subtotaal: '.$subtotaalRente.'<br />';
}else{
// Nee, er is geen jaargrens binnen deze periode
echo 'Deze periode bevat geen jaargrens.<br />';
// Aantal dagen berekenen
$aantalDagen = ceil(($eindDatum - $beginDatum)/60/60/24);
echo 'Aantal dagen in deze periode: '.$aantalDagen.'<br />';
echo 'Subtotaal: '.$subtotaal.'<br />';
// Rente berekenen en toevoegen aan renteSubtotaal
$renteBedrag = ($factuurBedrag * ($rentePercentage/100))/365*$aantalDagen;
echo 'Rentebedrag deze periode: '.$renteBedrag.'<br />';
// Subtotaal rente
$subtotaalRente = $subtotaalRente + $renteBedrag;
echo 'Rentesubtotaal: '.$subtotaalRente.'<br />';
}
}
echo '<br />';
}
}
// Bereken de som van alle rentePeriodes
}
else
{
// Bereken wettelijke rente (enkelvoud)
return 'De wettelijke rente (enkelvoud) wordt berekend';
}
}elseif($renteSoort == 2) // == Wettelijke rente
{
if($samengesteld == 1)
{
// Bereken wettelijke handelsrente (samengesteld)
return 'De wettelijke handelsrente (samengesteld) wordt berekend';
}
else
{
// Bereken wettelijke handelsrente (enkelvoud)
return 'De wettelijke handelsrente (enkelvoud) wordt berekend';
}
}elseif($renteSoort == 3)
{
if($samengesteld == 1) // == Contractuele rente
{
// Bereken contractuele rente (samengesteld)
$bedrag = $factuurBedrag;
$rente = $rentePercentage;
$produkt = 100+$rente;
$rentePeriode = $heden - $vervalDatum;
$jaar = ceil($rentePeriode/24/60/60)/365;
for ($i = 1;$i<$jaar;$i++){
$bedrag = ($bedrag/100)*$produkt;
// echo '<p>Jaar ' . ($i) . ' - ' . $bedrag . '</p>';
$value[] = $bedrag;
}
// Nu dient nog het 'staartje' te worden toegevoegd.
$restPeriode = floor(($jaar-floor($jaar))*365-2);
$subtotaal = $value[floor($jaar)-1];
$restRente = $subtotaal*($rente/100)/365*$restPeriode;
$totaal = round($subtotaal+$restRente,2);
echo 'De contractuele rente (samengesteld) wordt berekend.<br />';
echo 'Resultaat = '.$totaal;
}
elseif($samengesteld == 2)
{
// Bereken contractuele handelsrente (enkelvoud)
$rentePeriode = $heden - $vervalDatum;
echo 'De contractuele rente (enkelvoud) wordt berekend.<br />';
echo 'Resultaat = ';
echo number_format($factuurBedrag * ($rentePercentage/100) / 365 * ceil($rentePeriode/24/60/60),2);
echo '<br />';
}
}
}
}
?>
Weergeven doe ik op de volgende wijze:
<?php
$_GET['dossier'] = '1';
// Instants van classes creeren
$invoice = new Invoice($_GET['dossier']);
$user = new User($invoice->getUser());
$debtor = new Debtor($invoice->getDebtor());
$dossier = new Dossier($invoice->getId());
$misc = new Misc();
// Factuurgegevens ophalen
$db = new PDO('mysql:host=localhost;port=3307;dbname=****','****','****');
$sql = "SELECT id,rentePercentage,renteSoort FROM invoice WHERE dossierId = ".$dossier->getId();
$result = $db->query($sql);
$i = 0;
foreach($result as $row) {
$obj = new Invoice($row['id']);
// Bereken rente
echo $obj->calcRente($row['renteSoort'],$row['rentePercentage']);
$i++;
}
unset($obj);
?>
7.704 views