Passed
Push — master ( 07d32f...817bfa )
by Kauri
03:00
created

PaymentPeriods   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 131
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 1
dl 0
loc 131
ccs 38
cts 38
cp 1
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A add() 0 9 2
A getRatePerPeriod() 0 21 4
B getNumberOfPeriods() 0 22 4
A getPeriods() 0 4 1
A getNoOfPeriods() 0 4 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Kauri\Loan;
6
7
/**
8
 * Class PaymentPeriods
9
 * @package Kauri\Loan
10
 */
11
class PaymentPeriods implements PaymentPeriodsInterface
12
{
13
    /**
14
     * Exact payment with exact interest
15
     */
16
    const CALCULATION_TYPE_EXACT = 1;
17
    /**
18
     * Annuity payment with exact interest
19
     */
20
    const CALCULATION_TYPE_EXACT_INTEREST = 2;
21
    /**
22
     * Annuity payment with annuity interest
23
     */
24
    const CALCULATION_TYPE_ANNUITY = 3;
25
26
    /**
27
     * @var array
28
     */
29
    private $periods = array();
30
    /**
31
     * @var int
32
     */
33
    private $totalLength = 0;
34
    /**
35
     * @var int
36
     */
37
    private $averagePeriod;
38
    /**
39
     * @var int
40
     */
41
    private $averageTotalPeriod;
42
43
    /**
44
     * PaymentPeriods constructor.
45
     * @param int $averagePeriod
46
     */
47 7
    public function __construct(int $averagePeriod)
48
    {
49 7
        $this->averagePeriod = $averagePeriod;
50 7
    }
51
52
    /**
53
     * @param PeriodInterface $period
54
     * @param int|null $sequenceNo
55
     */
56 5
    public function add(PeriodInterface $period, int $sequenceNo = null): void
57
    {
58 5
        if (is_null($sequenceNo)) {
59 2
            $sequenceNo = $this->getNoOfPeriods() + 1;
60
        }
61 5
        $this->periods[$sequenceNo] = $period;
62 5
        $this->totalLength = $this->totalLength + $period->getLength();
63 5
        $this->averageTotalPeriod = count($this->periods) * $this->averagePeriod;
64 5
    }
65
66
    /**
67
     * @param PeriodInterface $period
68
     * @param float $yearlyInterestRate
69
     * @param int $calculationType
70
     * @return float
71
     * @throws \Exception
72
     */
73 3
    public function getRatePerPeriod(
74
        PeriodInterface $period,
75
        float $yearlyInterestRate,
76
        int $calculationType = self::CALCULATION_TYPE_ANNUITY
77
    ): float {
78
        switch ($calculationType) {
79 3
            case self::CALCULATION_TYPE_EXACT:
80 3
            case self::CALCULATION_TYPE_EXACT_INTEREST:
81 2
                $currentPeriod = $period->getLength();
82 2
                break;
83 3
            case self::CALCULATION_TYPE_ANNUITY:
84 2
                $currentPeriod = $this->averagePeriod;
85 2
                break;
86
            default:
87 1
                throw new \Exception('Calculation type not implemented');
88
        }
89
90 2
        $ratePerPeriod = $yearlyInterestRate / 360 * $currentPeriod;
91
92 2
        return $ratePerPeriod;
93
    }
94
95
    /**
96
     * @param PeriodInterface $period
97
     * @param int $calculationType
98
     * @return float|int
99
     * @throws \Exception
100
     */
101 6
    public function getNumberOfPeriods(
102
        PeriodInterface $period,
103
        int $calculationType = self::CALCULATION_TYPE_ANNUITY
104
    ): float {
105
        switch ($calculationType) {
106 6
            case self::CALCULATION_TYPE_EXACT:
107 5
                $currentPeriod = $period->getLength();
108 5
                $totalPeriods = $this->totalLength;
109 5
                break;
110 6
            case self::CALCULATION_TYPE_EXACT_INTEREST:
111 6
            case self::CALCULATION_TYPE_ANNUITY:
112 5
                $currentPeriod = $this->averagePeriod;
113 5
                $totalPeriods = $this->averageTotalPeriod;
114 5
                break;
115
            default:
116 1
                throw new \Exception('Calculation type not implemented');
117
        }
118
119 5
        $numberOfPeriods = $totalPeriods / $currentPeriod;
120
121 5
        return $numberOfPeriods;
122
    }
123
124
    /**
125
     * @return array
126
     */
127 5
    public function getPeriods(): array
128
    {
129 5
        return $this->periods;
130
    }
131
132
    /**
133
     * @return int
134
     */
135 2
    public function getNoOfPeriods(): int
136
    {
137 2
        return count($this->periods);
138
    }
139
140
141
}
142