fix: calculate depreciation properly on asset sale entry and scrap entry

This commit is contained in:
anandbaburajan 2022-09-15 13:15:34 +05:30
parent 87160c8d2f
commit ff5cad1cd6
3 changed files with 97 additions and 90 deletions

View File

@ -22,9 +22,12 @@ from erpnext.accounts.general_ledger import get_round_off_account_and_cost_cente
from erpnext.accounts.party import get_due_date, get_party_account, get_party_details
from erpnext.accounts.utils import get_account_currency
from erpnext.assets.doctype.asset.depreciation import (
depreciate_asset,
get_disposal_account_and_cost_center,
get_gl_entries_on_asset_disposal,
get_gl_entries_on_asset_regain,
reset_depreciation_schedule,
reverse_depreciation_entry_made_after_disposal,
)
from erpnext.controllers.accounts_controller import validate_account_head
from erpnext.controllers.selling_controller import SellingController
@ -1086,18 +1089,20 @@ class SalesInvoice(SellingController):
asset.db_set("disposal_date", None)
if asset.calculate_depreciation:
self.reverse_depreciation_entry_made_after_disposal(asset)
self.reset_depreciation_schedule(asset)
posting_date = frappe.db.get_value("Sales Invoice", self.return_against, "posting_date")
reverse_depreciation_entry_made_after_disposal(asset, posting_date)
reset_depreciation_schedule(asset, self.posting_date)
else:
if asset.calculate_depreciation:
depreciate_asset(asset, self.posting_date)
asset.reload()
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(
asset, item.base_net_amount, item.finance_book
)
asset.db_set("disposal_date", self.posting_date)
if asset.calculate_depreciation:
self.depreciate_asset(asset)
for gle in fixed_asset_gl_entries:
gle["against"] = self.customer
gl_entries.append(self.get_gl_dict(gle, item=item))

View File

