feat(india): reduced rate of depreciation as per IT Act (#25648)
* feat(india): reduced rate of depreciation as per IT Act * refactor: check date difference instead of month difference * feat: add test for regional feature
This commit is contained in:
parent
aa9e172091
commit
9226cd3932
@ -195,8 +195,7 @@ class Asset(AccountsController):
|
|||||||
# If depreciation is already completed (for double declining balance)
|
# If depreciation is already completed (for double declining balance)
|
||||||
if skip_row: continue
|
if skip_row: continue
|
||||||
|
|
||||||
depreciation_amount = self.get_depreciation_amount(value_after_depreciation,
|
depreciation_amount = get_depreciation_amount(self, value_after_depreciation, d)
|
||||||
d.total_number_of_depreciations, d)
|
|
||||||
|
|
||||||
if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1:
|
if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1:
|
||||||
schedule_date = add_months(d.depreciation_start_date,
|
schedule_date = add_months(d.depreciation_start_date,
|
||||||
@ -208,7 +207,7 @@ class Asset(AccountsController):
|
|||||||
|
|
||||||
# For first row
|
# For first row
|
||||||
if has_pro_rata and n==0:
|
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)
|
self.available_for_use_date, d.depreciation_start_date)
|
||||||
|
|
||||||
# For first depr schedule date will be the start date
|
# For first depr schedule date will be the start date
|
||||||
@ -220,7 +219,7 @@ class Asset(AccountsController):
|
|||||||
to_date = add_months(self.available_for_use_date,
|
to_date = add_months(self.available_for_use_date,
|
||||||
n * cint(d.frequency_of_depreciation))
|
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)
|
depreciation_amount, schedule_date, to_date)
|
||||||
|
|
||||||
monthly_schedule_date = add_months(schedule_date, 1)
|
monthly_schedule_date = add_months(schedule_date, 1)
|
||||||
@ -365,24 +364,6 @@ class Asset(AccountsController):
|
|||||||
def get_value_after_depreciation(self, idx):
|
def get_value_after_depreciation(self, idx):
|
||||||
return flt(self.get('finance_books')[cint(idx)-1].value_after_depreciation)
|
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):
|
def validate_expected_value_after_useful_life(self):
|
||||||
for row in self.get('finance_books'):
|
for row in self.get('finance_books'):
|
||||||
accumulated_depreciation_after_full_schedule = [d.accumulated_depreciation_amount
|
accumulated_depreciation_after_full_schedule = [d.accumulated_depreciation_amount
|
||||||
@ -575,6 +556,13 @@ class Asset(AccountsController):
|
|||||||
|
|
||||||
return 100 * (1 - flt(depreciation_rate, float_precision))
|
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():
|
def update_maintenance_status():
|
||||||
assets = frappe.get_all(
|
assets = frappe.get_all(
|
||||||
"Asset", filters={"docstatus": 1, "maintenance_required": 1}
|
"Asset", filters={"docstatus": 1, "maintenance_required": 1}
|
||||||
@ -758,15 +746,20 @@ def make_asset_movement(assets, purpose=None):
|
|||||||
def is_cwip_accounting_enabled(asset_category):
|
def is_cwip_accounting_enabled(asset_category):
|
||||||
return cint(frappe.db.get_value("Asset Category", asset_category, "enable_cwip_accounting"))
|
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):
|
def get_total_days(date, frequency):
|
||||||
period_start_date = add_months(date,
|
period_start_date = add_months(date,
|
||||||
cint(frequency) * -1)
|
cint(frequency) * -1)
|
||||||
|
|
||||||
return date_diff(date, period_start_date)
|
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
|
@ -635,6 +635,45 @@ class TestAsset(unittest.TestCase):
|
|||||||
frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc)
|
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)
|
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():
|
def create_asset_data():
|
||||||
if not frappe.db.exists("Asset Category", "Computers"):
|
if not frappe.db.exists("Asset Category", "Computers"):
|
||||||
create_asset_category()
|
create_asset_category()
|
||||||
|
@ -426,7 +426,8 @@ regional_overrides = {
|
|||||||
'erpnext.hr.utils.calculate_annual_eligible_hra_exemption': 'erpnext.regional.india.utils.calculate_annual_eligible_hra_exemption',
|
'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.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.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': {
|
'United Arab Emirates': {
|
||||||
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.united_arab_emirates.utils.update_itemised_tax_data',
|
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.united_arab_emirates.utils.update_itemised_tax_data',
|
||||||
|
@ -879,3 +879,24 @@ def update_taxable_values(doc, method):
|
|||||||
if total_charges != additional_taxes:
|
if total_charges != additional_taxes:
|
||||||
diff = additional_taxes - total_charges
|
diff = additional_taxes - total_charges
|
||||||
doc.get('items')[item_count - 1].taxable_value += diff
|
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
|
Loading…
Reference in New Issue
Block a user