fix: backport of #32226
This commit is contained in:
@@ -7,17 +7,7 @@ from frappe import _, msgprint, throw
|
|||||||
from frappe.contacts.doctype.address.address import get_address_display
|
from frappe.contacts.doctype.address.address import get_address_display
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
from frappe.model.utils import get_fetch_values
|
from frappe.model.utils import get_fetch_values
|
||||||
from frappe.utils import (
|
from frappe.utils import add_days, cint, cstr, flt, formatdate, get_link_to_form, getdate, nowdate
|
||||||
add_days,
|
|
||||||
add_months,
|
|
||||||
cint,
|
|
||||||
cstr,
|
|
||||||
flt,
|
|
||||||
formatdate,
|
|
||||||
get_link_to_form,
|
|
||||||
getdate,
|
|
||||||
nowdate,
|
|
||||||
)
|
|
||||||
from six import iteritems
|
from six import iteritems
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
@@ -33,10 +23,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.party import get_due_date, get_party_account, get_party_details
|
||||||
from erpnext.accounts.utils import get_account_currency
|
from erpnext.accounts.utils import get_account_currency
|
||||||
from erpnext.assets.doctype.asset.depreciation import (
|
from erpnext.assets.doctype.asset.depreciation import (
|
||||||
|
depreciate_asset,
|
||||||
get_disposal_account_and_cost_center,
|
get_disposal_account_and_cost_center,
|
||||||
get_gl_entries_on_asset_disposal,
|
get_gl_entries_on_asset_disposal,
|
||||||
get_gl_entries_on_asset_regain,
|
get_gl_entries_on_asset_regain,
|
||||||
make_depreciation_entry,
|
reset_depreciation_schedule,
|
||||||
|
reverse_depreciation_entry_made_after_disposal,
|
||||||
)
|
)
|
||||||
from erpnext.controllers.accounts_controller import validate_account_head
|
from erpnext.controllers.accounts_controller import validate_account_head
|
||||||
from erpnext.controllers.selling_controller import SellingController
|
from erpnext.controllers.selling_controller import SellingController
|
||||||
@@ -1114,18 +1106,20 @@ class SalesInvoice(SellingController):
|
|||||||
asset = self.get_asset(item)
|
asset = self.get_asset(item)
|
||||||
|
|
||||||
if self.is_return:
|
if self.is_return:
|
||||||
if asset.calculate_depreciation:
|
|
||||||
self.reverse_depreciation_entry_made_after_sale(asset)
|
|
||||||
self.reset_depreciation_schedule(asset)
|
|
||||||
|
|
||||||
fixed_asset_gl_entries = get_gl_entries_on_asset_regain(
|
fixed_asset_gl_entries = get_gl_entries_on_asset_regain(
|
||||||
asset, item.base_net_amount, item.finance_book
|
asset, item.base_net_amount, item.finance_book
|
||||||
)
|
)
|
||||||
asset.db_set("disposal_date", None)
|
asset.db_set("disposal_date", None)
|
||||||
|
|
||||||
|
if asset.calculate_depreciation:
|
||||||
|
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:
|
else:
|
||||||
if asset.calculate_depreciation:
|
if asset.calculate_depreciation:
|
||||||
self.depreciate_asset(asset)
|
depreciate_asset(asset, self.posting_date)
|
||||||
|
asset.reload()
|
||||||
|
|
||||||
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(
|
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(
|
||||||
asset, item.base_net_amount, item.finance_book
|
asset, item.base_net_amount, item.finance_book
|
||||||
@@ -1193,95 +1187,6 @@ class SalesInvoice(SellingController):
|
|||||||
_("Select finance book for the item {0} at row {1}").format(item.item_code, item.idx)
|
_("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_sale=self.posting_date)
|
|
||||||
asset.save()
|
|
||||||
|
|
||||||
make_depreciation_entry(asset.name, self.posting_date)
|
|
||||||
asset.load_from_db()
|
|
||||||
|
|
||||||
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()
|
|
||||||
asset.load_from_db()
|
|
||||||
|
|
||||||
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_sale(self, asset):
|
|
||||||
from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry
|
|
||||||
|
|
||||||
posting_date_of_original_invoice = self.get_posting_date_of_sales_invoice()
|
|
||||||
|
|
||||||
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_invoice:
|
|
||||||
if not self.sale_was_made_on_original_schedule_date(
|
|
||||||
asset, schedule, row, posting_date_of_original_invoice
|
|
||||||
) or self.sale_happens_in_the_future(posting_date_of_original_invoice):
|
|
||||||
|
|
||||||
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
|
|
||||||
depreciation_amount = self.get_depreciation_amount_in_je(reverse_journal_entry)
|
|
||||||
asset.finance_books[0].value_after_depreciation += depreciation_amount
|
|
||||||
asset.save()
|
|
||||||
|
|
||||||
def get_posting_date_of_sales_invoice(self):
|
|
||||||
return frappe.db.get_value("Sales Invoice", self.return_against, "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 sale_was_made_on_original_schedule_date(
|
|
||||||
self, asset, schedule, row, posting_date_of_original_invoice
|
|
||||||
):
|
|
||||||
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_original_invoice:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def sale_happens_in_the_future(self, posting_date_of_original_invoice):
|
|
||||||
if posting_date_of_original_invoice > getdate():
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_depreciation_amount_in_je(self, journal_entry):
|
|
||||||
if journal_entry.accounts[0].debit_in_account_currency:
|
|
||||||
return journal_entry.accounts[0].debit_in_account_currency
|
|
||||||
else:
|
|
||||||
return journal_entry.accounts[0].credit_in_account_currency
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def enable_discount_accounting(self):
|
def enable_discount_accounting(self):
|
||||||
if not hasattr(self, "_enable_discount_accounting"):
|
if not hasattr(self, "_enable_discount_accounting"):
|
||||||
|
|||||||
@@ -4,12 +4,13 @@
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import cint, flt, get_link_to_form, getdate, today
|
from frappe.utils import add_months, cint, flt, get_link_to_form, getdate, nowdate, today
|
||||||
from frappe.utils.user import get_users_with_role
|
from frappe.utils.user import get_users_with_role
|
||||||
|
|
||||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||||
get_checks_for_pl_and_bs_accounts,
|
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):
|
def post_depreciation_entries(date=None):
|
||||||
@@ -247,6 +248,11 @@ def scrap_asset(asset_name):
|
|||||||
_("Asset {0} cannot be scrapped, as it is already {1}").format(asset.name, asset.status)
|
_("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(
|
depreciation_series = frappe.get_cached_value(
|
||||||
"Company", asset.company, "series_for_depreciation_entry"
|
"Company", asset.company, "series_for_depreciation_entry"
|
||||||
)
|
)
|
||||||
@@ -254,7 +260,7 @@ def scrap_asset(asset_name):
|
|||||||
je = frappe.new_doc("Journal Entry")
|
je = frappe.new_doc("Journal Entry")
|
||||||
je.voucher_type = "Journal Entry"
|
je.voucher_type = "Journal Entry"
|
||||||
je.naming_series = depreciation_series
|
je.naming_series = depreciation_series
|
||||||
je.posting_date = today()
|
je.posting_date = date
|
||||||
je.company = asset.company
|
je.company = asset.company
|
||||||
je.remark = "Scrap Entry for asset {0}".format(asset_name)
|
je.remark = "Scrap Entry for asset {0}".format(asset_name)
|
||||||
|
|
||||||
@@ -265,7 +271,7 @@ def scrap_asset(asset_name):
|
|||||||
je.flags.ignore_permissions = True
|
je.flags.ignore_permissions = True
|
||||||
je.submit()
|
je.submit()
|
||||||
|
|
||||||
frappe.db.set_value("Asset", asset_name, "disposal_date", today())
|
frappe.db.set_value("Asset", asset_name, "disposal_date", date)
|
||||||
frappe.db.set_value("Asset", asset_name, "journal_entry_for_scrap", je.name)
|
frappe.db.set_value("Asset", asset_name, "journal_entry_for_scrap", je.name)
|
||||||
asset.set_status("Scrapped")
|
asset.set_status("Scrapped")
|
||||||
|
|
||||||
@@ -276,6 +282,9 @@ def scrap_asset(asset_name):
|
|||||||
def restore_asset(asset_name):
|
def restore_asset(asset_name):
|
||||||
asset = frappe.get_doc("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
|
je = asset.journal_entry_for_scrap
|
||||||
|
|
||||||
asset.db_set("disposal_date", None)
|
asset.db_set("disposal_date", None)
|
||||||
@@ -286,6 +295,91 @@ def restore_asset(asset_name):
|
|||||||
asset.set_status()
|
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
|
||||||
|
depreciation_amount = get_depreciation_amount_in_je(reverse_journal_entry)
|
||||||
|
asset.finance_books[0].value_after_depreciation += depreciation_amount
|
||||||
|
asset.save()
|
||||||
|
|
||||||
|
|
||||||
|
def get_depreciation_amount_in_je(journal_entry):
|
||||||
|
if journal_entry.accounts[0].debit_in_account_currency:
|
||||||
|
return journal_entry.accounts[0].debit_in_account_currency
|
||||||
|
else:
|
||||||
|
return journal_entry.accounts[0].credit_in_account_currency
|
||||||
|
|
||||||
|
|
||||||
|
# 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):
|
def get_gl_entries_on_asset_regain(asset, selling_amount=0, finance_book=None):
|
||||||
(
|
(
|
||||||
fixed_asset_account,
|
fixed_asset_account,
|
||||||
|
|||||||
@@ -4,7 +4,16 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import add_days, add_months, cstr, flt, get_last_day, getdate, nowdate
|
from frappe.utils import (
|
||||||
|
add_days,
|
||||||
|
add_months,
|
||||||
|
cstr,
|
||||||
|
flt,
|
||||||
|
get_first_day,
|
||||||
|
get_last_day,
|
||||||
|
getdate,
|
||||||
|
nowdate,
|
||||||
|
)
|
||||||
|
|
||||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||||
from erpnext.assets.doctype.asset.asset import make_sales_invoice, update_maintenance_status
|
from erpnext.assets.doctype.asset.asset import make_sales_invoice, update_maintenance_status
|
||||||
@@ -153,28 +162,59 @@ class TestAsset(AssetSetup):
|
|||||||
self.assertEqual(doc.items[0].is_fixed_asset, 1)
|
self.assertEqual(doc.items[0].is_fixed_asset, 1)
|
||||||
|
|
||||||
def test_scrap_asset(self):
|
def test_scrap_asset(self):
|
||||||
|
date = nowdate()
|
||||||
|
purchase_date = add_months(get_first_day(date), -2)
|
||||||
|
|
||||||
asset = create_asset(
|
asset = create_asset(
|
||||||
calculate_depreciation=1,
|
calculate_depreciation=1,
|
||||||
available_for_use_date="2020-01-01",
|
available_for_use_date=purchase_date,
|
||||||
purchase_date="2020-01-01",
|
purchase_date=purchase_date,
|
||||||
expected_value_after_useful_life=10000,
|
expected_value_after_useful_life=10000,
|
||||||
total_number_of_depreciations=10,
|
total_number_of_depreciations=10,
|
||||||
frequency_of_depreciation=1,
|
frequency_of_depreciation=1,
|
||||||
submit=1,
|
submit=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
post_depreciation_entries(date=add_months("2020-01-01", 4))
|
post_depreciation_entries(date=add_months(purchase_date, 2))
|
||||||
|
asset.load_from_db()
|
||||||
|
|
||||||
|
accumulated_depr_amount = flt(
|
||||||
|
asset.gross_purchase_amount - asset.finance_books[0].value_after_depreciation,
|
||||||
|
asset.precision("gross_purchase_amount"),
|
||||||
|
)
|
||||||
|
self.assertEquals(accumulated_depr_amount, 18000.0)
|
||||||
|
|
||||||
scrap_asset(asset.name)
|
scrap_asset(asset.name)
|
||||||
|
|
||||||
asset.load_from_db()
|
asset.load_from_db()
|
||||||
|
|
||||||
|
accumulated_depr_amount = flt(
|
||||||
|
asset.gross_purchase_amount - asset.finance_books[0].value_after_depreciation,
|
||||||
|
asset.precision("gross_purchase_amount"),
|
||||||
|
)
|
||||||
|
pro_rata_amount, _, _ = asset.get_pro_rata_amt(
|
||||||
|
asset.finance_books[0], 9000, get_last_day(add_months(purchase_date, 1)), date
|
||||||
|
)
|
||||||
|
pro_rata_amount = flt(pro_rata_amount, asset.precision("gross_purchase_amount"))
|
||||||
|
self.assertEquals(
|
||||||
|
accumulated_depr_amount,
|
||||||
|
flt(18000.0 + pro_rata_amount, asset.precision("gross_purchase_amount")),
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(asset.status, "Scrapped")
|
self.assertEqual(asset.status, "Scrapped")
|
||||||
self.assertTrue(asset.journal_entry_for_scrap)
|
self.assertTrue(asset.journal_entry_for_scrap)
|
||||||
|
|
||||||
expected_gle = (
|
expected_gle = (
|
||||||
("_Test Accumulated Depreciations - _TC", 36000.0, 0.0),
|
(
|
||||||
|
"_Test Accumulated Depreciations - _TC",
|
||||||
|
flt(18000.0 + pro_rata_amount, asset.precision("gross_purchase_amount")),
|
||||||
|
0.0,
|
||||||
|
),
|
||||||
("_Test Fixed Asset - _TC", 0.0, 100000.0),
|
("_Test Fixed Asset - _TC", 0.0, 100000.0),
|
||||||
("_Test Gain/Loss on Asset Disposal - _TC", 64000.0, 0.0),
|
(
|
||||||
|
"_Test Gain/Loss on Asset Disposal - _TC",
|
||||||
|
flt(82000.0 - pro_rata_amount, asset.precision("gross_purchase_amount")),
|
||||||
|
0.0,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
gle = frappe.db.sql(
|
gle = frappe.db.sql(
|
||||||
@@ -183,7 +223,7 @@ class TestAsset(AssetSetup):
|
|||||||
order by account""",
|
order by account""",
|
||||||
asset.journal_entry_for_scrap,
|
asset.journal_entry_for_scrap,
|
||||||
)
|
)
|
||||||
self.assertEqual(gle, expected_gle)
|
self.assertSequenceEqual(gle, expected_gle)
|
||||||
|
|
||||||
restore_asset(asset.name)
|
restore_asset(asset.name)
|
||||||
|
|
||||||
@@ -191,34 +231,57 @@ class TestAsset(AssetSetup):
|
|||||||
self.assertFalse(asset.journal_entry_for_scrap)
|
self.assertFalse(asset.journal_entry_for_scrap)
|
||||||
self.assertEqual(asset.status, "Partially Depreciated")
|
self.assertEqual(asset.status, "Partially Depreciated")
|
||||||
|
|
||||||
|
accumulated_depr_amount = flt(
|
||||||
|
asset.gross_purchase_amount - asset.finance_books[0].value_after_depreciation,
|
||||||
|
asset.precision("gross_purchase_amount"),
|
||||||
|
)
|
||||||
|
this_month_depr_amount = 9000.0 if is_last_day_of_the_month(date) else 0
|
||||||
|
|
||||||
|
self.assertEquals(accumulated_depr_amount, 18000.0 + this_month_depr_amount)
|
||||||
|
|
||||||
def test_gle_made_by_asset_sale(self):
|
def test_gle_made_by_asset_sale(self):
|
||||||
|
date = nowdate()
|
||||||
|
purchase_date = add_months(get_first_day(date), -2)
|
||||||
|
|
||||||
asset = create_asset(
|
asset = create_asset(
|
||||||
calculate_depreciation=1,
|
calculate_depreciation=1,
|
||||||
available_for_use_date="2020-06-06",
|
available_for_use_date=purchase_date,
|
||||||
purchase_date="2020-01-01",
|
purchase_date=purchase_date,
|
||||||
expected_value_after_useful_life=10000,
|
expected_value_after_useful_life=10000,
|
||||||
total_number_of_depreciations=3,
|
total_number_of_depreciations=10,
|
||||||
frequency_of_depreciation=10,
|
frequency_of_depreciation=1,
|
||||||
depreciation_start_date="2020-12-31",
|
|
||||||
submit=1,
|
submit=1,
|
||||||
)
|
)
|
||||||
post_depreciation_entries(date="2021-01-01")
|
|
||||||
|
post_depreciation_entries(date=add_months(purchase_date, 2))
|
||||||
|
|
||||||
si = make_sales_invoice(asset=asset.name, item_code="Macbook Pro", company="_Test Company")
|
si = make_sales_invoice(asset=asset.name, item_code="Macbook Pro", company="_Test Company")
|
||||||
si.customer = "_Test Customer"
|
si.customer = "_Test Customer"
|
||||||
si.set_posting_time = 1
|
si.due_date = nowdate()
|
||||||
si.posting_date = "2021-10-31"
|
si.get("items")[0].rate = 25000
|
||||||
si.due_date = "2021-10-31"
|
si.insert()
|
||||||
si.get("items")[0].rate = 75000
|
|
||||||
si.submit()
|
si.submit()
|
||||||
|
|
||||||
self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold")
|
self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold")
|
||||||
|
|
||||||
|
pro_rata_amount, _, _ = asset.get_pro_rata_amt(
|
||||||
|
asset.finance_books[0], 9000, get_last_day(add_months(purchase_date, 1)), date
|
||||||
|
)
|
||||||
|
pro_rata_amount = flt(pro_rata_amount, asset.precision("gross_purchase_amount"))
|
||||||
|
|
||||||
expected_gle = (
|
expected_gle = (
|
||||||
("_Test Accumulated Depreciations - _TC", 50490.2, 0.0),
|
(
|
||||||
|
"_Test Accumulated Depreciations - _TC",
|
||||||
|
flt(18000.0 + pro_rata_amount, asset.precision("gross_purchase_amount")),
|
||||||
|
0.0,
|
||||||
|
),
|
||||||
("_Test Fixed Asset - _TC", 0.0, 100000.0),
|
("_Test Fixed Asset - _TC", 0.0, 100000.0),
|
||||||
("_Test Gain/Loss on Asset Disposal - _TC", 0.0, 25490.2),
|
(
|
||||||
("Debtors - _TC", 75000.0, 0.0),
|
"_Test Gain/Loss on Asset Disposal - _TC",
|
||||||
|
flt(57000.0 - pro_rata_amount, asset.precision("gross_purchase_amount")),
|
||||||
|
0.0,
|
||||||
|
),
|
||||||
|
("Debtors - _TC", 25000.0, 0.0),
|
||||||
)
|
)
|
||||||
|
|
||||||
gle = frappe.db.sql(
|
gle = frappe.db.sql(
|
||||||
@@ -228,14 +291,9 @@ class TestAsset(AssetSetup):
|
|||||||
si.name,
|
si.name,
|
||||||
)
|
)
|
||||||
|
|
||||||
for i, gle_entry in enumerate(gle):
|
self.assertSequenceEqual(gle, expected_gle)
|
||||||
self.assertEqual(gle_entry[0], expected_gle[i][0])
|
|
||||||
self.assertEqual(flt(gle_entry[1], 1), flt(expected_gle[i][1], 1))
|
|
||||||
self.assertEqual(flt(gle_entry[2], 1), flt(expected_gle[i][2], 1))
|
|
||||||
|
|
||||||
si.load_from_db()
|
|
||||||
si.cancel()
|
si.cancel()
|
||||||
|
|
||||||
self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated")
|
self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated")
|
||||||
|
|
||||||
def test_asset_with_maintenance_required_status_after_sale(self):
|
def test_asset_with_maintenance_required_status_after_sale(self):
|
||||||
@@ -1471,3 +1529,9 @@ def set_depreciation_settings_in_company():
|
|||||||
|
|
||||||
def enable_cwip_accounting(asset_category, enable=1):
|
def enable_cwip_accounting(asset_category, enable=1):
|
||||||
frappe.db.set_value("Asset Category", asset_category, "enable_cwip_accounting", enable)
|
frappe.db.set_value("Asset Category", asset_category, "enable_cwip_accounting", enable)
|
||||||
|
|
||||||
|
|
||||||
|
def is_last_day_of_the_month(dt):
|
||||||
|
last_day_of_the_month = get_last_day(dt)
|
||||||
|
|
||||||
|
return getdate(dt) == getdate(last_day_of_the_month)
|
||||||
|
|||||||
Reference in New Issue
Block a user