Skip to content

Commit

Permalink
feat(india): reduced rate of depreciation as per IT Act (#25648)
Browse files Browse the repository at this point in the history
* feat(india): reduced rate of depreciation as per IT Act

* refactor: check date difference instead of month difference

* feat: add test for regional feature
  • Loading branch information
nextchamp-saqib committed May 10, 2021
1 parent aa9e172 commit 9226cd3
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 30 deletions.
51 changes: 22 additions & 29 deletions erpnext/assets/doctype/asset/asset.py
Expand Up @@ -195,8 +195,7 @@ def make_depreciation_schedule(self):
# If depreciation is already completed (for double declining balance)
if skip_row: continue

depreciation_amount = self.get_depreciation_amount(value_after_depreciation,
d.total_number_of_depreciations, d)
depreciation_amount = get_depreciation_amount(self, value_after_depreciation, d)

if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1:
schedule_date = add_months(d.depreciation_start_date,
Expand All @@ -208,7 +207,7 @@ def make_depreciation_schedule(self):

# For first row
if has_pro_rata and n==0:
depreciation_amount, days, months = get_pro_rata_amt(d, depreciation_amount,
depreciation_amount, days, months = self.get_pro_rata_amt(d, depreciation_amount,
self.available_for_use_date, d.depreciation_start_date)

# For first depr schedule date will be the start date
Expand All @@ -220,7 +219,7 @@ def make_depreciation_schedule(self):
to_date = add_months(self.available_for_use_date,
n * cint(d.frequency_of_depreciation))

depreciation_amount, days, months = get_pro_rata_amt(d,
depreciation_amount, days, months = self.get_pro_rata_amt(d,
depreciation_amount, schedule_date, to_date)

monthly_schedule_date = add_months(schedule_date, 1)
Expand Down Expand Up @@ -365,24 +364,6 @@ def set_accumulated_depreciation(self, ignore_booked_entry = False):
def get_value_after_depreciation(self, idx):
return flt(self.get('finance_books')[cint(idx)-1].value_after_depreciation)

def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row):
precision = self.precision("gross_purchase_amount")

if row.depreciation_method in ("Straight Line", "Manual"):
depreciation_left = (cint(row.total_number_of_depreciations) - cint(self.number_of_depreciations_booked))

if not depreciation_left:
frappe.msgprint(_("All the depreciations has been booked"))
depreciation_amount = flt(row.expected_value_after_useful_life)
return depreciation_amount

depreciation_amount = (flt(row.value_after_depreciation) -
flt(row.expected_value_after_useful_life)) / depreciation_left
else:
depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100), precision)

return depreciation_amount

def validate_expected_value_after_useful_life(self):
for row in self.get('finance_books'):
accumulated_depreciation_after_full_schedule = [d.accumulated_depreciation_amount
Expand Down Expand Up @@ -575,6 +556,13 @@ def get_depreciation_rate(self, args, on_validate=False):

return 100 * (1 - flt(depreciation_rate, float_precision))

def get_pro_rata_amt(self, row, depreciation_amount, from_date, to_date):
days = date_diff(to_date, from_date)
months = month_diff(to_date, from_date)
total_days = get_total_days(to_date, row.frequency_of_depreciation)

return (depreciation_amount * flt(days)) / flt(total_days), days, months

def update_maintenance_status():
assets = frappe.get_all(
"Asset", filters={"docstatus": 1, "maintenance_required": 1}
Expand Down Expand Up @@ -758,15 +746,20 @@ def make_asset_movement(assets, purpose=None):
def is_cwip_accounting_enabled(asset_category):
return cint(frappe.db.get_value("Asset Category", asset_category, "enable_cwip_accounting"))

def get_pro_rata_amt(row, depreciation_amount, from_date, to_date):
days = date_diff(to_date, from_date)
months = month_diff(to_date, from_date)
total_days = get_total_days(to_date, row.frequency_of_depreciation)

return (depreciation_amount * flt(days)) / flt(total_days), days, months

def get_total_days(date, frequency):
period_start_date = add_months(date,
cint(frequency) * -1)

return date_diff(date, period_start_date)

@erpnext.allow_regional
def get_depreciation_amount(asset, depreciable_value, row):
depreciation_left = flt(row.total_number_of_depreciations) - flt(asset.number_of_depreciations_booked)

if row.depreciation_method in ("Straight Line", "Manual"):
depreciation_amount = (flt(row.value_after_depreciation) -
flt(row.expected_value_after_useful_life)) / depreciation_left
else:
depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100))

return depreciation_amount
39 changes: 39 additions & 0 deletions erpnext/assets/doctype/asset/test_asset.py
Expand Up @@ -635,6 +635,45 @@ def test_asset_cwip_toggling_cases(self):
frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc)
frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", cwip_acc)

