Add depreciation with half-year convention. Fixed #1237 (#6128)

* Add half-year convention in depreciation for Models/Depreciable.php

* Add a setting for the depreciation method

* Integrate half-year convention inside working output

* fix: add more checks at Depreciable.php

* depreciation value rounding

* Codestyle fix
This commit is contained in:
Dmitriy Minaev 2018-08-28 22:32:46 +03:00 committed by snipe
parent 678ba228cb
commit bc8fa31eb2
4 changed files with 132 additions and 0 deletions

View file

@ -351,6 +351,8 @@ class SettingsController extends Controller
$setting->thumbnail_max_h = $request->input('thumbnail_max_h');
$setting->privacy_policy_link = $request->input('privacy_policy_link');
$setting->depreciation_method = $request->input('depreciation_method');
if (Input::get('per_page')!='') {
$setting->per_page = $request->input('per_page');
} else {

View file

@ -49,7 +49,29 @@ class Depreciable extends SnipeModel
if ($this->get_depreciation()->months <= 0) {
return $this->purchase_cost;
}
$depreciation = 0;
$setting = Setting::first();
switch($setting->depreciation_method) {
case 'half_1':
$depreciation = $this->getHalfYearDepreciatedValue(true);
break;
case 'half_2':
$depreciation = $this->getHalfYearDepreciatedValue(false);
break;
default:
$depreciation = $this->getLinearDepreciatedValue();
}
return $depreciation;
}
/**
* @return float|int
*/
public function getLinearDepreciatedValue()
{
// fraction of value left
$months_remaining = $this->time_until_depreciated()->m + 12*$this->time_until_depreciated()->y; //UGlY
$current_value = round(($months_remaining/ $this->get_depreciation()->months) * $this->purchase_cost, 2);
@ -60,6 +82,62 @@ class Depreciable extends SnipeModel
return $current_value;
}
/**
* @param onlyHalfFirstYear Boolean always applied only second half of the first year
* @return float|int
*/
public function getHalfYearDepreciatedValue($onlyHalfFirstYear = false)
{
// @link http://www.php.net/manual/en/class.dateinterval.php
$current_date = $this->getDateTime();
$purchase_date = date_create($this->purchase_date);
$currentYear = $this->get_fiscal_year( $current_date );
$purchaseYear = $this->get_fiscal_year( $purchase_date );
$yearsPast = $currentYear - $purchaseYear;
$deprecationYears = ceil($this->get_depreciation()->months / 12);
if( $onlyHalfFirstYear ) {
$yearsPast -= 0.5;
}
else if( !$this->is_first_half_of_year($purchase_date) ) {
$yearsPast -= 0.5;
}
if( !$this->is_first_half_of_year($current_date) ) {
$yearsPast += 0.5;
}
if($yearsPast >= $deprecationYears) {
$yearsPast = $deprecationYears;
}
else if($yearsPast < 0) {
$yearsPast = 0;
}
return round($yearsPast / $deprecationYears * $this->purchase_cost, 2);
}
/**
* @param \DateTime $date
* @return int
*/
protected function get_fiscal_year($date) {
$year = intval($date->format('Y'));
// also, maybe it'll have to set fiscal year date
if($date->format('nj') === '1231') {
return $year;
}
else {
return $year - 1;
}
}
/**
* @param \DateTime $date
* @return bool
*/
protected function is_first_half_of_year($date) {
$date0m0d = intval($date->format('md'));
return ($date0m0d < 601) || ($date0m0d >= 1231);
}
public function time_until_depreciated()
{
// @link http://www.php.net/manual/en/class.datetime.php
@ -81,4 +159,10 @@ class Depreciable extends SnipeModel
date_add($date, date_interval_create_from_date_string($this->get_depreciation()->months . ' months'));
return $date; //date_format($date, 'Y-m-d'); //don't bake-in format, for internationalization
}
// it's necessary for unit tests
protected function getDateTime($time = null)
{
return new \DateTime($time);
}
}

View file

@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddDepreciationOptionToSettings extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->char('depreciation_method', 10)->nullable()->default('default');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('depreciation_method');
});
}
}

View file

@ -281,6 +281,20 @@
{{ Form::checkbox('show_in_model_list[]', 'model_number', Input::old('show_in_model_list', $snipeSettings->modellistCheckedValue('model_number')),array('class' => 'minimal')) }} {{ trans('general.model_no') }}<br>
</div>
</div>
<!-- Depreciation method -->
<div class="form-group {{ $errors->has('depreciation_method') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('depreciation_method', trans('Depreciation method')) }}
</div>
<div class="col-md-9">
{{ Form::select('depreciation_method', array(
'default' => 'Linear (default)',
'half_1' => 'Half-year convention, always applied',
'half_2' => 'Half-year convention, applied with condition',
), Input::old('username_format', $setting->depreciation_method)) }}
</div>
</div>
<!-- /.form-group -->
<!-- Privacy Policy Footer-->