-
Notifications
You must be signed in to change notification settings - Fork 0
/
MemoryInterestCalculator.php
69 lines (53 loc) · 1.77 KB
/
MemoryInterestCalculator.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
<?php
declare(strict_types=1);
namespace Shrink\Chip\Interest;
use Lcobucci\Clock\Clock;
final class MemoryInterestCalculator implements AwardsInterest
{
/**
* Number of days to award interest for.
*/
private int $awardFrequency;
/**
* @var array<string,float>
*/
private array $pendingAwards = [];
private Clock $clock;
public function __construct(int $awardFrequency, Clock $clock)
{
$this->awardFrequency = $awardFrequency;
$this->clock = $clock;
}
/**
* The total award amount is calculated using the amount earned for this
* period and any pending amounts. The total award amount must exceed one
* penny for the award to be granted, otherwise it is recorded as pending.
*/
public function awardEarnedInterest(Account $account): void
{
$userId = (string) $account->userId();
$amount = $this->amountEarnedForPeriod($account);
$award = ($this->pendingAwards[$userId] ?? 0) + $amount;
if ($award > 0 && $award < 1) {
$this->pendingAwards[$userId] = $award;
return;
}
$account->recordTransaction(
new Transaction((int) $award, $this->clock->now())
);
}
private function amountEarnedForPeriod(Account $account): float
{
$dailyInterestAmount = $this->dailyInterestAmount(
$account->balance(),
$account->interestRate()
);
return $dailyInterestAmount * $this->awardFrequency;
}
private function dailyInterestAmount(int $balance, int $interestRate): float
{
$eligibleBalance = max(0, $balance);
$dailyInterestPercentage = $interestRate / 10_000 / 365;
return $eligibleBalance * $dailyInterestPercentage;
}
}