def test_discounted_wdv_depreciation_rate_for_indian_region(self):
# set indian company
company_flag = frappe.flags.company
frappe.flags.company = "_Test Company"

pr = make_purchase_receipt(item_code="Macbook Pro",
qty=1, rate=8000.0, location="Test Location")

asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
asset = frappe.get_doc('Asset', asset_name)
asset.calculate_depreciation = 1
asset.available_for_use_date = '2030-06-12'
asset.purchase_date = '2030-01-01'
asset.append("finance_books", {
"expected_value_after_useful_life": 1000,
"depreciation_method": "Written Down Value",
"total_number_of_depreciations": 3,
"frequency_of_depreciation": 12,
"depreciation_start_date": "2030-12-31"
})
asset.save(ignore_permissions=True)

self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0)

expected_schedules = [
["2030-12-31", 1106.85, 1106.85],
["2031-12-31", 3446.58, 4553.43],
["2032-12-31", 1723.29, 6276.72],
["2033-06-12", 723.28, 7000.00]
]

schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)]
for d in asset.get("schedules")]

self.assertEqual(schedules, expected_schedules)

# reset indian company
frappe.flags.company = company_flag

def create_asset_data():
if not frappe.db.exists("Asset Category", "Computers"):
create_asset_category()
Expand Down
3 changes: 2 additions & 1 deletion erpnext/hooks.py
Expand Up @@ -426,7 +426,8 @@
'erpnext.hr.utils.calculate_annual_eligible_hra_exemption': 'erpnext.regional.india.utils.calculate_annual_eligible_hra_exemption',
'erpnext.hr.utils.calculate_hra_exemption_for_period': 'erpnext.regional.india.utils.calculate_hra_exemption_for_period',
'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_regional_gl_entries': 'erpnext.regional.india.utils.make_regional_gl_entries',
'erpnext.controllers.accounts_controller.validate_einvoice_fields': 'erpnext.regional.india.e_invoice.utils.validate_einvoice_fields'
'erpnext.controllers.accounts_controller.validate_einvoice_fields': 'erpnext.regional.india.e_invoice.utils.validate_einvoice_fields',
'erpnext.assets.doctype.asset.asset.get_depreciation_amount': 'erpnext.regional.india.utils.get_depreciation_amount'
},
'United Arab Emirates': {
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.united_arab_emirates.utils.update_itemised_tax_data',
Expand Down
21 changes: 21 additions & 0 deletions erpnext/regional/india/utils.py
Expand Up @@ -879,3 +879,24 @@ def update_taxable_values(doc, method):
if total_charges != additional_taxes:
diff = additional_taxes - total_charges
doc.get('items')[item_count - 1].taxable_value += diff

def get_depreciation_amount(asset, depreciable_value, row):
depreciation_left = flt(row.total_number_of_depreciations) - flt(asset.number_of_depreciations_booked)

if row.depreciation_method in ("Straight Line", "Manual"):
depreciation_amount = (flt(row.value_after_depreciation) -
flt(row.expected_value_after_useful_life)) / depreciation_left
else:
rate_of_depreciation = row.rate_of_depreciation
# if its the first depreciation
if depreciable_value == asset.gross_purchase_amount:
# as per IT act, if the asset is purchased in the 2nd half of fiscal year, then rate is divided by 2
diff = date_diff(asset.available_for_use_date, row.depreciation_start_date)
if diff <= 180:
rate_of_depreciation = rate_of_depreciation / 2
frappe.msgprint(
_('As per IT Act, the rate of depreciation for the first depreciation entry is reduced by 50%.'))

depreciation_amount = flt(depreciable_value * (flt(rate_of_depreciation) / 100))

return depreciation_amount

0 comments on commit 9226cd3

Please sign in to comment.