Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
<?php
2
 
3
namespace PhpOffice\PhpSpreadsheet\Calculation\Financial;
4
 
5
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel;
6
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
7
use PhpOffice\PhpSpreadsheet\Calculation\Financial\Constants as FinancialConstants;
8
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
9
 
10
class Amortization
11
{
12
    /**
13
     * AMORDEGRC.
14
     *
15
     * Returns the depreciation for each accounting period.
16
     * This function is provided for the French accounting system. If an asset is purchased in
17
     * the middle of the accounting period, the prorated depreciation is taken into account.
18
     * The function is similar to AMORLINC, except that a depreciation coefficient is applied in
19
     * the calculation depending on the life of the assets.
20
     * This function will return the depreciation until the last period of the life of the assets
21
     * or until the cumulated value of depreciation is greater than the cost of the assets minus
22
     * the salvage value.
23
     *
24
     * Excel Function:
25
     *        AMORDEGRC(cost,purchased,firstPeriod,salvage,period,rate[,basis])
26
     *
27
     * @param mixed $cost The float cost of the asset
28
     * @param mixed $purchased Date of the purchase of the asset
29
     * @param mixed $firstPeriod Date of the end of the first period
30
     * @param mixed $salvage The salvage value at the end of the life of the asset
31
     * @param mixed $period the period (float)
32
     * @param mixed $rate rate of depreciation (float)
33
     * @param mixed $basis The type of day count to use (int).
34
     *                         0 or omitted    US (NASD) 30/360
35
     *                         1               Actual/actual
36
     *                         2               Actual/360
37
     *                         3               Actual/365
38
     *                         4               European 30/360
39
     *
40
     * @return float|string (string containing the error type if there is an error)
41
     */
42
    public static function AMORDEGRC(
43
        mixed $cost,
44
        mixed $purchased,
45
        mixed $firstPeriod,
46
        mixed $salvage,
47
        mixed $period,
48
        mixed $rate,
49
        mixed $basis = FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
50
    ): string|float {
51
        $cost = Functions::flattenSingleValue($cost);
52
        $purchased = Functions::flattenSingleValue($purchased);
53
        $firstPeriod = Functions::flattenSingleValue($firstPeriod);
54
        $salvage = Functions::flattenSingleValue($salvage);
55
        $period = Functions::flattenSingleValue($period);
56
        $rate = Functions::flattenSingleValue($rate);
57
        $basis = ($basis === null)
58
            ? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
59
            : Functions::flattenSingleValue($basis);
60
 
61
        try {
62
            $cost = FinancialValidations::validateFloat($cost);
63
            $purchased = FinancialValidations::validateDate($purchased);
64
            $firstPeriod = FinancialValidations::validateDate($firstPeriod);
65
            $salvage = FinancialValidations::validateFloat($salvage);
66
            $period = FinancialValidations::validateInt($period);
67
            $rate = FinancialValidations::validateFloat($rate);
68
            $basis = FinancialValidations::validateBasis($basis);
69
        } catch (Exception $e) {
70
            return $e->getMessage();
71
        }
72
 
73
        $yearFracx = DateTimeExcel\YearFrac::fraction($purchased, $firstPeriod, $basis);
74
        if (is_string($yearFracx)) {
75
            return $yearFracx;
76
        }
77
        /** @var float $yearFrac */
78
        $yearFrac = $yearFracx;
79
 
80
        $amortiseCoeff = self::getAmortizationCoefficient($rate);
81
 
82
        $rate *= $amortiseCoeff;
83
        $rate = (float) (string) $rate; // ugly way to avoid rounding problem
84
        $fNRate = round($yearFrac * $rate * $cost, 0);
85
        $cost -= $fNRate;
86
        $fRest = $cost - $salvage;
87
 
88
        for ($n = 0; $n < $period; ++$n) {
89
            $fNRate = round($rate * $cost, 0);
90
            $fRest -= $fNRate;
91
 
92
            if ($fRest < 0.0) {
93
                return match ($period - $n) {
94
                    1 => round($cost * 0.5, 0),
95
                    default => 0.0,
96
                };
97
            }
98
            $cost -= $fNRate;
99
        }
100
 
101
        return $fNRate;
102
    }
103
 
104
    /**
105
     * AMORLINC.
106
     *
107
     * Returns the depreciation for each accounting period.
108
     * This function is provided for the French accounting system. If an asset is purchased in
109
     * the middle of the accounting period, the prorated depreciation is taken into account.
110
     *
111
     * Excel Function:
112
     *        AMORLINC(cost,purchased,firstPeriod,salvage,period,rate[,basis])
113
     *
114
     * @param mixed $cost The cost of the asset as a float
115
     * @param mixed $purchased Date of the purchase of the asset
116
     * @param mixed $firstPeriod Date of the end of the first period
117
     * @param mixed $salvage The salvage value at the end of the life of the asset
118
     * @param mixed $period The period as a float
119
     * @param mixed $rate Rate of depreciation as  float
120
     * @param mixed $basis Integer indicating the type of day count to use.
121
     *                             0 or omitted    US (NASD) 30/360
122
     *                             1               Actual/actual
123
     *                             2               Actual/360
124
     *                             3               Actual/365
125
     *                             4               European 30/360
126
     *
127
     * @return float|string (string containing the error type if there is an error)
128
     */
129
    public static function AMORLINC(
130
        mixed $cost,
131
        mixed $purchased,
132
        mixed $firstPeriod,
133
        mixed $salvage,
134
        mixed $period,
135
        mixed $rate,
136
        mixed $basis = FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
137
    ): string|float {
138
        $cost = Functions::flattenSingleValue($cost);
139
        $purchased = Functions::flattenSingleValue($purchased);
140
        $firstPeriod = Functions::flattenSingleValue($firstPeriod);
141
        $salvage = Functions::flattenSingleValue($salvage);
142
        $period = Functions::flattenSingleValue($period);
143
        $rate = Functions::flattenSingleValue($rate);
144
        $basis = ($basis === null)
145
            ? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
146
            : Functions::flattenSingleValue($basis);
147
 
148
        try {
149
            $cost = FinancialValidations::validateFloat($cost);
150
            $purchased = FinancialValidations::validateDate($purchased);
151
            $firstPeriod = FinancialValidations::validateDate($firstPeriod);
152
            $salvage = FinancialValidations::validateFloat($salvage);
153
            $period = FinancialValidations::validateFloat($period);
154
            $rate = FinancialValidations::validateFloat($rate);
155
            $basis = FinancialValidations::validateBasis($basis);
156
        } catch (Exception $e) {
157
            return $e->getMessage();
158
        }
159
 
160
        $fOneRate = $cost * $rate;
161
        $fCostDelta = $cost - $salvage;
162
        //    Note, quirky variation for leap years on the YEARFRAC for this function
163
        $purchasedYear = DateTimeExcel\DateParts::year($purchased);
164
        $yearFracx = DateTimeExcel\YearFrac::fraction($purchased, $firstPeriod, $basis);
165
        if (is_string($yearFracx)) {
166
            return $yearFracx;
167
        }
168
        /** @var float $yearFrac */
169
        $yearFrac = $yearFracx;
170
 
171
        if (
172
            $basis == FinancialConstants::BASIS_DAYS_PER_YEAR_ACTUAL
173
            && $yearFrac < 1
174
            && DateTimeExcel\Helpers::isLeapYear(Functions::scalar($purchasedYear))
175
        ) {
176
            $yearFrac *= 365 / 366;
177
        }
178
 
179
        $f0Rate = $yearFrac * $rate * $cost;
180
        $nNumOfFullPeriods = (int) (($cost - $salvage - $f0Rate) / $fOneRate);
181
 
182
        if ($period == 0) {
183
            return $f0Rate;
184
        } elseif ($period <= $nNumOfFullPeriods) {
185
            return $fOneRate;
186
        } elseif ($period == ($nNumOfFullPeriods + 1)) {
187
            return $fCostDelta - $fOneRate * $nNumOfFullPeriods - $f0Rate;
188
        }
189
 
190
        return 0.0;
191
    }
192
 
193
    private static function getAmortizationCoefficient(float $rate): float
194
    {
195
        //    The depreciation coefficients are:
196
        //    Life of assets (1/rate)        Depreciation coefficient
197
        //    Less than 3 years            1
198
        //    Between 3 and 4 years        1.5
199
        //    Between 5 and 6 years        2
200
        //    More than 6 years            2.5
201
        $fUsePer = 1.0 / $rate;
202
 
203
        if ($fUsePer < 3.0) {
204
            return 1.0;
205
        } elseif ($fUsePer < 4.0) {
206
            return 1.5;
207
        } elseif ($fUsePer <= 6.0) {
208
            return 2.0;
209
        }
210
 
211
        return 2.5;
212
    }
213
}