PaymentsCalculator::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 6
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Kauri\Loan;
6
7
class PaymentsCalculator implements PaymentsCalculatorInterface
8
{
9
    /**
10
     * @var PaymentAmountCalculatorInterface
11
     */
12
    private $paymentAmountCalculator;
13
    /**
14
     * @var InterestAmountCalculatorInterface
15
     */
16
    private $interestAmountCalculator;
17
18
    /**
19
     * PaymentsCalculator constructor.
20
     * @param PaymentAmountCalculatorInterface $paymentAmountCalculator
21
     * @param InterestAmountCalculatorInterface $interestAmountCalculator
22
     */
23 6
    public function __construct(
24
        PaymentAmountCalculatorInterface $paymentAmountCalculator,
25
        InterestAmountCalculatorInterface $interestAmountCalculator
26
    ) {
27 6
        $this->paymentAmountCalculator = $paymentAmountCalculator;
28 6
        $this->interestAmountCalculator = $interestAmountCalculator;
29 6
    }
30
31
    /**
32
     * @param PaymentPeriodsInterface $paymentPeriods
33
     * @param float $amountOfPrincipal
34
     * @param float $yearlyInterestRate
35
     * @param int $calculationMode
36
     * @param float $futureValue
37
     * @return array
38
     */
39 6
    public function calculatePayments(
40
        PaymentPeriodsInterface $paymentPeriods,
41
        float $amountOfPrincipal,
42
        float $yearlyInterestRate,
43
        int $calculationMode,
44
        float $futureValue
45
    ): array {
46 6
        $payments = array();
47
48 6
        $periodLengths = $this->getPeriodLengths($paymentPeriods, $calculationMode);
49 6
        $paymentAmounts = $this->paymentAmountCalculator->getPaymentAmounts($periodLengths, $amountOfPrincipal,
50 6
            $yearlyInterestRate, $futureValue);
51
52 6
        $principalLeft = $amountOfPrincipal;
53
54 6
        foreach ($paymentPeriods->getPeriods() as $period) {
55
            /**
56
             * Get payment amount
57
             */
58 6
            $paymentAmount = round($paymentAmounts[$period->getSequenceNo()], 2);
59
60
            /**
61
             * Get interest rate for period
62
             */
63 6
            $ratePerPeriod = $this->interestAmountCalculator->getPeriodInterestRate($yearlyInterestRate,
64 6
                $period->getLength($calculationMode));
65
66
            /**
67
             * Calculate interest part
68
             */
69 6
            $interest = round($this->interestAmountCalculator->getInterestAmount($principalLeft, $ratePerPeriod), 2);
70
71
            /**
72
             * Calculate principal part
73
             */
74 6
            if ($period->getSequenceNo() < $paymentPeriods->getNoOfPeriods()) {
75 6
                $principal = $paymentAmount - $interest;
76
            } else {
77 6
                $principal = $principalLeft - $futureValue;
78
            }
79
80
            /**
81
             * Calculate balance left
82
             */
83 6
            $principalLeft = $principalLeft - $principal;
84
85
            /**
86
             * Compose payment data
87
             */
88
            $paymentData = array(
89 6
                'sequence_no' => $period->getSequenceNo(),
90 6
                'payment' => $interest + $principal,
91 6
                'principal' => $principal,
92 6
                'interest' => $interest,
93 6
                'principal_left' => $principalLeft,
94 6
                'period' => $period
95
            );
96
97 6
            $payments[$period->getSequenceNo()] = $paymentData;
98
        }
99
100 6
        return $payments;
101
    }
102
103
    /**
104
     * @param PaymentPeriodsInterface $paymentPeriods
105
     * @param int $lengthMode
106
     * @return array
107
     */
108 6
    private function getPeriodLengths(PaymentPeriodsInterface $paymentPeriods, int $lengthMode): array
109
    {
110 6
        $lengths = array();
111
112
        /** @var PeriodInterface $period */
113 6
        foreach ($paymentPeriods->getPeriods() as $period) {
114 6
            $lengths[$period->getSequenceNo()] = $period->getLength($lengthMode);
115
        }
116
117 6
        return $lengths;
118
    }
119
}
120