Passed
Branch kaurikk-patch-1 (5656e8)
by Kauri
02:51
created

PaymentsCalculator   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 111
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 33
dl 0
loc 111
ccs 31
cts 31
cp 1
rs 10
c 0
b 0
f 0
wmc 6

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A calculatePayments() 0 62 3
A getPeriodLengths() 0 10 2
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
    public function __construct(
24 6
        PaymentAmountCalculatorInterface $paymentAmountCalculator,
25
        InterestAmountCalculatorInterface $interestAmountCalculator
26
    ) {
27
        $this->paymentAmountCalculator = $paymentAmountCalculator;
28 6
        $this->interestAmountCalculator = $interestAmountCalculator;
29 6
    }
30 6
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
    public function calculatePayments(
40 6
        PaymentPeriodsInterface $paymentPeriods,
41
        float $amountOfPrincipal,
42
        float $yearlyInterestRate,
43
        int $calculationMode,
44
        float $futureValue
45
    ): array {
46
        $payments = array();
47 6
48
        $periodLengths = $this->getPeriodLengths($paymentPeriods, $calculationMode);
49 6
        $paymentAmounts = $this->paymentAmountCalculator->getPaymentAmounts($periodLengths, $amountOfPrincipal,
50 6
            $yearlyInterestRate, $futureValue);
51 6
52
        $principalLeft = $amountOfPrincipal;
53 6
54
        foreach ($paymentPeriods->getPeriods() as $period) {
55 6
            /**
56
             * Get payment amount
57
             */
58
            $paymentAmount = round($paymentAmounts[$period->getSequenceNo()], 2);
59 6
60
            /**
61
             * Get interest rate for period
62
             */
63
            $ratePerPeriod = $this->interestAmountCalculator->getPeriodInterestRate($yearlyInterestRate,
64 6
                $period->getLength($calculationMode));
65 6
66
            /**
67
             * Calculate interest part
68
             */
69
            $interest = round($this->interestAmountCalculator->getInterestAmount($principalLeft, $ratePerPeriod), 2);
70 6
71
            /**
72
             * Calculate principal part
73
             */
74
            if ($period->getSequenceNo() < $paymentPeriods->getNoOfPeriods()) {
75 6
                $principal = $paymentAmount - $interest;
76 6
            } else {
77
                $principal = $principalLeft - $futureValue;
78 6
            }
79
80
            /**
81
             * Calculate balance left
82
             */
83
            $principalLeft = $principalLeft - $principal;
84 6
85
            /**
86
             * Compose payment data
87
             */
88
            $paymentData = array(
89
                '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 6
            );
96
97
            $payments[$period->getSequenceNo()] = $paymentData;
98 6
        }
99
100
        return $payments;
101 6
    }
102
103
    /**
104
     * @param PaymentPeriodsInterface $paymentPeriods
105
     * @param int $lengthMode
106
     * @return array
107
     */
108
    private function getPeriodLengths(PaymentPeriodsInterface $paymentPeriods, int $lengthMode): array
109 6
    {
110
        $lengths = array();
111 6
112
        /** @var PeriodInterface $period */
113
        foreach ($paymentPeriods->getPeriods() as $period) {
114 6
            $lengths[$period->getSequenceNo()] = $period->getLength($lengthMode);
115 6
        }
116
117
        return $lengths;
118 6
    }
119
}
120