1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic; |
4
|
|
|
|
5
|
|
|
use PhpOffice\PhpSpreadsheet\Calculation\Exception; |
6
|
|
|
use PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\CashFlowValidations; |
7
|
|
|
use PhpOffice\PhpSpreadsheet\Calculation\Financial\Constants as FinancialConstants; |
8
|
|
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions; |
9
|
|
|
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError; |
10
|
|
|
|
11
|
|
|
class Payments |
12
|
|
|
{ |
13
|
|
|
/** |
14
|
|
|
* PMT. |
15
|
|
|
* |
16
|
|
|
* Returns the constant payment (annuity) for a cash flow with a constant interest rate. |
17
|
|
|
* |
18
|
|
|
* @param mixed $interestRate Interest rate per period |
19
|
|
|
* @param mixed $numberOfPeriods Number of periods |
20
|
|
|
* @param mixed $presentValue Present Value |
21
|
|
|
* @param mixed $futureValue Future Value |
22
|
|
|
* @param mixed $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period |
23
|
|
|
* |
24
|
|
|
* @return float|string Result, or a string containing an error |
25
|
|
|
*/ |
26
|
56 |
|
public static function annuity( |
27
|
|
|
mixed $interestRate, |
28
|
|
|
mixed $numberOfPeriods, |
29
|
|
|
mixed $presentValue, |
30
|
|
|
mixed $futureValue = 0.0, |
31
|
|
|
mixed $type = FinancialConstants::PAYMENT_END_OF_PERIOD |
32
|
|
|
): string|float { |
33
|
56 |
|
$interestRate = Functions::flattenSingleValue($interestRate); |
34
|
56 |
|
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods); |
35
|
56 |
|
$presentValue = Functions::flattenSingleValue($presentValue); |
36
|
56 |
|
$futureValue = Functions::flattenSingleValue($futureValue) ?? 0.0; |
37
|
56 |
|
$type = Functions::flattenSingleValue($type) ?? FinancialConstants::PAYMENT_END_OF_PERIOD; |
38
|
|
|
|
39
|
|
|
try { |
40
|
56 |
|
$interestRate = CashFlowValidations::validateRate($interestRate); |
41
|
55 |
|
$numberOfPeriods = CashFlowValidations::validateInt($numberOfPeriods); |
42
|
54 |
|
$presentValue = CashFlowValidations::validatePresentValue($presentValue); |
43
|
53 |
|
$futureValue = CashFlowValidations::validateFutureValue($futureValue); |
44
|
52 |
|
$type = CashFlowValidations::validatePeriodType($type); |
45
|
6 |
|
} catch (Exception $e) { |
46
|
6 |
|
return $e->getMessage(); |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
// Calculate |
50
|
50 |
|
if ($interestRate != 0.0) { |
51
|
49 |
|
return (-$futureValue - $presentValue * (1 + $interestRate) ** $numberOfPeriods) |
52
|
49 |
|
/ (1 + $interestRate * $type) / (((1 + $interestRate) ** $numberOfPeriods - 1) / $interestRate); |
53
|
|
|
} |
54
|
|
|
|
55
|
1 |
|
return (-$presentValue - $futureValue) / $numberOfPeriods; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* PPMT. |
60
|
|
|
* |
61
|
|
|
* Returns the interest payment for a given period for an investment based on periodic, constant payments |
62
|
|
|
* and a constant interest rate. |
63
|
|
|
* |
64
|
|
|
* @param mixed $interestRate Interest rate per period |
65
|
|
|
* @param mixed $period Period for which we want to find the interest |
66
|
|
|
* @param mixed $numberOfPeriods Number of periods |
67
|
|
|
* @param mixed $presentValue Present Value |
68
|
|
|
* @param mixed $futureValue Future Value |
69
|
|
|
* @param mixed $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period |
70
|
|
|
* |
71
|
|
|
* @return float|string Result, or a string containing an error |
72
|
|
|
*/ |
73
|
30 |
|
public static function interestPayment( |
74
|
|
|
mixed $interestRate, |
75
|
|
|
mixed $period, |
76
|
|
|
mixed $numberOfPeriods, |
77
|
|
|
mixed $presentValue, |
78
|
|
|
mixed $futureValue = 0, |
79
|
|
|
mixed $type = FinancialConstants::PAYMENT_END_OF_PERIOD |
80
|
|
|
): string|float { |
81
|
30 |
|
$interestRate = Functions::flattenSingleValue($interestRate); |
82
|
30 |
|
$period = Functions::flattenSingleValue($period); |
83
|
30 |
|
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods); |
84
|
30 |
|
$presentValue = Functions::flattenSingleValue($presentValue); |
85
|
30 |
|
$futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue); |
86
|
30 |
|
$type = Functions::flattenSingleValue($type) ?? FinancialConstants::PAYMENT_END_OF_PERIOD; |
87
|
|
|
|
88
|
|
|
try { |
89
|
30 |
|
$interestRate = CashFlowValidations::validateRate($interestRate); |
90
|
29 |
|
$period = CashFlowValidations::validateInt($period); |
91
|
28 |
|
$numberOfPeriods = CashFlowValidations::validateInt($numberOfPeriods); |
92
|
27 |
|
$presentValue = CashFlowValidations::validatePresentValue($presentValue); |
93
|
26 |
|
$futureValue = CashFlowValidations::validateFutureValue($futureValue); |
94
|
25 |
|
$type = CashFlowValidations::validatePeriodType($type); |
95
|
7 |
|
} catch (Exception $e) { |
96
|
7 |
|
return $e->getMessage(); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
// Validate parameters |
100
|
23 |
|
if ($period <= 0 || $period > $numberOfPeriods) { |
101
|
3 |
|
return ExcelError::NAN(); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
// Calculate |
105
|
20 |
|
$interestAndPrincipal = new InterestAndPrincipal( |
106
|
20 |
|
$interestRate, |
107
|
20 |
|
$period, |
108
|
20 |
|
$numberOfPeriods, |
109
|
20 |
|
$presentValue, |
110
|
20 |
|
$futureValue, |
111
|
20 |
|
$type |
112
|
20 |
|
); |
113
|
|
|
|
114
|
20 |
|
return $interestAndPrincipal->principal(); |
115
|
|
|
} |
116
|
|
|
} |
117
|
|
|
|