AnnuityPaymentScheduleCalculator   A
last analyzed

Complexity

Total Complexity 6

Size/Duplication

Total Lines 81
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 6
lcom 1
cbo 2
dl 0
loc 81
rs 10
c 0
b 0
f 0
ccs 28
cts 28
cp 1

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
B calculateSchedule() 0 25 3
A calculateAnnuityPaymentAmount() 0 5 1
A calculateInterestPerPeriod() 0 8 1
1
<?php
2
/**
3
 * @author: Vova Lando <[email protected]>
4
 * @package: LoanPaymentsCalculator
5
 * @subpackage:
6
 * @created: 06/09/2017 13:30
7
 */
8
9
namespace cog\LoanPaymentsCalculator\PaymentSchedule;
10
11
12
use cog\LoanPaymentsCalculator\Payment\Payment;
13
use cog\LoanPaymentsCalculator\Period\Period;
14
15
16
class AnnuityPaymentScheduleCalculator implements PaymentScheduleCalculator
17
{
18
    /**
19
     * @var Period[]
20
     */
21
    private $schedulePeriods;
22
23
    /**
24
     * @var float
25
     */
26
    private $principalAmount;
27
28
    /**
29
     * @var float
30
     */
31
    private $dailyInterestRate;
32
33
    /**
34
     * AnnuityPaymentScheduleCalculator constructor.
35
     * @param Period[] $schedulePeriods
36
     * @param float    $principalAmount
37
     * @param float    $dailyInterestRate
38
     */
39 2
    public function __construct($schedulePeriods, $principalAmount, $dailyInterestRate)
40
    {
41 2
        $this->schedulePeriods = $schedulePeriods;
42 2
        $this->principalAmount = $principalAmount;
43 2
        $this->dailyInterestRate = $dailyInterestRate;
44 2
    }
45
46
    /**
47
     * @inheritdoc
48
     */
49 2
    public function calculateSchedule()
50
    {
51 2
        $payments = [];
52 2
        $numberOfPeriods = count($this->schedulePeriods);
53 2
        $periodInterestRate = $this->calculateInterestPerPeriod();
54 2
        $paymentAmount = $this->calculateAnnuityPaymentAmount($periodInterestRate);
55 2
        $totalPrincipalToPay = $this->principalAmount;
56
57 2
        for ($i=0; $i<$numberOfPeriods; $i++) {
58 2
            $payment = new Payment($this->schedulePeriods[$i]);
59
            // Payment interest
60 2
            $paymentInterest = $totalPrincipalToPay * $periodInterestRate;
61 2
            $payment->setInterest($paymentInterest);
62
            // Payment principal
63 2
            $paymentPrincipal = $i == $numberOfPeriods-1 ? $totalPrincipalToPay : $paymentAmount - $paymentInterest;
64 2
            $payment->setPrincipal($paymentPrincipal);
65
            // Payment totals
66 2
            $totalPrincipalToPay-=$paymentPrincipal;
67 2
            $payment->setPrincipalBalanceLeft($totalPrincipalToPay);
68
69 2
            $payments[] = $payment;
70
        }
71
72 2
        return $payments;
73
    }
74
75
    /**
76
     * @param float $interestPerPeriod
77
     * @return float
78
     */
79 2
    private function calculateAnnuityPaymentAmount($interestPerPeriod)
80
    {
81
        // Payment = InterestPerPeriod x TotalPrincipal / 1 - ( 1 + InterestPerPeriod)^(-numberOfPeriods)
82 2
        return (($interestPerPeriod) *  $this->principalAmount) / (1 - pow(1 + ($interestPerPeriod), -count($this->schedulePeriods)));
83
    }
84
85
    /**
86
     * @return float
87
     */
88 2
    private function calculateInterestPerPeriod()
89
    {
90 2
        $startDate = $this->schedulePeriods[0]->startDate;
91 2
        $endDate = $this->schedulePeriods[count($this->schedulePeriods)-1]->endDate;
92 2
        $daysDiff = $startDate->diff($endDate)->days;
93
94 2
        return $this->dailyInterestRate * $daysDiff/count($this->schedulePeriods);
95
    }
96
}