@ -4,11 +4,12 @@
import frappe
from frappe import _
from frappe.utils import cint, flt, getdate, today
from frappe.utils import add_months, cint, flt, getdate, nowdate, today
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_checks_for_pl_and_bs_accounts,
)
from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry
def post_depreciation_entries(date=None, commit=True):
@ -196,6 +197,11 @@ def scrap_asset(asset_name):
_("Asset {0} cannot be scrapped, as it is already {1}").format(asset.name, asset.status)
)
date = today()
depreciate_asset(asset, date)
asset.reload()
depreciation_series = frappe.get_cached_value(
"Company", asset.company, "series_for_depreciation_entry"
)
@ -203,7 +209,7 @@ def scrap_asset(asset_name):
je = frappe.new_doc("Journal Entry")
je.voucher_type = "Journal Entry"
je.naming_series = depreciation_series
je.posting_date = today()
je.posting_date = date
je.company = asset.company
je.remark = "Scrap Entry for asset {0}".format(asset_name)
@ -225,6 +231,9 @@ def scrap_asset(asset_name):
def restore_asset(asset_name):
asset = frappe.get_doc("Asset", asset_name)
reverse_depreciation_entry_made_after_disposal(asset, asset.disposal_date)
reset_depreciation_schedule(asset, asset.disposal_date)
je = asset.journal_entry_for_scrap
asset.db_set("disposal_date", None)
@ -235,6 +244,82 @@ def restore_asset(asset_name):
asset.set_status()
def depreciate_asset(asset, date):
asset.flags.ignore_validate_update_after_submit = True
asset.prepare_depreciation_data(date_of_disposal=date)
asset.save()
make_depreciation_entry(asset.name, date)
def reset_depreciation_schedule(asset, date):
asset.flags.ignore_validate_update_after_submit = True
# recreate original depreciation schedule of the asset
asset.prepare_depreciation_data(date_of_return=date)
modify_depreciation_schedule_for_asset_repairs(asset)
asset.save()
def modify_depreciation_schedule_for_asset_repairs(asset):
asset_repairs = frappe.get_all(
"Asset Repair", filters={"asset": asset.name}, fields=["name", "increase_in_asset_life"]
)
for repair in asset_repairs:
if repair.increase_in_asset_life:
asset_repair = frappe.get_doc("Asset Repair", repair.name)
asset_repair.modify_depreciation_schedule()
asset.prepare_depreciation_data()
def reverse_depreciation_entry_made_after_disposal(asset, date):
row = -1
finance_book = asset.get("schedules")[0].get("finance_book")
for schedule in asset.get("schedules"):
if schedule.finance_book != finance_book:
row = 0
finance_book = schedule.finance_book
else:
row += 1
if schedule.schedule_date == date:
if not disposal_was_made_on_original_schedule_date(
asset, schedule, row, date
) or disposal_happens_in_the_future(date):
reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry)
reverse_journal_entry.posting_date = nowdate()
frappe.flags.is_reverse_depr_entry = True
reverse_journal_entry.submit()
frappe.flags.is_reverse_depr_entry = False
asset.flags.ignore_validate_update_after_submit = True
schedule.journal_entry = None
asset.save()
# if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone
def disposal_was_made_on_original_schedule_date(asset, schedule, row, posting_date_of_disposal):
for finance_book in asset.get("finance_books"):
if schedule.finance_book == finance_book.finance_book:
orginal_schedule_date = add_months(
finance_book.depreciation_start_date, row * cint(finance_book.frequency_of_depreciation)
)
if orginal_schedule_date == posting_date_of_disposal:
return True
return False
def disposal_happens_in_the_future(posting_date_of_disposal):
if posting_date_of_disposal > getdate():
return True
return False
def get_gl_entries_on_asset_regain(asset, selling_amount=0, finance_book=None):
(
fixed_asset_account,

View File

@ -38,7 +38,6 @@ from erpnext.accounts.party import (
validate_party_frozen_disabled,
)
from erpnext.accounts.utils import get_account_currency, get_fiscal_years, validate_fiscal_year
from erpnext.assets.doctype.asset.depreciation import make_depreciation_entry
from erpnext.buying.utils import update_last_purchase_rate
from erpnext.controllers.print_settings import (
set_print_templates_for_item_table,
@ -1886,88 +1885,6 @@ class AccountsController(TransactionBase):
_("Select finance book for the item {0} at row {1}").format(item.item_code, item.idx)
)
def depreciate_asset(self, asset):
asset.flags.ignore_validate_update_after_submit = True
asset.prepare_depreciation_data(date_of_disposal=self.posting_date)
asset.save()
make_depreciation_entry(asset.name, self.posting_date)
def reset_depreciation_schedule(self, asset):
asset.flags.ignore_validate_update_after_submit = True
# recreate original depreciation schedule of the asset
asset.prepare_depreciation_data(date_of_return=self.posting_date)
self.modify_depreciation_schedule_for_asset_repairs(asset)
asset.save()
def modify_depreciation_schedule_for_asset_repairs(self, asset):
asset_repairs = frappe.get_all(
"Asset Repair", filters={"asset": asset.name}, fields=["name", "increase_in_asset_life"]
)
for repair in asset_repairs:
if repair.increase_in_asset_life:
asset_repair = frappe.get_doc("Asset Repair", repair.name)
asset_repair.modify_depreciation_schedule()
asset.prepare_depreciation_data()
def reverse_depreciation_entry_made_after_disposal(self, asset):
from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry
posting_date_of_original_disposal = self.get_posting_date_of_disposal_entry()
row = -1
finance_book = asset.get("schedules")[0].get("finance_book")
for schedule in asset.get("schedules"):
if schedule.finance_book != finance_book:
row = 0
finance_book = schedule.finance_book
else:
row += 1
if schedule.schedule_date == posting_date_of_original_disposal:
if not self.disposal_was_made_on_original_schedule_date(
asset, schedule, row, posting_date_of_original_disposal
) or self.disposal_happens_in_the_future(posting_date_of_original_disposal):
reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry)
reverse_journal_entry.posting_date = nowdate()
frappe.flags.is_reverse_depr_entry = True
reverse_journal_entry.submit()
frappe.flags.is_reverse_depr_entry = False
asset.flags.ignore_validate_update_after_submit = True
schedule.journal_entry = None
asset.save()
def get_posting_date_of_disposal_entry(self):
if self.doctype == "Sales Invoice" and self.return_against:
return frappe.db.get_value("Sales Invoice", self.return_against, "posting_date")
else:
return self.posting_date
# if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone
def disposal_was_made_on_original_schedule_date(
self, asset, schedule, row, posting_date_of_disposal
):
for finance_book in asset.get("finance_books"):
if schedule.finance_book == finance_book.finance_book:
orginal_schedule_date = add_months(
finance_book.depreciation_start_date, row * cint(finance_book.frequency_of_depreciation)
)
if orginal_schedule_date == posting_date_of_disposal:
return True
return False
def disposal_happens_in_the_future(self, posting_date_of_disposal):
if posting_date_of_disposal > getdate():
return True
return False
@frappe.whitelist()
def get_tax_rate(account_head):