Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.

Differences Between: [Versions 400 and 401] [Versions 400 and 402] [Versions 400 and 403]

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