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\Exception;
6
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
7
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
8
 
9
class Depreciation
10
{
11
    private static float $zeroPointZero = 0.0;
12
 
13
    /**
14
     * DB.
15
     *
16
     * Returns the depreciation of an asset for a specified period using the
17
     * fixed-declining balance method.
18
     * This form of depreciation is used if you want to get a higher depreciation value
19
     * at the beginning of the depreciation (as opposed to linear depreciation). The
20
     * depreciation value is reduced with every depreciation period by the depreciation
21
     * already deducted from the initial cost.
22
     *
23
     * Excel Function:
24
     *        DB(cost,salvage,life,period[,month])
25
     *
26
     * @param mixed $cost Initial cost of the asset
27
     * @param mixed $salvage Value at the end of the depreciation.
28
     *                             (Sometimes called the salvage value of the asset)
29
     * @param mixed $life Number of periods over which the asset is depreciated.
30
     *                           (Sometimes called the useful life of the asset)
31
     * @param mixed $period The period for which you want to calculate the
32
     *                          depreciation. Period must use the same units as life.
33
     * @param mixed $month Number of months in the first year. If month is omitted,
34
     *                         it defaults to 12.
35
     */
36
    public static function DB(mixed $cost, mixed $salvage, mixed $life, mixed $period, mixed $month = 12): string|float|int
37
    {
38
        $cost = Functions::flattenSingleValue($cost);
39
        $salvage = Functions::flattenSingleValue($salvage);
40
        $life = Functions::flattenSingleValue($life);
41
        $period = Functions::flattenSingleValue($period);
42
        $month = Functions::flattenSingleValue($month);
43
 
44
        try {
45
            $cost = self::validateCost($cost);
46
            $salvage = self::validateSalvage($salvage);
47
            $life = self::validateLife($life);
48
            $period = self::validatePeriod($period);
49
            $month = self::validateMonth($month);
50
        } catch (Exception $e) {
51
            return $e->getMessage();
52
        }
53
 
54
        if ($cost === self::$zeroPointZero) {
55
            return 0.0;
56
        }
57
 
58
        //    Set Fixed Depreciation Rate
59
        $fixedDepreciationRate = 1 - ($salvage / $cost) ** (1 / $life);
60
        $fixedDepreciationRate = round($fixedDepreciationRate, 3);
61
 
62
        //    Loop through each period calculating the depreciation
63
        // TODO Handle period value between 0 and 1 (e.g. 0.5)
64
        $previousDepreciation = 0;
65
        $depreciation = 0;
66
        for ($per = 1; $per <= $period; ++$per) {
67
            if ($per == 1) {
68
                $depreciation = $cost * $fixedDepreciationRate * $month / 12;
69
            } elseif ($per == ($life + 1)) {
70
                $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate * (12 - $month) / 12;
71
            } else {
72
                $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate;
73
            }
74
            $previousDepreciation += $depreciation;
75
        }
76
 
77
        return $depreciation;
78
    }
79
 
80
    /**
81
     * DDB.
82
     *
83
     * Returns the depreciation of an asset for a specified period using the
84
     * double-declining balance method or some other method you specify.
85
     *
86
     * Excel Function:
87
     *        DDB(cost,salvage,life,period[,factor])
88
     *
89
     * @param mixed $cost Initial cost of the asset
90
     * @param mixed $salvage Value at the end of the depreciation.
91
     *                                (Sometimes called the salvage value of the asset)
92
     * @param mixed $life Number of periods over which the asset is depreciated.
93
     *                                (Sometimes called the useful life of the asset)
94
     * @param mixed $period The period for which you want to calculate the
95
     *                                depreciation. Period must use the same units as life.
96
     * @param mixed $factor The rate at which the balance declines.
97
     *                                If factor is omitted, it is assumed to be 2 (the
98
     *                                double-declining balance method).
99
     */
100
    public static function DDB(mixed $cost, mixed $salvage, mixed $life, mixed $period, mixed $factor = 2.0): float|string
101
    {
102
        $cost = Functions::flattenSingleValue($cost);
103
        $salvage = Functions::flattenSingleValue($salvage);
104
        $life = Functions::flattenSingleValue($life);
105
        $period = Functions::flattenSingleValue($period);
106
        $factor = Functions::flattenSingleValue($factor);
107
 
108
        try {
109
            $cost = self::validateCost($cost);
110
            $salvage = self::validateSalvage($salvage);
111
            $life = self::validateLife($life);
112
            $period = self::validatePeriod($period);
113
            $factor = self::validateFactor($factor);
114
        } catch (Exception $e) {
115
            return $e->getMessage();
116
        }
117
 
118
        if ($period > $life) {
119
            return ExcelError::NAN();
120
        }
121
 
122
        // Loop through each period calculating the depreciation
123
        // TODO Handling for fractional $period values
124
        $previousDepreciation = 0;
125
        $depreciation = 0;
126
        for ($per = 1; $per <= $period; ++$per) {
127
            $depreciation = min(
128
                ($cost - $previousDepreciation) * ($factor / $life),
129
                ($cost - $salvage - $previousDepreciation)
130
            );
131
            $previousDepreciation += $depreciation;
132
        }
133
 
134
        return $depreciation;
135
    }
136
 
137
    /**
138
     * SLN.
139
     *
140
     * Returns the straight-line depreciation of an asset for one period
141
     *
142
     * @param mixed $cost Initial cost of the asset
143
     * @param mixed $salvage Value at the end of the depreciation
144
     * @param mixed $life Number of periods over which the asset is depreciated
145
     *
146
     * @return float|string Result, or a string containing an error
147
     */
148
    public static function SLN(mixed $cost, mixed $salvage, mixed $life): string|float
149
    {
150
        $cost = Functions::flattenSingleValue($cost);
151
        $salvage = Functions::flattenSingleValue($salvage);
152
        $life = Functions::flattenSingleValue($life);
153
 
154
        try {
155
            $cost = self::validateCost($cost, true);
156
            $salvage = self::validateSalvage($salvage, true);
157
            $life = self::validateLife($life, true);
158
        } catch (Exception $e) {
159
            return $e->getMessage();
160
        }
161
 
162
        if ($life === self::$zeroPointZero) {
163
            return ExcelError::DIV0();
164
        }
165
 
166
        return ($cost - $salvage) / $life;
167
    }
168
 
169
    /**
170
     * SYD.
171
     *
172
     * Returns the sum-of-years' digits depreciation of an asset for a specified period.
173
     *
174
     * @param mixed $cost Initial cost of the asset
175
     * @param mixed $salvage Value at the end of the depreciation
176
     * @param mixed $life Number of periods over which the asset is depreciated
177
     * @param mixed $period Period
178
     *
179
     * @return float|string Result, or a string containing an error
180
     */
181
    public static function SYD(mixed $cost, mixed $salvage, mixed $life, mixed $period): string|float
182
    {
183
        $cost = Functions::flattenSingleValue($cost);
184
        $salvage = Functions::flattenSingleValue($salvage);
185
        $life = Functions::flattenSingleValue($life);
186
        $period = Functions::flattenSingleValue($period);
187
 
188
        try {
189
            $cost = self::validateCost($cost, true);
190
            $salvage = self::validateSalvage($salvage);
191
            $life = self::validateLife($life);
192
            $period = self::validatePeriod($period);
193
        } catch (Exception $e) {
194
            return $e->getMessage();
195
        }
196
 
197
        if ($period > $life) {
198
            return ExcelError::NAN();
199
        }
200
 
201
        $syd = (($cost - $salvage) * ($life - $period + 1) * 2) / ($life * ($life + 1));
202
 
203
        return $syd;
204
    }
205
 
206
    private static function validateCost(mixed $cost, bool $negativeValueAllowed = false): float
207
    {
208
        $cost = FinancialValidations::validateFloat($cost);
209
        if ($cost < 0.0 && $negativeValueAllowed === false) {
210
            throw new Exception(ExcelError::NAN());
211
        }
212
 
213
        return $cost;
214
    }
215
 
216
    private static function validateSalvage(mixed $salvage, bool $negativeValueAllowed = false): float
217
    {
218
        $salvage = FinancialValidations::validateFloat($salvage);
219
        if ($salvage < 0.0 && $negativeValueAllowed === false) {
220
            throw new Exception(ExcelError::NAN());
221
        }
222
 
223
        return $salvage;
224
    }
225
 
226
    private static function validateLife(mixed $life, bool $negativeValueAllowed = false): float
227
    {
228
        $life = FinancialValidations::validateFloat($life);
229
        if ($life < 0.0 && $negativeValueAllowed === false) {
230
            throw new Exception(ExcelError::NAN());
231
        }
232
 
233
        return $life;
234
    }
235
 
236
    private static function validatePeriod(mixed $period, bool $negativeValueAllowed = false): float
237
    {
238
        $period = FinancialValidations::validateFloat($period);
239
        if ($period <= 0.0 && $negativeValueAllowed === false) {
240
            throw new Exception(ExcelError::NAN());
241
        }
242
 
243
        return $period;
244
    }
245
 
246
    private static function validateMonth(mixed $month): int
247
    {
248
        $month = FinancialValidations::validateInt($month);
249
        if ($month < 1) {
250
            throw new Exception(ExcelError::NAN());
251
        }
252
 
253
        return $month;
254
    }
255
 
256
    private static function validateFactor(mixed $factor): float
257
    {
258
        $factor = FinancialValidations::validateFloat($factor);
259
        if ($factor <= 0.0) {
260
            throw new Exception(ExcelError::NAN());
261
        }
262
 
263
        return $factor;
264
    }
265
}