MFRPG: Rente betalen via `before insert` trigger...
Ik ben bezig met het maken van een financiele morpg. Ik noem het maar een MFRPG...
In dit spel zijn er natuurlijk banken, die via een rekening type & vestiging, bank rekeningen kunnen uitgeven. Zo'n bank rekening kan een 'SPAAR' rekening zijn waar op een bepaalde moment (per jaar of per maand) rente betaald moet worden.
Nu heb ik het volgende bedacht:
De rekening tabel waar de gegevens PER REKENING in staan, krijgt een BEFORE UPDATE trigger. Dus steeds als deze REKENING aangepast wordt, wordt er een script uitgevoerd. In dit script bereken ik dan hoeveel rente iemand moet ontvangen en sla dit op in een speciaal veld: "rknRENTESALDO". Aan het einde van de maand of jaar worden deze waardes in de rknRENTESALDO overgeboekt naar het rknSALDO veld, via een PROCEDURE (Betaal rente).
Voorbeeld:
Op 5 januarie om 12:00 opent een persoon een bepaalde rekening met 5% rente en stort hier 100,- euro op.
Op 10 Januarie om 12:00, stort deze persoon 900,- euro.
Op 20 Januarie om 12:00, neemt deze persoon 200,- euro van zijn rekening op.
Nu is de vraag: hoeveel rente ontvangt deze persoon op 1-2-2011 om 12:00?
Bij mijn script wordt het dan zo gedaan:
- Eerst een INSERT.... Voor het aanmaken van de rekening...
Het veld rknSALDODATUM van het type TIMESTAMP wordt op CURRENT_TIMESTAMP (Default waarde) gezet. Dus tot deze datum is de rente dan berekend.
- Update 1:
Op 10 januarie om 12:00 wordt een UPDATE gedaan van het saldo van 100,- naar 1000,-
Nu gaan we de rente berekenen over de periode rknSALDODATUM (5 Januarie) en NU (CURRENT_TIMESTAMP = 10 Januarie). De periode is dan gewoon: CURRENT_TIMESTAMP - rknSALDODATUM. Nu moeten we dit getal gaan omrekenen naar "PER JAAR", dit omdat de rente altijd wordt aangegeven per jaar in dit spel. Ook al betalen we het elke maand uit !. Dus de rente die deze persoon ontvangt is dan de rente over het bedrag x De periode in jaren.
De ontvangen rente doen we niet meteen bij het rknSALDO optellen maar eerst optellen bij de rknRENTESALDO. Op het moment dat de bank de rente gaat uitkeren, wordt voor elke rekening de rente opnieuw berekend tot nu en van deze bank de rknRENTESALDO opgeteld bij de rknSALDO en de rknRENTESALDO wordt dan weer gewist.
Hierdoor heb ik dan een spaar rekening gemaakt waarvan de rente redelijk klopt. Behalve als men heel veel transacties kort achter elkaar doet kan men afrond fouten krijgen. Het berekenen van de periode in tijd wordt op 100ste van een seconde bepaald en de rknRENTESALDO tot op 6 cijfers achter de komma, zodat de afrond fouten gering zijn.
Zijn er ook nog andere oplossingen mogelijk die een juiste rente kunnen berekenen op steeds wijzigende rekeningen?
Oja: Met het overboeken ga ik dit ook oplossen volledig in de database. Dit omdat het betalings verkeer het meest gebruikte logica is in het spel. En omdat het een MASSIVE ONLINE game is wil ik het zo gemakkelijk mogelijk maken voor de server.
Het overboeken ga ik procedure maken die je 3 parameters mee geeft.
Bedrag, RekeningVan, RekeningNaar en die geeft een 1 voor "OK" en 0 of kleiner voor "0=Mislukt (Onbekende fout)" of andere error code. Het overboeken werkt dan met een database transactie.
Verder wil ik het zo maken dat je deze functie/procedure ook op een view toegepast kunnen worden. Zodat men ook grote 'batches' van betalings opdrachten op een bepaalde datum kan laten uitvoeren.
Iemand nog een ander idee ?
Groetjes: Roger Keulen.
Ps: M'n MySQL Workbench 5.2 CE valt steeds uit. (Ben ik de enige die dit probleem heeft?)
Toevoeging op 26/04/2011 19:31:51:
Mooi we hebben hem werkend:
DELIMITER $$
USE `MFRPG`$$
CREATE TRIGGER before_rekeningen_update
BEFORE UPDATE ON rkn_REKENINGEN
FOR EACH ROW BEGIN
SET @Verschil = CURRENT_TIMESTAMP - OLD.rknRENTEDATUM;
if @Verschil > 0 and OLD.rknISACTIEF then
SET NEW.rknRENTESALDO = OLD.rknRENTESALDO + ((OLD.rknSALDO * (OLD.rknRENTE / 100)) / (345600 * @Verschil));
SET NEW.rknRENTEDATUM = CURRENT_TIMESTAMP; -- Reset Datumtijd...
END IF;
END$$
rknRENTEDATUM = Timestamp met default waarde: CURRENT_TIMESTAMP
En 345600 is er omdat in het spel 4 dagen 1 jaar is. Het is een financiele morpg en die van mij werkt met kwartalen.
Ga nu de RENTE UITBETAAL functionaliteit maken.
En deze wil ik kunnen aanroepen per: Rekening, RekeningType, Vestiging en Bank.
Dus een view die deze data toont...
En ik maak voor elke groepering een PROCEDURE die de SQL WHERE maakt en deze doorgeeft aan de echte UITBETAAL RENTE PROCEDURE... En dat hoeft nog niet met transacties...
Het volgende daarna: Betalings verkeer.... Dus wie idieen heeft....
Steeds als het rknSALDO wijzigd, dus UPDATE wordt getriggerd, zal er rente worden berekend. Dit wordt opgeslagen in rknRENTESALDO.
Op het moment dat ik een UPDATE SET rknRENTESALDO = 0 doe, betaal ik de rente uit.
Door rknRENTESALDO + de rente tot nu op te tellen bij het saldo.
Ik ga hem nu nog zo aanpassen dat hij ook met terugwerkende kracht werkt.
Dus het script moet runnen op 01-01-2012 12:00:00
en hij runt 2 seconde later omdat er nog een procedure liep.
Dan wil ik toch de berekening om 12:00:00 als tijd neemt.
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
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
-- Trigger DDL Statements
DELIMITER $$
USE `MFRPG`$$
-- Uitbetalen en optellen van de rente...
CREATE TRIGGER before_rekeningen_update
BEFORE UPDATE ON rkn_REKENINGEN
FOR EACH ROW BEGIN
-- Aantal Seconde geleden laatste RUN
SET @Verschil = CURRENT_TIMESTAMP - OLD.rknRENTEDATUM;
-- Wanneer RENTE OVERHEVELEN ....
-- Verschil groter dan seconde + Rekening Actief...
if NEW.rknHEEFTRENTE and @Verschil > 0 and OLD.rknISACTIEF then
SET @Rente = ((OLD.rknSALDO * (OLD.rknRENTE / 100)) / (345600 * @Verschil));
-- Zetten we de RENTESALDO op 0 dan betalen we de rente uit.
if NEW.rknRENTESALDO = 0 then
-- Uitbetalen rente...
SET NEW.rknSALDO = OLD.rknSALDO + OLD.rknRENTESALDO + @Rente;
ELSE
-- Cumalatief optellen van de rente...
SET NEW.rknRENTESALDO = OLD.rknRENTESALDO + @Rente;
end if;
-- Reset Datumtijd...
SET NEW.rknRENTEDATUM = CURRENT_TIMESTAMP;
END IF;
END$$
DELIMITER $$
USE `MFRPG`$$
-- Uitbetalen en optellen van de rente...
CREATE TRIGGER before_rekeningen_update
BEFORE UPDATE ON rkn_REKENINGEN
FOR EACH ROW BEGIN
-- Aantal Seconde geleden laatste RUN
SET @Verschil = CURRENT_TIMESTAMP - OLD.rknRENTEDATUM;
-- Wanneer RENTE OVERHEVELEN ....
-- Verschil groter dan seconde + Rekening Actief...
if NEW.rknHEEFTRENTE and @Verschil > 0 and OLD.rknISACTIEF then
SET @Rente = ((OLD.rknSALDO * (OLD.rknRENTE / 100)) / (345600 * @Verschil));
-- Zetten we de RENTESALDO op 0 dan betalen we de rente uit.
if NEW.rknRENTESALDO = 0 then
-- Uitbetalen rente...
SET NEW.rknSALDO = OLD.rknSALDO + OLD.rknRENTESALDO + @Rente;
ELSE
-- Cumalatief optellen van de rente...
SET NEW.rknRENTESALDO = OLD.rknRENTESALDO + @Rente;
end if;
-- Reset Datumtijd...
SET NEW.rknRENTEDATUM = CURRENT_TIMESTAMP;
END IF;
END$$
Verder probeer ik m'n layout te maken van het rechten gedeelte voor de web-sites die bij het ontwikkelen van de test simulator en het spel horen.
Gewijzigd op 28/04/2011 22:36:53 door Roger Keulen